summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core')
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/README.md120
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/README.md11
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/attr_container.c986
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/attr_container.h596
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/shared_utils.h155
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h101
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.cmake15
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.h13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c493
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_ext_lib_export.c38
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_framework.cmake93
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.c89
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.h65
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/req_resp_api.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/request.c365
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer.c100
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer_api.h36
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/request.h171
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/timer_wasm_app.h71
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.h20
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib.inl14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib_export.c24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/req_resp_native_api.h29
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/request_response.c84
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/runtime_lib.h22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_native_api.h40
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_wrapper.c220
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/wasm_lib.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection.c118
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection_api.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wa-inc/connection.h94
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wasm_app.cmake11
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection.inl9
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_lib.h75
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_native_api.h36
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_wrapper.c61
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.c54
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.h28
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.c103
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.h28
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.c58
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.h28
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.c609
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/wasm_lib.cmake18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_lib_impl.c25
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_mgr.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor.c122
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor_api.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wa-inc/sensor.h94
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wasm_app.cmake11
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.c434
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.h69
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.inl9
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_mgr_ref.c148
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_native_api.h33
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/wasm_lib.cmake14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wa-inc/app_xxx.h8
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wasm_app.cmake16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/native/app_xxx.inl6
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/native/wasm_lib.cmake17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/README.md8
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.c431
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.h86
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.c324
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.h23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_mgr.cmake17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/ble_msg.c115
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/coding_rule.txt15
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.c204
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.h41
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/message.c88
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_config.h23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.c1883
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.h29
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_utils.c230
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.c1743
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.h143
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.c58
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.h21
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/darwin/app_mgr_darwin.c1
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/linux/app_mgr_linux.c46
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c64
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/resource_reg.c211
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.c140
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.h40
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_manager_export.h307
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/host_link.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/module.json52
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/config.h448
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/README.md14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/SConscript33
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.c765
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.h306
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_loader.c3035
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_reloc.h185
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.c2836
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.h571
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_aarch64.c405
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arc.c419
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arm.c376
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_mips.c69
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_riscv.c440
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_thumb.c431
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_32.c152
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_64.c266
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c302
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/LICENSE_NUTTX202
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/NOTICE_NUTTX5
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf.h368
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf32.h161
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf64.h161
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.c154
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.h27
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.c255
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.h29
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/iwasm_aot.cmake40
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/SConscript28
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64.s81
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64_simd.s79
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arc.s69
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm.s75
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm_vfp.s86
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.asm62
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.s64
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.asm62
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.s64
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_general.c114
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.asm27
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.s37
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64.s57
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64_simd.s57
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mips.s74
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_osx_universal.s18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_riscv.S148
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb.s91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb_vfp.s100
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_xtensa.s74
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/iwasm_common.cmake99
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_application.c645
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api.c5227
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api_internal.h241
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.c258
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.h323
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.c759
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.h41
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.c526
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.h81
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.c5475
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.h1010
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.c491
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.h70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.c594
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.h335
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.c2921
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.h383
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_aot_file.c2930
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.c232
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.h35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.c172
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.h35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.c1155
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.h62
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.c939
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.h90
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.c141
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.h24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.c1729
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.h36
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.c1435
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.h110
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.c1248
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.h87
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.c107
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.h27
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.c503
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.h59
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.c267
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.h39
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.c2770
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.h526
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra.cpp360
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.cpp108
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.h17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.cpp289
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.h75
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.cpp510
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.h56
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/iwasm_compl.cmake26
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.c418
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.h92
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.c144
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.h35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.c133
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.h35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.c144
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.h23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.c138
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.h39
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.c157
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.h45
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.c229
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.h43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.c135
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.h27
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.c743
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.h90
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.c388
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.h107
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.c406
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.h91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.c331
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.h49
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.c81
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.h33
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/classic_interpreter.MD5
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/export_function.excalidraw5695
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.excalidraw2643
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.svg16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_exports.svg16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.excalidraw7754
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.svg16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.excalidraw2313
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.svg16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_exports.MD22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_function.MD47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_globals.MD4
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/asmjit_sgx_patch.diff42
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ASMJIT17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ZYDIS23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp9508
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.c345
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.h32
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.c47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.c1318
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.h56
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.c660
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.h73
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.c78
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.h23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.c945
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.h39
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.c1200
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.h92
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.c1707
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.h76
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.c130
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.h25
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.c318
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.h47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.c312
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.h35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/iwasm_fast_jit.cmake97
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.c86
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.c22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.h93
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.c291
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.h162
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.c336
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.h54
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.c2387
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.h508
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.c1427
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.def346
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.h1880
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_regalloc.c862
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.c19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.h136
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/aot_export.h107
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/lib_export.h55
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_c_api.h814
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_export.h1374
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/SConscript30
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/iwasm_interp.cmake29
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm.h797
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp.h96
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_classic.c4315
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_fast.c4021
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.c10131
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.h80
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_mini_loader.c7544
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_opcode.h917
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.c3532
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.h668
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c1433
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h253
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c330
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c876
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript20
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c1331
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h40
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c115
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h48
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h999
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake9
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c1009
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh25
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c49
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c193
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c184
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h126
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c128
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c83
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c94
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c72
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c44
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c97
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c80
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h36
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c1123
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c554
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV66
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI21
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake44
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c1150
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript34
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c2329
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h55
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE7
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE121
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h1508
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h265
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c4072
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h89
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h98
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c98
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h21
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h139
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h100
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h143
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c1351
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h218
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md96
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake41
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h69
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c163
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h51
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c306
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp417
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp45
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt173
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh21
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py16
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py15
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py33
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt1
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c146
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c162
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h52
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h89
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h106
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/LICENSE.md30
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/coap-constants.h194
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/extension/coap_ext.h20
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/lib_coap.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/SConscript33
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_alloc.c794
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc.h168
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc_internal.h306
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_hmu.c91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_kfc.c297
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.c190
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.cmake19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.h55
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/README.md10
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_platform.c71
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_thread.c361
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_time.c12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/platform_internal.h67
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/shared_platform.cmake16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_init.c171
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_internal.h155
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/shared_platform.cmake18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_malloc.c28
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_thread.c454
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_time.c13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/platform_api_freertos.cmake8
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/COPYRIGHT126
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/math.c1681
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/platform_api_math.cmake8
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/platform_api_posix.cmake8
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_malloc.c72
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_memmap.c253
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_socket.c1028
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_thread.c680
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_time.c17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_init.c43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_internal.h109
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/shared_platform.cmake18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_init.c6
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_internal.h6
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/shared_platform.cmake20
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_malloc.c84
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_memmap.c51
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_platform.c252
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_socket.c228
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_thread.c233
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/platform_internal.h115
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/shared_platform.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_init.c43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_internal.h108
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/shared_platform.cmake18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_extension.h1039
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_vmcore.h145
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_common.h204
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/platform_internal.h75
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.c1117
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.h266
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.c532
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.h61
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_platform.c197
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.c91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.h35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_rsrv_mem_mngr.h95
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.c31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.h57
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.c1222
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.h332
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_thread.c212
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.c135
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.h50
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_wamr.edl158
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/shared_platform.cmake38
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/file.c321
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/pthread.c54
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/signal.c11
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/socket.c148
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/time.c44
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_init.c43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_internal.h106
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/shared_platform.cmake18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/nuttx_platform.c259
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/platform_internal.h130
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/shared_platform.cmake14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/platform_internal.h79
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_platform.c81
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_thread.c432
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_time.c34
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/shared_platform.cmake17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/SConscript34
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/platform_internal.h48
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/rtt_platform.c209
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/shared_platform.cmake19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_init.c43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_internal.h102
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/shared_platform.cmake18
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c75
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h138
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c30
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c146
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c541
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c750
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c20
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/platform_internal.h149
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/shared_platform.cmake16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_platform.c223
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_thread.c576
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_time.c12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/SConscript17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.c25
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.h42
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.c163
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.h73
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.c337
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.h168
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.c111
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.h109
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.c107
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.h88
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_platform.h38
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.c256
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.h80
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.c279
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.h126
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.c469
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.h51
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/shared_utils.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/SConscript32
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.c65
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.h28
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.c117
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.h22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/shared_uncommon.cmake11
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/version.h11
545 files changed, 192739 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/README.md
new file mode 100644
index 000000000..d1476fd8b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/README.md
@@ -0,0 +1,120 @@
+# Application framework
+
+By using the WAMR VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some effort.
+
+The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, that are based on the event driven programming model. Here are the supporting API sets by the [WAMR application framework library](../doc/wamr_api.md) :
+
+- Timer, Inter-app communication (request/response and pub/sub), Sensor, Connectivity and data transmission, 2D graphic UI
+
+Browse the folder [core/app-framework](./app-framework) for how to extend the application framework.
+
+
+## Directory structure
+This folder "app-native-shared" 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.
+
+This folder "template" contains a pre-defined directory structure for a framework component. The developers can copy the template folder to create new components to the application framework.
+
+Every other subfolder is framework component. Each component contains two library parts: **app and native**.
+
+- The "base" component provide timer API and inter-app communication support. It must be enabled if other components are selected.
+- Under the "app" folder of a component, the subfolder "wa_inc" holds all header files that should be included by the WASM applications
+
+## Application framework basic model
+
+The app framework is built on top of two fundamental operations:
+
+- [Native calls into WASM function](../../doc/embed_wamr.md)
+
+- [WASM app calls into native API](../../doc/export_native_api.md)
+
+Asynchronized programming model is supported for WASM applications
+
+- Every WASM app has its own sandbox and thread
+
+- Queue and messaging
+
+<img src="../../doc/pics/app_framework.PNG" style="zoom:67%;" />
+
+
+
+## Customized building of app framework
+
+A component can be compilation configurable to the runtime. The wamr SDK tool "build_sdk.sh" supports menu config to select app components for building a customized runtime.
+
+A number of CMAKE variables are defined to control build of framework and components. You can create a cmake file for defining these variables and include it in the CMakeList.txt for your software, or pass it in "-x" argument when run the [build_sdk.sh](../../wamr-sdk/build_sdk.sh) for building the runtime SDK.
+
+```cmake
+set (WAMR_BUILD_APP_FRAMEWORK 1)
+set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE)
+```
+
+Variables:
+
+- **WAMR_BUILD_APP_FRAMEWORK**: enable the application framework
+- **WAMR_BUILD_APP_LIST**: the selected components to be built into the final runtime
+
+
+
+The configuration file can be generated through the wamr-sdk menu config:
+
+```bash
+cd wamr-sdk
+./build_sdk -n [profile] -i
+```
+
+
+
+## Create new components
+
+Generally you should follow following steps to create a new component:
+
+- Copy the “template” for creating a new folder
+
+- Implement the app part
+
+ - If your component exports native function to WASM, ensure your created a header file under app for declaring the function prototype.
+ - If you component provides header files for the WASM applications to include, ensure it is placed under subfolder "wa_inc".
+
+- Implement the native part
+
+ - If your native function is exported to WASM, you need to create an inl file for the registration. It can be any file name, assuming the file name is "my_component.inl" here:
+
+ ```c
+ //use right signature for your functions
+ EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_1, "(i*~)i"),
+ EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_2, "(i)i"),
+ ```
+
+ - Ensure "wasm_lib.cmake" is provided as it will be included by the WAMR SDK building script
+
+ - Add a definition in "wasm_lib.cmake" for your component, e.g.
+
+ ```cmake
+ add_definitions (-DAPP_FRAMEWORK_MY_COMPONENT)
+ ```
+
+- Modify the file [app_ext_lib_export.c](./app_ext_lib_export.c) to register native APIs exported for the new introduced component. Skip it if not exporting native functions.
+
+ ```
+ #include "lib_export.h"
+
+ ...
+ #ifdef APP_FRAMEWORK_MY_COMPONENT // this definition is created in wasm_lib.cmake
+ #include "my_component_native_api.h"
+ #endif
+
+ static NativeSymbol extended_native_symbol_defs[] = {
+ ...
+ #ifdef APP_FRAMEWORK_MY_COMPONENT
+ #include "my_component.inl"
+ #endif
+ };
+ ```
+
+
+## Sensor component working flow
+![](../../doc/pics/sensor_callflow.PNG)
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/README.md
new file mode 100644
index 000000000..b166e0b3a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/attr_container.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/attr_container.c
new file mode 100644
index 000000000..e1e9f4e35
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/attr_container.c
@@ -0,0 +1,986 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bi-inc/attr_container.h"
+
+typedef union jvalue {
+ bool z;
+ int8_t i8;
+ uint8_t u8;
+ int16_t i16;
+ uint16_t u16;
+ int32_t i32;
+ uint32_t u32;
+ int64_t i64;
+ uint64_t u64;
+ float f;
+ double d;
+} jvalue;
+
+static inline int16_t
+get_int16(const char *buf)
+{
+ int16_t ret;
+ bh_memcpy_s(&ret, sizeof(int16_t), buf, sizeof(int16_t));
+ return ret;
+}
+
+static inline uint16_t
+get_uint16(const char *buf)
+{
+ uint16_t ret;
+ bh_memcpy_s(&ret, sizeof(uint16_t), buf, sizeof(uint16_t));
+ return ret;
+}
+
+static inline int32_t
+get_int32(const char *buf)
+{
+ int32_t ret;
+ bh_memcpy_s(&ret, sizeof(int32_t), buf, sizeof(int32_t));
+ return ret;
+}
+
+static inline uint32_t
+get_uint32(const char *buf)
+{
+ uint32_t ret;
+ bh_memcpy_s(&ret, sizeof(uint32_t), buf, sizeof(uint32_t));
+ return ret;
+}
+
+static inline int64_t
+get_int64(const char *buf)
+{
+ int64_t ret;
+ bh_memcpy_s(&ret, sizeof(int64_t), buf, sizeof(int64_t));
+ return ret;
+}
+
+static inline uint64_t
+get_uint64(const char *buf)
+{
+ uint64_t ret;
+ bh_memcpy_s(&ret, sizeof(uint64_t), buf, sizeof(uint64_t));
+ return ret;
+}
+
+static inline void
+set_int16(char *buf, int16_t v)
+{
+ bh_memcpy_s(buf, sizeof(int16_t), &v, sizeof(int16_t));
+}
+
+static inline void
+set_uint16(char *buf, uint16_t v)
+{
+ bh_memcpy_s(buf, sizeof(uint16_t), &v, sizeof(uint16_t));
+}
+
+static inline void
+set_int32(char *buf, int32_t v)
+{
+ bh_memcpy_s(buf, sizeof(int32_t), &v, sizeof(int32_t));
+}
+
+static inline void
+set_uint32(char *buf, uint32_t v)
+{
+ bh_memcpy_s(buf, sizeof(uint32_t), &v, sizeof(uint32_t));
+}
+
+static inline void
+set_int64(char *buf, int64_t v)
+{
+ bh_memcpy_s(buf, sizeof(int64_t), &v, sizeof(int64_t));
+}
+
+static inline void
+set_uint64(char *buf, uint64_t v)
+{
+ bh_memcpy_s(buf, sizeof(uint64_t), &v, sizeof(uint64_t));
+}
+
+char *
+attr_container_get_attr_begin(const attr_container_t *attr_cont,
+ uint32_t *p_total_length, uint16_t *p_attr_num)
+{
+ char *p = (char *)attr_cont->buf;
+ uint16_t str_len, attr_num;
+ uint32_t total_length;
+
+ /* skip total length */
+ total_length = get_uint32(p);
+ p += sizeof(uint32_t);
+ if (!total_length)
+ return NULL;
+
+ /* tag length */
+ str_len = get_uint16(p);
+ p += sizeof(uint16_t);
+ if (!str_len)
+ return NULL;
+
+ /* tag content */
+ p += str_len;
+ if ((uint32_t)(p - attr_cont->buf) >= total_length)
+ return NULL;
+
+ /* attribute num */
+ attr_num = get_uint16(p);
+ p += sizeof(uint16_t);
+ if ((uint32_t)(p - attr_cont->buf) >= total_length)
+ return NULL;
+
+ if (p_total_length)
+ *p_total_length = total_length;
+
+ if (p_attr_num)
+ *p_attr_num = attr_num;
+
+ /* first attribute */
+ return p;
+}
+
+static char *
+attr_container_get_attr_next(const char *curr_attr)
+{
+ char *p = (char *)curr_attr;
+ uint8_t type;
+
+ /* key length and key */
+ p += sizeof(uint16_t) + get_uint16(p);
+ type = *p++;
+
+ /* Byte type to Boolean type */
+ if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) {
+ p += 1 << (type & 3);
+ return p;
+ }
+ /* String type */
+ else if (type == ATTR_TYPE_STRING) {
+ p += sizeof(uint16_t) + get_uint16(p);
+ return p;
+ }
+ /* ByteArray type */
+ else if (type == ATTR_TYPE_BYTEARRAY) {
+ p += sizeof(uint32_t) + get_uint32(p);
+ return p;
+ }
+
+ return NULL;
+}
+
+static const char *
+attr_container_find_attr(const attr_container_t *attr_cont, const char *key)
+{
+ uint32_t total_length;
+ uint16_t str_len, attr_num, i;
+ const char *p = attr_cont->buf;
+
+ if (!key)
+ return NULL;
+
+ if (!(p = attr_container_get_attr_begin(attr_cont, &total_length,
+ &attr_num)))
+ return NULL;
+
+ for (i = 0; i < attr_num; i++) {
+ /* key length */
+ if (!(str_len = get_uint16(p)))
+ return NULL;
+
+ if (str_len == strlen(key) + 1
+ && memcmp(p + sizeof(uint16_t), key, str_len) == 0) {
+ if ((uint32_t)(p + sizeof(uint16_t) + str_len - attr_cont->buf)
+ >= total_length)
+ return NULL;
+ return p;
+ }
+
+ if (!(p = attr_container_get_attr_next(p)))
+ return NULL;
+ }
+
+ return NULL;
+}
+
+char *
+attr_container_get_attr_end(const attr_container_t *attr_cont)
+{
+ uint32_t total_length;
+ uint16_t attr_num, i;
+ char *p;
+
+ if (!(p = attr_container_get_attr_begin(attr_cont, &total_length,
+ &attr_num)))
+ return NULL;
+
+ for (i = 0; i < attr_num; i++)
+ if (!(p = attr_container_get_attr_next(p)))
+ return NULL;
+
+ return p;
+}
+
+static char *
+attr_container_get_msg_end(attr_container_t *attr_cont)
+{
+ char *p = attr_cont->buf;
+ return p + get_uint32(p);
+}
+
+uint16_t
+attr_container_get_attr_num(const attr_container_t *attr_cont)
+{
+ uint16_t str_len;
+ /* skip total length */
+ const char *p = attr_cont->buf + sizeof(uint32_t);
+
+ str_len = get_uint16(p);
+ /* skip tag length and tag */
+ p += sizeof(uint16_t) + str_len;
+
+ /* attribute num */
+ return get_uint16(p);
+}
+
+static void
+attr_container_inc_attr_num(attr_container_t *attr_cont)
+{
+ uint16_t str_len, attr_num;
+ /* skip total length */
+ char *p = attr_cont->buf + sizeof(uint32_t);
+
+ str_len = get_uint16(p);
+ /* skip tag length and tag */
+ p += sizeof(uint16_t) + str_len;
+
+ /* attribute num */
+ attr_num = get_uint16(p) + 1;
+ set_uint16(p, attr_num);
+}
+
+attr_container_t *
+attr_container_create(const char *tag)
+{
+ attr_container_t *attr_cont;
+ int length, tag_length;
+ char *p;
+
+ tag_length = tag ? strlen(tag) + 1 : 1;
+ length = offsetof(attr_container_t, buf) +
+ /* total length + tag length + tag + reserved 100 bytes */
+ sizeof(uint32_t) + sizeof(uint16_t) + tag_length + 100;
+
+ if (!(attr_cont = attr_container_malloc(length))) {
+ attr_container_printf(
+ "Create attr_container failed: allocate memory failed.\r\n");
+ return NULL;
+ }
+
+ memset(attr_cont, 0, length);
+ p = attr_cont->buf;
+
+ /* total length */
+ set_uint32(p, length - offsetof(attr_container_t, buf));
+ p += 4;
+
+ /* tag length, tag */
+ set_uint16(p, tag_length);
+ p += 2;
+ if (tag)
+ bh_memcpy_s(p, tag_length, tag, tag_length);
+
+ return attr_cont;
+}
+
+void
+attr_container_destroy(const attr_container_t *attr_cont)
+{
+ if (attr_cont)
+ attr_container_free((char *)attr_cont);
+}
+
+static bool
+check_set_attr(attr_container_t **p_attr_cont, const char *key)
+{
+ uint32_t flags;
+
+ if (!p_attr_cont || !*p_attr_cont || !key || strlen(key) == 0) {
+ attr_container_printf(
+ "Set attribute failed: invalid input arguments.\r\n");
+ return false;
+ }
+
+ flags = get_uint32((char *)*p_attr_cont);
+ if (flags & ATTR_CONT_READONLY_SHIFT) {
+ attr_container_printf(
+ "Set attribute failed: attribute container is readonly.\r\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool
+attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
+ int type, const void *value, int value_length)
+{
+ attr_container_t *attr_cont, *attr_cont1;
+ uint16_t str_len;
+ uint32_t total_length, attr_len;
+ char *p, *p1, *attr_end, *msg_end, *attr_buf;
+
+ if (!check_set_attr(p_attr_cont, key)) {
+ return false;
+ }
+
+ attr_cont = *p_attr_cont;
+ p = attr_cont->buf;
+ total_length = get_uint32(p);
+
+ if (!(attr_end = attr_container_get_attr_end(attr_cont))) {
+ attr_container_printf("Set attr failed: get attr end failed.\r\n");
+ return false;
+ }
+
+ msg_end = attr_container_get_msg_end(attr_cont);
+
+ /* key len + key + '\0' + type */
+ attr_len = sizeof(uint16_t) + strlen(key) + 1 + 1;
+ if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN)
+ attr_len += 1 << (type & 3);
+ else if (type == ATTR_TYPE_STRING)
+ attr_len += sizeof(uint16_t) + value_length;
+ else if (type == ATTR_TYPE_BYTEARRAY)
+ attr_len += sizeof(uint32_t) + value_length;
+
+ if (!(p = attr_buf = attr_container_malloc(attr_len))) {
+ attr_container_printf("Set attr failed: allocate memory failed.\r\n");
+ return false;
+ }
+
+ /* Set the attr buf */
+ str_len = (uint16_t)(strlen(key) + 1);
+ set_uint16(p, str_len);
+ p += sizeof(uint16_t);
+ bh_memcpy_s(p, str_len, key, str_len);
+ p += str_len;
+
+ *p++ = type;
+ if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN)
+ bh_memcpy_s(p, 1 << (type & 3), value, 1 << (type & 3));
+ else if (type == ATTR_TYPE_STRING) {
+ set_uint16(p, value_length);
+ p += sizeof(uint16_t);
+ bh_memcpy_s(p, value_length, value, value_length);
+ }
+ else if (type == ATTR_TYPE_BYTEARRAY) {
+ set_uint32(p, value_length);
+ p += sizeof(uint32_t);
+ bh_memcpy_s(p, value_length, value, value_length);
+ }
+
+ if ((p = (char *)attr_container_find_attr(attr_cont, key))) {
+ /* key found */
+ p1 = attr_container_get_attr_next(p);
+
+ if (p1 - p == attr_len) {
+ bh_memcpy_s(p, attr_len, attr_buf, attr_len);
+ attr_container_free(attr_buf);
+ return true;
+ }
+
+ if ((uint32_t)(p1 - p + msg_end - attr_end) >= attr_len) {
+ memmove(p, p1, attr_end - p1);
+ bh_memcpy_s(p + (attr_end - p1), attr_len, attr_buf, attr_len);
+ attr_container_free(attr_buf);
+ return true;
+ }
+
+ total_length += attr_len + 100;
+ if (!(attr_cont1 = attr_container_malloc(offsetof(attr_container_t, buf)
+ + total_length))) {
+ attr_container_printf(
+ "Set attr failed: allocate memory failed.\r\n");
+ attr_container_free(attr_buf);
+ return false;
+ }
+
+ bh_memcpy_s(attr_cont1, p - (char *)attr_cont, attr_cont,
+ p - (char *)attr_cont);
+ bh_memcpy_s((char *)attr_cont1 + (unsigned)(p - (char *)attr_cont),
+ attr_end - p1, p1, attr_end - p1);
+ bh_memcpy_s((char *)attr_cont1 + (unsigned)(p - (char *)attr_cont)
+ + (unsigned)(attr_end - p1),
+ attr_len, attr_buf, attr_len);
+ p = attr_cont1->buf;
+ set_uint32(p, total_length);
+ *p_attr_cont = attr_cont1;
+ /* Free original buffer */
+ attr_container_free(attr_cont);
+ attr_container_free(attr_buf);
+ return true;
+ }
+ else {
+ /* key not found */
+ if ((uint32_t)(msg_end - attr_end) >= attr_len) {
+ bh_memcpy_s(attr_end, msg_end - attr_end, attr_buf, attr_len);
+ attr_container_inc_attr_num(attr_cont);
+ attr_container_free(attr_buf);
+ return true;
+ }
+
+ total_length += attr_len + 100;
+ if (!(attr_cont1 = attr_container_malloc(offsetof(attr_container_t, buf)
+ + total_length))) {
+ attr_container_printf(
+ "Set attr failed: allocate memory failed.\r\n");
+ attr_container_free(attr_buf);
+ return false;
+ }
+
+ bh_memcpy_s(attr_cont1, attr_end - (char *)attr_cont, attr_cont,
+ attr_end - (char *)attr_cont);
+ bh_memcpy_s((char *)attr_cont1
+ + (unsigned)(attr_end - (char *)attr_cont),
+ attr_len, attr_buf, attr_len);
+ attr_container_inc_attr_num(attr_cont1);
+ p = attr_cont1->buf;
+ set_uint32(p, total_length);
+ *p_attr_cont = attr_cont1;
+ /* Free original buffer */
+ attr_container_free(attr_cont);
+ attr_container_free(attr_buf);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
+ short value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_SHORT, &value,
+ 2);
+}
+
+bool
+attr_container_set_int16(attr_container_t **p_attr_cont, const char *key,
+ int16_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT16, &value,
+ 2);
+}
+
+bool
+attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
+ int value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT, &value, 4);
+}
+
+bool
+attr_container_set_int32(attr_container_t **p_attr_cont, const char *key,
+ int32_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT32, &value,
+ 4);
+}
+
+bool
+attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key,
+ uint32_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT32, &value,
+ 4);
+}
+
+bool
+attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
+ int64_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT64, &value,
+ 8);
+}
+
+bool
+attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key,
+ uint64_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT64, &value,
+ 8);
+}
+
+bool
+attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
+ int8_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTE, &value, 1);
+}
+
+bool
+attr_container_set_int8(attr_container_t **p_attr_cont, const char *key,
+ int8_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT8, &value, 1);
+}
+
+bool
+attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key,
+ uint8_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT8, &value,
+ 1);
+}
+
+bool
+attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
+ uint16_t value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT16, &value,
+ 2);
+}
+
+bool
+attr_container_set_float(attr_container_t **p_attr_cont, const char *key,
+ float value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_FLOAT, &value,
+ 4);
+}
+
+bool
+attr_container_set_double(attr_container_t **p_attr_cont, const char *key,
+ double value)
+{
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_DOUBLE, &value,
+ 8);
+}
+
+bool
+attr_container_set_bool(attr_container_t **p_attr_cont, const char *key,
+ bool value)
+{
+ int8_t value1 = value ? 1 : 0;
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BOOLEAN, &value1,
+ 1);
+}
+
+bool
+attr_container_set_string(attr_container_t **p_attr_cont, const char *key,
+ const char *value)
+{
+ if (!value) {
+ attr_container_printf("Set attr failed: invald input arguments.\r\n");
+ return false;
+ }
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_STRING, value,
+ strlen(value) + 1);
+}
+
+bool
+attr_container_set_bytearray(attr_container_t **p_attr_cont, const char *key,
+ const int8_t *value, unsigned length)
+{
+ if (!value) {
+ attr_container_printf("Set attr failed: invald input arguments.\r\n");
+ return false;
+ }
+ return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTEARRAY, value,
+ length);
+}
+
+static const char *
+attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
+{
+ const char *attr_addr;
+
+ if (!attr_cont || !key) {
+ attr_container_printf(
+ "Get attribute failed: invalid input arguments.\r\n");
+ return NULL;
+ }
+
+ if (!(attr_addr = attr_container_find_attr(attr_cont, key))) {
+ attr_container_printf("Get attribute failed: lookup key failed.\r\n");
+ return NULL;
+ }
+
+ /* key len + key + '\0' */
+ return attr_addr + 2 + strlen(key) + 1;
+}
+
+#define TEMPLATE_ATTR_BUF_TO_VALUE(attr, key, var_name) \
+ do { \
+ jvalue val; \
+ const char *addr = attr_container_get_attr(attr, key); \
+ uint8_t type; \
+ if (!addr) \
+ return 0; \
+ val.i64 = 0; \
+ type = *(uint8_t *)addr++; \
+ switch (type) { \
+ case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ \
+ case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ \
+ case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ \
+ case ATTR_TYPE_INT64: \
+ case ATTR_TYPE_UINT8: \
+ case ATTR_TYPE_UINT16: \
+ case ATTR_TYPE_UINT32: \
+ case ATTR_TYPE_UINT64: \
+ case ATTR_TYPE_FLOAT: \
+ case ATTR_TYPE_DOUBLE: \
+ case ATTR_TYPE_BOOLEAN: \
+ bh_memcpy_s(&val, sizeof(val.var_name), addr, \
+ 1 << (type & 3)); \
+ break; \
+ case ATTR_TYPE_STRING: \
+ { \
+ unsigned len = get_uint16(addr); \
+ addr += 2; \
+ if (len > sizeof(val.var_name)) \
+ len = sizeof(val.var_name); \
+ bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
+ break; \
+ } \
+ case ATTR_TYPE_BYTEARRAY: \
+ { \
+ unsigned len = get_uint32(addr); \
+ addr += 4; \
+ if (len > sizeof(val.var_name)) \
+ len = sizeof(val.var_name); \
+ bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
+ break; \
+ } \
+ default: \
+ bh_assert(0); \
+ break; \
+ } \
+ return val.var_name; \
+ } while (0)
+
+short
+attr_container_get_as_short(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i16);
+}
+
+int16_t
+attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key)
+{
+ return (int16_t)attr_container_get_as_short(attr_cont, key);
+}
+
+int
+attr_container_get_as_int(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i32);
+}
+
+int32_t
+attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key)
+{
+ return (int32_t)attr_container_get_as_int(attr_cont, key);
+}
+
+uint32_t
+attr_container_get_as_uint32(const attr_container_t *attr_cont, const char *key)
+{
+ return (uint32_t)attr_container_get_as_int(attr_cont, key);
+}
+
+int64_t
+attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i64);
+}
+
+uint64_t
+attr_container_get_as_uint64(const attr_container_t *attr_cont, const char *key)
+{
+ return (uint64_t)attr_container_get_as_int64(attr_cont, key);
+}
+
+int8_t
+attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i8);
+}
+
+int8_t
+attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key)
+{
+ return attr_container_get_as_byte(attr_cont, key);
+}
+
+uint8_t
+attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key)
+{
+ return (uint8_t)attr_container_get_as_byte(attr_cont, key);
+}
+
+uint16_t
+attr_container_get_as_uint16(const attr_container_t *attr_cont, const char *key)
+{
+ return (uint16_t)attr_container_get_as_short(attr_cont, key);
+}
+
+float
+attr_container_get_as_float(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, f);
+}
+
+double
+attr_container_get_as_double(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, d);
+}
+
+bool
+attr_container_get_as_bool(const attr_container_t *attr_cont, const char *key)
+{
+ TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, z);
+}
+
+const int8_t *
+attr_container_get_as_bytearray(const attr_container_t *attr_cont,
+ const char *key, unsigned *array_length)
+{
+ const char *addr = attr_container_get_attr(attr_cont, key);
+ uint8_t type;
+ uint32_t length;
+
+ if (!addr)
+ return NULL;
+
+ if (!array_length) {
+ attr_container_printf("Get attribute failed: invalid input arguments.");
+ return NULL;
+ }
+
+ type = *(uint8_t *)addr++;
+ switch (type) {
+ case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
+ case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
+ case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
+ case ATTR_TYPE_INT64:
+ case ATTR_TYPE_UINT8:
+ case ATTR_TYPE_UINT16:
+ case ATTR_TYPE_UINT32:
+ case ATTR_TYPE_UINT64:
+ case ATTR_TYPE_FLOAT:
+ case ATTR_TYPE_DOUBLE:
+ case ATTR_TYPE_BOOLEAN:
+ length = 1 << (type & 3);
+ break;
+ case ATTR_TYPE_STRING:
+ length = get_uint16(addr);
+ addr += 2;
+ break;
+ case ATTR_TYPE_BYTEARRAY:
+ length = get_uint32(addr);
+ addr += 4;
+ break;
+ default:
+ return NULL;
+ }
+
+ *array_length = length;
+ return (const int8_t *)addr;
+}
+
+char *
+attr_container_get_as_string(const attr_container_t *attr_cont, const char *key)
+{
+ unsigned array_length;
+ return (char *)attr_container_get_as_bytearray(attr_cont, key,
+ &array_length);
+}
+
+const char *
+attr_container_get_tag(const attr_container_t *attr_cont)
+{
+ return attr_cont ? attr_cont->buf + sizeof(uint32_t) + sizeof(uint16_t)
+ : NULL;
+}
+
+bool
+attr_container_contain_key(const attr_container_t *attr_cont, const char *key)
+{
+ if (!attr_cont || !key || !strlen(key)) {
+ attr_container_printf(
+ "Check contain key failed: invalid input arguments.\r\n");
+ return false;
+ }
+ return attr_container_find_attr(attr_cont, key) ? true : false;
+}
+
+unsigned int
+attr_container_get_serialize_length(const attr_container_t *attr_cont)
+{
+ const char *p;
+
+ if (!attr_cont) {
+ attr_container_printf("Get container serialize length failed: invalid "
+ "input arguments.\r\n");
+ return 0;
+ }
+
+ p = attr_cont->buf;
+ return sizeof(uint16_t) + get_uint32(p);
+}
+
+bool
+attr_container_serialize(char *buf, const attr_container_t *attr_cont)
+{
+ const char *p;
+ uint16_t flags;
+ uint32_t length;
+
+ if (!buf || !attr_cont) {
+ attr_container_printf(
+ "Container serialize failed: invalid input arguments.\r\n");
+ return false;
+ }
+
+ p = attr_cont->buf;
+ length = sizeof(uint16_t) + get_uint32(p);
+ bh_memcpy_s(buf, length, attr_cont, length);
+ /* Set readonly */
+ flags = get_uint16((const char *)attr_cont);
+ set_uint16(buf, flags | (1 << ATTR_CONT_READONLY_SHIFT));
+
+ return true;
+}
+
+bool
+attr_container_is_constant(const attr_container_t *attr_cont)
+{
+ uint16_t flags;
+
+ if (!attr_cont) {
+ attr_container_printf(
+ "Container check const: invalid input arguments.\r\n");
+ return false;
+ }
+
+ flags = get_uint16((const char *)attr_cont);
+ return (flags & (1 << ATTR_CONT_READONLY_SHIFT)) ? true : false;
+}
+
+void
+attr_container_dump(const attr_container_t *attr_cont)
+{
+ uint32_t total_length;
+ uint16_t attr_num, i, type;
+ const char *p, *tag, *key;
+ jvalue value;
+
+ if (!attr_cont)
+ return;
+
+ tag = attr_container_get_tag(attr_cont);
+ if (!tag)
+ return;
+
+ attr_container_printf("Attribute container dump:\n");
+ attr_container_printf("Tag: %s\n", tag);
+
+ p = attr_container_get_attr_begin(attr_cont, &total_length, &attr_num);
+ if (!p)
+ return;
+
+ attr_container_printf("Attribute list:\n");
+ for (i = 0; i < attr_num; i++) {
+ key = p + 2;
+ /* Skip key len and key */
+ p += 2 + get_uint16(p);
+ type = *p++;
+ attr_container_printf(" key: %s", key);
+
+ switch (type) {
+ case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
+ bh_memcpy_s(&value.i8, 1, p, 1);
+ attr_container_printf(", type: byte, value: 0x%x\n",
+ value.i8 & 0xFF);
+ p++;
+ break;
+ case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
+ bh_memcpy_s(&value.i16, sizeof(int16_t), p, sizeof(int16_t));
+ attr_container_printf(", type: short, value: 0x%x\n",
+ value.i16 & 0xFFFF);
+ p += 2;
+ break;
+ case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
+ bh_memcpy_s(&value.i32, sizeof(int32_t), p, sizeof(int32_t));
+ attr_container_printf(", type: int, value: 0x%x\n", value.i32);
+ p += 4;
+ break;
+ case ATTR_TYPE_INT64:
+ bh_memcpy_s(&value.i64, sizeof(int64_t), p, sizeof(int64_t));
+ attr_container_printf(", type: int64, value: 0x%llx\n",
+ (long long unsigned int)(value.i64));
+ p += 8;
+ break;
+ case ATTR_TYPE_UINT8:
+ bh_memcpy_s(&value.u8, 1, p, 1);
+ attr_container_printf(", type: uint8, value: 0x%x\n", value.u8);
+ p++;
+ break;
+ case ATTR_TYPE_UINT16:
+ bh_memcpy_s(&value.u16, sizeof(uint16_t), p, sizeof(uint16_t));
+ attr_container_printf(", type: uint16, value: 0x%x\n",
+ value.u16);
+ p += 2;
+ break;
+ case ATTR_TYPE_UINT32:
+ bh_memcpy_s(&value.u32, sizeof(uint32_t), p, sizeof(uint32_t));
+ attr_container_printf(", type: uint32, value: 0x%x\n",
+ value.u32);
+ p += 4;
+ break;
+ case ATTR_TYPE_UINT64:
+ bh_memcpy_s(&value.u64, sizeof(uint64_t), p, sizeof(uint64_t));
+ attr_container_printf(", type: int64, value: 0x%llx\n",
+ (long long unsigned int)(value.u64));
+ p += 8;
+ break;
+ case ATTR_TYPE_FLOAT:
+ bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float));
+ attr_container_printf(", type: float, value: %f\n", value.f);
+ p += 4;
+ break;
+ case ATTR_TYPE_DOUBLE:
+ bh_memcpy_s(&value.d, sizeof(double), p, sizeof(double));
+ attr_container_printf(", type: double, value: %f\n", value.d);
+ p += 8;
+ break;
+ case ATTR_TYPE_BOOLEAN:
+ bh_memcpy_s(&value.z, 1, p, 1);
+ attr_container_printf(", type: bool, value: 0x%x\n", value.z);
+ p++;
+ break;
+ case ATTR_TYPE_STRING:
+ attr_container_printf(", type: string, value: %s\n",
+ p + sizeof(uint16_t));
+ p += sizeof(uint16_t) + get_uint16(p);
+ break;
+ case ATTR_TYPE_BYTEARRAY:
+ attr_container_printf(", type: byte array, length: %d\n",
+ get_uint32(p));
+ p += sizeof(uint32_t) + get_uint32(p);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ attr_container_printf("\n");
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/attr_container.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/attr_container.h
new file mode 100644
index 000000000..f5d8759b8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/attr_container.h
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _ATTR_CONTAINER_H_
+#define _ATTR_CONTAINER_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Attribute type */
+enum {
+ ATTR_TYPE_BEGIN = 0,
+ ATTR_TYPE_BYTE = ATTR_TYPE_BEGIN,
+ ATTR_TYPE_INT8 = ATTR_TYPE_BYTE,
+ ATTR_TYPE_SHORT,
+ ATTR_TYPE_INT16 = ATTR_TYPE_SHORT,
+ ATTR_TYPE_INT,
+ ATTR_TYPE_INT32 = ATTR_TYPE_INT,
+ ATTR_TYPE_INT64,
+ ATTR_TYPE_UINT8,
+ ATTR_TYPE_UINT16,
+ ATTR_TYPE_UINT32,
+ ATTR_TYPE_UINT64,
+ /**
+ * Why ATTR_TYPE_FLOAT = 10?
+ * We determine the number of bytes that should be copied through 1<<(type &
+ * 3). ATTR_TYPE_BYTE = 0, so the number of bytes is 1 << 0 = 1.
+ * ATTR_TYPE_UINT64 = 7, so the number of bytes is 1 << 3 = 8.
+ * Since the float type takes up 4 bytes, ATTR_TYPE_FLOAT should be 10.
+ * Calculation: (1 << (10&3)) = (1 << 2) = 4
+ */
+ ATTR_TYPE_FLOAT = 10,
+ ATTR_TYPE_DOUBLE,
+ ATTR_TYPE_BOOLEAN,
+ ATTR_TYPE_STRING,
+ ATTR_TYPE_BYTEARRAY,
+ ATTR_TYPE_END = ATTR_TYPE_BYTEARRAY
+};
+
+#define ATTR_CONT_READONLY_SHIFT 2
+
+typedef struct attr_container {
+ /* container flag:
+ * bit0, bit1 denote the implemenation algorithm, 00: buffer, 01: link list
+ * bit2 denotes the readonly flag: 1 is readonly and attr cannot be set
+ */
+ char flags[2];
+ /**
+ * Buffer format
+ * for buffer implementation:
+ * buf length (4 bytes)
+ * tag length (2 bytes)
+ * tag
+ * attr num (2bytes)
+ * attr[0..n-1]:
+ * attr key length (2 bytes)
+ * attr type (1byte)
+ * attr value (length depends on attr type)
+ */
+ char buf[1];
+} attr_container_t;
+
+/**
+ * Create attribute container
+ *
+ * @param tag tag of current attribute container
+ *
+ * @return the created attribute container, NULL if failed
+ */
+attr_container_t *
+attr_container_create(const char *tag);
+
+/**
+ * Destroy attribute container
+ *
+ * @param attr_cont the attribute container to destroy
+ */
+void
+attr_container_destroy(const attr_container_t *attr_cont);
+
+/**
+ * Set short attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
+ short value);
+
+/**
+ * Set int16 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_int16(attr_container_t **p_attr_cont, const char *key,
+ int16_t value);
+
+/**
+ * Set int attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
+ int value);
+
+/**
+ * Set int32 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_int32(attr_container_t **p_attr_cont, const char *key,
+ int32_t value);
+
+/**
+ * Set uint32 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key,
+ uint32_t value);
+
+/**
+ * Set int64 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
+ int64_t value);
+
+/**
+ * Set uint64 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key,
+ uint64_t value);
+
+/**
+ * Set byte attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
+ int8_t value);
+
+/**
+ * Set int8 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_int8(attr_container_t **p_attr_cont, const char *key,
+ int8_t value);
+
+/**
+ * Set uint8 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key,
+ uint8_t value);
+
+/**
+ * Set uint16 attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
+ uint16_t value);
+
+/**
+ * Set float attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_float(attr_container_t **p_attr_cont, const char *key,
+ float value);
+
+/**
+ * Set double attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_double(attr_container_t **p_attr_cont, const char *key,
+ double value);
+
+/**
+ * Set bool attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_bool(attr_container_t **p_attr_cont, const char *key,
+ bool value);
+
+/**
+ * Set string attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the attribute value
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_string(attr_container_t **p_attr_cont, const char *key,
+ const char *value);
+
+/**
+ * Set bytearray attribute in attribute container
+ *
+ * @param p_attr_cont pointer to attribute container to set attribute, and
+ * return the new attribute container if it is re-created
+ * @param key the attribute key
+ * @param value the bytearray buffer
+ * @param length the bytearray length
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_set_bytearray(attr_container_t **p_attr_cont, const char *key,
+ const int8_t *value, unsigned length);
+
+/**
+ * Get tag of current attribute container
+ *
+ * @param attr_cont the attribute container
+ *
+ * @return tag of current attribute container
+ */
+const char *
+attr_container_get_tag(const attr_container_t *attr_cont);
+
+/**
+ * Get attribute number of current attribute container
+ *
+ * @param attr_cont the attribute container
+ *
+ * @return attribute number of current attribute container
+ */
+uint16_t
+attr_container_get_attr_num(const attr_container_t *attr_cont);
+
+/**
+ * Whether the attribute container contains an attribute key.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return true if key is contained in message, false otherwise
+ */
+bool
+attr_container_contain_key(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as short value,
+ * return 0 if attribute isn't found in message.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the short value of the attribute, 0 if key isn't found
+ */
+short
+attr_container_get_as_short(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as int16 value,
+ * return 0 if attribute isn't found in message.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the short value of the attribute, 0 if key isn't found
+ */
+int16_t
+attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as int value,
+ * return 0 if attribute isn't found in message.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the int value of the attribute, 0 if key isn't found
+ */
+int
+attr_container_get_as_int(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as int32 value,
+ * return 0 if attribute isn't found in message.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the int value of the attribute, 0 if key isn't found
+ */
+int32_t
+attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as uint32 value,
+ * return 0 if attribute isn't found in message.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the unsigned int value of the attribute, 0 if key isn't found
+ */
+uint32_t
+attr_container_get_as_uint32(const attr_container_t *attr_cont,
+ const char *key);
+
+/**
+ * Get attribute from attribute container and return it as int64 value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the long value of the attribute, 0 if key isn't found
+ */
+int64_t
+attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as uint64 value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the unsigned long value of the attribute, 0 if key isn't found
+ */
+uint64_t
+attr_container_get_as_uint64(const attr_container_t *attr_cont,
+ const char *key);
+
+/**
+ * Get attribute from attribute container and return it as byte value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the byte value of the attribute, 0 if key isn't found
+ */
+int8_t
+attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as int8 value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the byte value of the attribute, 0 if key isn't found
+ */
+int8_t
+attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as uint8 value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the uint8 value of the attribute, 0 if key isn't found
+ */
+uint8_t
+attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as uint16 value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the char value of the attribute, 0 if key isn't found
+ */
+uint16_t
+attr_container_get_as_uint16(const attr_container_t *attr_cont,
+ const char *key);
+
+/**
+ * Get attribute from attribute container and return it as float value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the float value of the attribute, 0 if key isn't found
+ */
+float
+attr_container_get_as_float(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as double value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the double value of the attribute, 0 if key isn't found
+ */
+double
+attr_container_get_as_double(const attr_container_t *attr_cont,
+ const char *key);
+
+/**
+ * Get attribute from attribute container and return it as bool value,
+ * return false if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the bool value of the attribute, 0 if key isn't found
+ */
+bool
+attr_container_get_as_bool(const attr_container_t *attr_cont, const char *key);
+
+/**
+ * Get attribute from attribute container and return it as string value,
+ * return NULL if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the string value of the attribute, NULL if key isn't found
+ */
+char *
+attr_container_get_as_string(const attr_container_t *attr_cont,
+ const char *key);
+
+/**
+ * Get attribute from attribute container and return it as bytearray value,
+ * return 0 if attribute isn't found in attribute container.
+ *
+ * @param attr_cont the attribute container
+ * @param key the attribute key
+ *
+ * @return the bytearray value of the attribute, NULL if key isn't found
+ */
+const int8_t *
+attr_container_get_as_bytearray(const attr_container_t *attr_cont,
+ const char *key, unsigned *array_length);
+
+/**
+ * Get the buffer size of attribute container
+ *
+ * @param attr_cont the attribute container
+ *
+ * @return the buffer size of attribute container
+ */
+unsigned
+attr_container_get_serialize_length(const attr_container_t *attr_cont);
+
+/**
+ * Serialize attribute container to a buffer
+ *
+ * @param buf the buffer to receive the serialized data
+ * @param attr_cont the attribute container to be serialized
+ *
+ * @return true if success, false otherwise
+ */
+bool
+attr_container_serialize(char *buf, const attr_container_t *attr_cont);
+
+/**
+ * Whether the attribute container is const, or set attribute isn't supported
+ *
+ * @param attr_cont the attribute container
+ *
+ * @return true if const, false otherwise
+ */
+bool
+attr_container_is_constant(const attr_container_t *attr_cont);
+
+void
+attr_container_dump(const attr_container_t *attr_cont);
+
+#ifndef attr_container_malloc
+#define attr_container_malloc WA_MALLOC
+#endif
+
+#ifndef attr_container_free
+#define attr_container_free WA_FREE
+#endif
+
+#ifndef attr_container_printf
+#define attr_container_printf printf
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _ATTR_CONTAINER_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/shared_utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/shared_utils.h
new file mode 100644
index 000000000..8155ea1f7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/shared_utils.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SHARED_UTILS_H_
+#define _SHARED_UTILS_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FMT_ATTR_CONTAINER 99
+#define FMT_APP_RAW_BINARY 98
+
+/* the request structure */
+typedef struct request {
+ // message id
+ uint32 mid;
+
+ // url of the request
+ char *url;
+
+ // action of the request, can be PUT/GET/POST/DELETE
+ int action;
+
+ // payload format, currently only support attr_container_t type
+ int fmt;
+
+ // payload of the request, currently only support attr_container_t type
+ void *payload;
+
+ // length in bytes of the payload
+ int payload_len;
+
+ // sender of the request
+ unsigned long sender;
+} request_t;
+
+/* the response structure */
+typedef struct response {
+ // message id
+ uint32 mid;
+
+ // status of the response
+ int status;
+
+ // payload format
+ int fmt;
+
+ // payload of the response,
+ void *payload;
+
+ // length in bytes of the payload
+ int payload_len;
+
+ // receiver of the response
+ unsigned long reciever;
+} response_t;
+
+int
+check_url_start(const char *url, int url_len, const char *leading_str);
+
+bool
+match_url(char *pattern, char *matched);
+
+char *
+find_key_value(char *buffer, int buffer_len, char *key, char *value,
+ int value_len, char delimiter);
+
+request_t *
+clone_request(request_t *request);
+
+void
+request_cleaner(request_t *request);
+
+response_t *
+clone_response(response_t *response);
+
+void
+response_cleaner(response_t *response);
+
+/**
+ * @brief Set fields of response.
+ *
+ * @param response pointer of the response to be set
+ * @param status status of response
+ * @param fmt format of the response payload
+ * @param payload payload of the response
+ * @param payload_len length in bytes of the response payload
+ *
+ * @return pointer to the response
+ *
+ * @warning the response pointer MUST NOT be NULL
+ */
+response_t *
+set_response(response_t *response, int status, int fmt, const char *payload,
+ int payload_len);
+
+/**
+ * @brief Make a response for a request.
+ *
+ * @param request pointer of the request
+ * @param response pointer of the response to be made
+ *
+ * @return pointer to the response
+ *
+ * @warning the request and response pointers MUST NOT be NULL
+ */
+response_t *
+make_response_for_request(request_t *request, response_t *response);
+
+/**
+ * @brief Initialize a request.
+ *
+ * @param request pointer of the request to be initialized
+ * @param url url of the request
+ * @param action action of the request
+ * @param fmt format of the request payload
+ * @param payload payload of the request
+ * @param payload_len length in bytes of the request payload
+ *
+ * @return pointer to the request
+ *
+ * @warning the request pointer MUST NOT be NULL
+ */
+request_t *
+init_request(request_t *request, char *url, int action, int fmt, void *payload,
+ int payload_len);
+
+char *
+pack_request(request_t *request, int *size);
+
+request_t *
+unpack_request(char *packet, int size, request_t *request);
+
+char *
+pack_response(response_t *response, int *size);
+
+response_t *
+unpack_response(char *packet, int size, response_t *response);
+
+void
+free_req_resp_packet(char *packet);
+
+char *
+wa_strdup(const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SHARED_UTILS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h
new file mode 100644
index 000000000..86d864e41
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H
+#define WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+/* Object native function IDs */
+enum {
+ OBJ_FUNC_ID_DEL,
+ OBJ_FUNC_ID_DEL_ASYNC,
+ OBJ_FUNC_ID_CLEAN,
+ OBJ_FUNC_ID_SET_EVT_CB,
+ OBJ_FUNC_ID_ALIGN,
+
+ /* Number of functions */
+ _OBJ_FUNC_ID_NUM,
+};
+
+/* Button native function IDs */
+enum {
+ BTN_FUNC_ID_CREATE,
+ BTN_FUNC_ID_SET_TOGGLE,
+ BTN_FUNC_ID_SET_STATE,
+ BTN_FUNC_ID_TOGGLE,
+ BTN_FUNC_ID_SET_INK_IN_TIME,
+ BTN_FUNC_ID_SET_INK_WAIT_TIME,
+ BTN_FUNC_ID_SET_INK_OUT_TIME,
+ BTN_FUNC_ID_GET_STATE,
+ BTN_FUNC_ID_GET_TOGGLE,
+ BTN_FUNC_ID_GET_INK_IN_TIME,
+ BTN_FUNC_ID_GET_INK_WAIT_TIME,
+ BTN_FUNC_ID_GET_INK_OUT_TIME,
+ /* Number of functions */
+ _BTN_FUNC_ID_NUM,
+};
+
+/* Check box native function IDs */
+enum {
+ CB_FUNC_ID_CREATE,
+ CB_FUNC_ID_SET_TEXT,
+ CB_FUNC_ID_SET_STATIC_TEXT,
+ CB_FUNC_ID_GET_TEXT,
+ CB_FUNC_ID_GET_TEXT_LENGTH,
+
+ /* Number of functions */
+ _CB_FUNC_ID_NUM,
+};
+
+/* List native function IDs */
+enum {
+ LIST_FUNC_ID_CREATE,
+ LIST_FUNC_ID_ADD_BTN,
+
+ /* Number of functions */
+ _LIST_FUNC_ID_NUM,
+};
+
+/* Label native function IDs */
+enum {
+ LABEL_FUNC_ID_CREATE,
+ LABEL_FUNC_ID_SET_TEXT,
+ LABEL_FUNC_ID_SET_ARRAY_TEXT,
+ LABEL_FUNC_ID_SET_STATIC_TEXT,
+ LABEL_FUNC_ID_SET_LONG_MODE,
+ LABEL_FUNC_ID_SET_ALIGN,
+ LABEL_FUNC_ID_SET_RECOLOR,
+ LABEL_FUNC_ID_SET_BODY_DRAW,
+ LABEL_FUNC_ID_SET_ANIM_SPEED,
+ LABEL_FUNC_ID_SET_TEXT_SEL_START,
+ LABEL_FUNC_ID_SET_TEXT_SEL_END,
+ LABEL_FUNC_ID_GET_TEXT,
+ LABEL_FUNC_ID_GET_TEXT_LENGTH,
+ LABEL_FUNC_ID_GET_LONG_MODE,
+ LABEL_FUNC_ID_GET_ALIGN,
+ LABEL_FUNC_ID_GET_RECOLOR,
+ LABEL_FUNC_ID_GET_BODY_DRAW,
+ LABEL_FUNC_ID_GET_ANIM_SPEED,
+ LABEL_FUNC_ID_GET_LETTER_POS,
+ LABEL_FUNC_ID_GET_TEXT_SEL_START,
+ LABEL_FUNC_ID_GET_TEXT_SEL_END,
+ LABEL_FUNC_ID_INS_TEXT,
+ LABEL_FUNC_ID_CUT_TEXT,
+ /* Number of functions */
+ _LABEL_FUNC_ID_NUM,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.cmake
new file mode 100644
index 000000000..48ebe0a33
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.cmake
@@ -0,0 +1,15 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (NATIVE_INTERFACE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${NATIVE_INTERFACE_DIR})
+
+
+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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.h
new file mode 100644
index 000000000..ce9f24780
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/native_interface.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _NATIVE_INTERFACE_H_
+#define _NATIVE_INTERFACE_H_
+
+/* Note: the bh_plaform.h is the only head file separately
+ implemented by both [app] and [native] worlds */
+#include "bh_platform.h"
+
+#endif /* end of _NATIVE_INTERFACE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c
new file mode 100644
index 000000000..03e86a699
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "bi-inc/shared_utils.h"
+
+/* Serialization of request and response message
+ *
+ * Choices:
+ * We considered a few options:
+ * 1. coap
+ * 2. flatbuffer
+ * 3. cbor
+ * 4. attr-containers of our own
+ * 5. customized serialization for request/response
+ *
+ * Now we choose the #5 mainly because we need to quickly get the URL for
+ * dispatching and sometimes we want to change the URL in the original packet.
+ * the request format: fixed part: version: (1 byte), code (1 byte), fmt(2
+ * byte), mid (4 bytes), sender_id(4 bytes), url_len(2 bytes),
+ * payload_len(4bytes) dynamic part: url (bytes in url_len), payload
+ *
+ * response format:
+ * fixed part: (1 byte), code (1 byte), fmt(2 byte), mid (4 bytes), sender_id(4
+ * bytes), payload_len(4bytes) dynamic part: payload
+ */
+#define REQUES_PACKET_VER 1
+#define REQUEST_PACKET_FIX_PART_LEN 18
+#define REQUEST_PACKET_URL_OFFSET REQUEST_PACKET_FIX_PART_LEN
+#define REQUEST_PACKET_URL_LEN \
+ *((uint16 *)((char *)buffer + 12)) /* to ensure little endian */
+#define REQUEST_PACKET_PAYLOAD_LEN \
+ *((uint32 *)((char *)buffer + 14)) /* to ensure little endian */
+#define REQUEST_PACKET_URL(buffer) ((char *)buffer + REQUEST_PACKET_URL_OFFSET)
+#define REQUEST_PACKET_PAYLOAD(buffer) \
+ ((char *)buffer + REQUEST_PACKET_URL_OFFSET \
+ + REQUEST_PACKET_URL_LEN(buffer))
+
+#define RESPONSE_PACKET_FIX_PART_LEN 16
+
+char *
+pack_request(request_t *request, int *size)
+{
+ int url_len = strlen(request->url) + 1;
+ int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len;
+ uint16 u16;
+ uint32 u32;
+ char *packet;
+
+ if ((packet = (char *)WA_MALLOC(len)) == NULL)
+ return NULL;
+
+ /* TODO: ensure little endian for words and dwords */
+ *packet = REQUES_PACKET_VER;
+ *((uint8 *)(packet + 1)) = request->action;
+
+ u16 = htons(request->fmt);
+ memcpy(packet + 2, &u16, 2);
+
+ u32 = htonl(request->mid);
+ memcpy(packet + 4, &u32, 4);
+
+ u32 = htonl(request->sender);
+ memcpy(packet + 8, &u32, 4);
+
+ u16 = htons(url_len);
+ memcpy(packet + 12, &u16, 2);
+
+ u32 = htonl(request->payload_len);
+ memcpy(packet + 14, &u32, 4);
+
+ strcpy(packet + REQUEST_PACKET_URL_OFFSET, request->url);
+ memcpy(packet + REQUEST_PACKET_URL_OFFSET + url_len, request->payload,
+ request->payload_len);
+
+ *size = len;
+ return packet;
+}
+
+void
+free_req_resp_packet(char *packet)
+{
+ WA_FREE(packet);
+}
+
+request_t *
+unpack_request(char *packet, int size, request_t *request)
+{
+ uint16 url_len, u16;
+ uint32 payload_len, u32;
+
+ if (*packet != REQUES_PACKET_VER) {
+ return NULL;
+ }
+ if (size < REQUEST_PACKET_FIX_PART_LEN) {
+ return NULL;
+ }
+
+ memcpy(&u16, packet + 12, 2);
+ url_len = ntohs(u16);
+
+ memcpy(&u32, packet + 14, 4);
+ payload_len = ntohl(u32);
+
+ if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
+ return NULL;
+ }
+
+ if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) {
+ return NULL;
+ }
+
+ request->action = *((uint8 *)(packet + 1));
+
+ memcpy(&u16, packet + 2, 2);
+ request->fmt = ntohs(u16);
+
+ memcpy(&u32, packet + 4, 4);
+ request->mid = ntohl(u32);
+
+ memcpy(&u32, packet + 8, 4);
+ request->sender = ntohl(u32);
+
+ request->payload_len = payload_len;
+ request->url = REQUEST_PACKET_URL(packet);
+
+ if (payload_len > 0)
+ request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len;
+ else
+ request->payload = NULL;
+
+ return request;
+}
+
+char *
+pack_response(response_t *response, int *size)
+{
+ int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len;
+ uint16 u16;
+ uint32 u32;
+ char *packet;
+
+ if ((packet = (char *)WA_MALLOC(len)) == NULL)
+ return NULL;
+
+ /* TODO: ensure little endian for words and dwords */
+ *packet = REQUES_PACKET_VER;
+ *((uint8 *)(packet + 1)) = response->status;
+
+ u16 = htons(response->fmt);
+ memcpy(packet + 2, &u16, 2);
+
+ u32 = htonl(response->mid);
+ memcpy(packet + 4, &u32, 4);
+
+ u32 = htonl(response->reciever);
+ memcpy(packet + 8, &u32, 4);
+
+ u32 = htonl(response->payload_len);
+ memcpy(packet + 12, &u32, 4);
+
+ memcpy(packet + RESPONSE_PACKET_FIX_PART_LEN, response->payload,
+ response->payload_len);
+
+ *size = len;
+ return packet;
+}
+
+response_t *
+unpack_response(char *packet, int size, response_t *response)
+{
+ uint16 u16;
+ uint32 payload_len, u32;
+
+ if (*packet != REQUES_PACKET_VER)
+ return NULL;
+
+ if (size < RESPONSE_PACKET_FIX_PART_LEN)
+ return NULL;
+
+ memcpy(&u32, packet + 12, 4);
+ payload_len = ntohl(u32);
+ if (size != (RESPONSE_PACKET_FIX_PART_LEN + payload_len))
+ return NULL;
+
+ response->status = *((uint8 *)(packet + 1));
+
+ memcpy(&u16, packet + 2, 2);
+ response->fmt = ntohs(u16);
+
+ memcpy(&u32, packet + 4, 4);
+ response->mid = ntohl(u32);
+
+ memcpy(&u32, packet + 8, 4);
+ response->reciever = ntohl(u32);
+
+ response->payload_len = payload_len;
+ if (payload_len > 0)
+ response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN;
+ else
+ response->payload = NULL;
+
+ return response;
+}
+
+request_t *
+clone_request(request_t *request)
+{
+ /* deep clone */
+ request_t *req = (request_t *)WA_MALLOC(sizeof(request_t));
+ if (req == NULL)
+ return NULL;
+
+ memset(req, 0, sizeof(*req));
+ req->action = request->action;
+ req->fmt = request->fmt;
+ req->url = wa_strdup(request->url);
+ req->sender = request->sender;
+ req->mid = request->mid;
+
+ if (req->url == NULL)
+ goto fail;
+
+ req->payload_len = request->payload_len;
+
+ if (request->payload_len) {
+ req->payload = (char *)WA_MALLOC(request->payload_len);
+ if (!req->payload)
+ goto fail;
+ memcpy(req->payload, request->payload, request->payload_len);
+ }
+ else {
+ /* when payload_len is 0, the payload may be used for
+ carrying some handle or integer */
+ req->payload = request->payload;
+ }
+
+ return req;
+
+fail:
+ request_cleaner(req);
+ return NULL;
+}
+
+void
+request_cleaner(request_t *request)
+{
+ if (request->url != NULL)
+ WA_FREE(request->url);
+ if (request->payload != NULL && request->payload_len > 0)
+ WA_FREE(request->payload);
+
+ WA_FREE(request);
+}
+
+void
+response_cleaner(response_t *response)
+{
+ if (response->payload != NULL && response->payload_len > 0)
+ WA_FREE(response->payload);
+
+ WA_FREE(response);
+}
+
+response_t *
+clone_response(response_t *response)
+{
+ response_t *clone = (response_t *)WA_MALLOC(sizeof(response_t));
+
+ if (clone == NULL)
+ return NULL;
+
+ memset(clone, 0, sizeof(*clone));
+ clone->fmt = response->fmt;
+ clone->mid = response->mid;
+ clone->status = response->status;
+ clone->reciever = response->reciever;
+ clone->payload_len = response->payload_len;
+ if (clone->payload_len) {
+ clone->payload = (char *)WA_MALLOC(response->payload_len);
+ if (!clone->payload)
+ goto fail;
+ memcpy(clone->payload, response->payload, response->payload_len);
+ }
+ else {
+ /* when payload_len is 0, the payload may be used for
+ carrying some handle or integer */
+ clone->payload = response->payload;
+ }
+ return clone;
+
+fail:
+ response_cleaner(clone);
+ return NULL;
+}
+
+response_t *
+set_response(response_t *response, int status, int fmt, const char *payload,
+ int payload_len)
+{
+ response->payload = (void *)payload;
+ response->payload_len = payload_len;
+ response->status = status;
+ response->fmt = fmt;
+ return response;
+}
+
+response_t *
+make_response_for_request(request_t *request, response_t *response)
+{
+ response->mid = request->mid;
+ response->reciever = request->sender;
+
+ return response;
+}
+
+static unsigned int mid = 0;
+
+request_t *
+init_request(request_t *request, char *url, int action, int fmt, void *payload,
+ int payload_len)
+{
+ request->url = url;
+ request->action = action;
+ request->fmt = fmt;
+ request->payload = payload;
+ request->payload_len = payload_len;
+ request->mid = ++mid;
+
+ return request;
+}
+
+/*
+ check if the "url" is starting with "leading_str"
+ return: 0 - not match; >0 - the offset of matched url, include any "/" at the
+ end notes:
+ 1. it ensures the leading_str "/abc" can pass "/abc/cde" and "/abc/, but fail
+ "/ab" and "/abcd". leading_str "/abc/" can pass "/abc"
+ 2. it omit the '/' at the first char
+ 3. it ensure the leading_str "/abc" can pass "/abc?cde
+ */
+
+int
+check_url_start(const char *url, int url_len, const char *leading_str)
+{
+ int offset = 0;
+ if (*leading_str == '/')
+ leading_str++;
+ if (url_len > 0 && *url == '/') {
+ url_len--;
+ url++;
+ offset++;
+ }
+
+ int len = strlen(leading_str);
+ if (len == 0)
+ return 0;
+
+ /* ensure leading_str not end with "/" */
+ if (leading_str[len - 1] == '/') {
+ len--;
+ if (len == 0)
+ return 0;
+ }
+
+ /* equal length */
+ if (url_len == len) {
+ if (memcmp(url, leading_str, url_len) == 0) {
+ return (offset + len);
+ }
+ else {
+ return 0;
+ }
+ }
+
+ if (url_len < len)
+ return 0;
+ else if (memcmp(url, leading_str, len) != 0)
+ return 0;
+ else if (url[len] != '/' && url[len] != '?')
+ return 0;
+ else
+ return (offset + len + 1);
+}
+
+// * @pattern:
+// * sample 1: /abcd, match /abcd only
+// * sample 2: /abcd/ match match "/abcd" and "/abcd/*"
+// * sample 3: /abcd*, match any url started with "/abcd"
+// * sample 4: /abcd/*, exclude "/abcd"
+
+bool
+match_url(char *pattern, char *matched)
+{
+ if (*pattern == '/')
+ pattern++;
+ if (*matched == '/')
+ matched++;
+
+ int matched_len = strlen(matched);
+ if (matched_len == 0)
+ return false;
+
+ if (matched[matched_len - 1] == '/') {
+ matched_len--;
+ if (matched_len == 0)
+ return false;
+ }
+
+ int len = strlen(pattern);
+ if (len == 0)
+ return false;
+
+ if (pattern[len - 1] == '/') {
+ len--;
+ if (strncmp(pattern, matched, len) != 0)
+ return false;
+
+ if (len == matched_len)
+ return true;
+
+ if (matched_len > len && matched[len] == '/')
+ return true;
+
+ return false;
+ }
+ else if (pattern[len - 1] == '*') {
+ if (pattern[len - 2] == '/') {
+ if (strncmp(pattern, matched, len - 1) == 0)
+ return true;
+ else
+ return false;
+ }
+ else {
+ return (strncmp(pattern, matched, len - 1) == 0);
+ }
+ }
+ else {
+ return (strcmp(pattern, matched) == 0);
+ }
+}
+
+/*
+ * get the value of the key from following format buffer:
+ * key1=value1;key2=value2;key3=value3
+ */
+char *
+find_key_value(char *buffer, int buffer_len, char *key, char *value,
+ int value_len, char delimiter)
+{
+ char *p = buffer;
+ int remaining = buffer_len;
+ int key_len = strlen(key);
+
+ while (*p != 0 && remaining > 0) {
+ while (*p == ' ' || *p == delimiter) {
+ p++;
+ remaining--;
+ }
+
+ if (remaining <= key_len)
+ return NULL;
+
+ /* find the key */
+ if (0 == strncmp(p, key, key_len) && p[key_len] == '=') {
+ p += (key_len + 1);
+ remaining -= (key_len + 1);
+ char *v = value;
+ memset(value, 0, value_len);
+ value_len--; /* ensure last char is 0 */
+ while (*p != delimiter && remaining > 0 && value_len > 0) {
+ *v++ = *p++;
+ remaining--;
+ value_len--;
+ }
+ return value;
+ }
+
+ /* goto next key */
+ while (*p != delimiter && remaining > 0) {
+ p++;
+ remaining--;
+ }
+ }
+
+ return NULL;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_ext_lib_export.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_ext_lib_export.c
new file mode 100644
index 000000000..532491b43
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_ext_lib_export.c
@@ -0,0 +1,38 @@
+#include "lib_export.h"
+
+#ifdef APP_FRAMEWORK_SENSOR
+#include "sensor_native_api.h"
+#endif
+
+#ifdef APP_FRAMEWORK_CONNECTION
+#include "connection_native_api.h"
+#endif
+
+#ifdef APP_FRAMEWORK_WGL
+#include "gui_native_api.h"
+#endif
+
+/* More header file here */
+
+static NativeSymbol extended_native_symbol_defs[] = {
+#ifdef APP_FRAMEWORK_SENSOR
+#include "runtime_sensor.inl"
+#endif
+
+#ifdef APP_FRAMEWORK_CONNECTION
+#include "connection.inl"
+#endif
+
+#ifdef APP_FRAMEWORK_WGL
+#include "wamr_gui.inl"
+#endif
+
+ /* More inl file here */
+};
+
+int
+get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis)
+{
+ *p_ext_lib_apis = extended_native_symbol_defs;
+ return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_framework.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_framework.cmake
new file mode 100644
index 000000000..b8a63d856
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app_framework.cmake
@@ -0,0 +1,93 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+add_definitions (-DWASM_ENABLE_APP_FRAMEWORK=1)
+
+set (APP_FRAMEWORK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE )
+ LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${CMAKE_CURRENT_LIST_DIR}/app_ext_lib_export.c)
+endif()
+
+# 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 WASM_APP_LIBS_DIR ${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native)
+ set (WASM_APP_LIBS_DIR ${WASM_APP_LIBS_DIR} PARENT_SCOPE)
+
+ 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)
+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()
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.c
new file mode 100644
index 000000000..1848d0792
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ *
+ *
+ */
+
+static bool
+is_little_endian()
+{
+ long i = 0x01020304;
+ unsigned char *c = (unsigned char *)&i;
+ return (*c == 0x04) ? true : false;
+}
+
+static void
+swap32(uint8 *pData)
+{
+ uint8 value = *pData;
+ *pData = *(pData + 3);
+ *(pData + 3) = value;
+
+ value = *(pData + 1);
+ *(pData + 1) = *(pData + 2);
+ *(pData + 2) = value;
+}
+
+static void
+swap16(uint8 *pData)
+{
+ uint8 value = *pData;
+ *(pData) = *(pData + 1);
+ *(pData + 1) = value;
+}
+
+uint32
+htonl(uint32 value)
+{
+ uint32 ret;
+ if (is_little_endian()) {
+ ret = value;
+ swap32((uint8 *)&ret);
+ return ret;
+ }
+
+ return value;
+}
+
+uint32
+ntohl(uint32 value)
+{
+ return htonl(value);
+}
+
+uint16
+htons(uint16 value)
+{
+ uint16 ret;
+ if (is_little_endian()) {
+ ret = value;
+ swap16((uint8 *)&ret);
+ return ret;
+ }
+
+ return value;
+}
+
+uint16
+ntohs(uint16 value)
+{
+ return htons(value);
+}
+
+char *
+wa_strdup(const char *s)
+{
+ char *s1 = NULL;
+ if (s && (s1 = WA_MALLOC(strlen(s) + 1)))
+ memcpy(s1, s, strlen(s) + 1);
+ return s1;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.h
new file mode 100644
index 000000000..8e10dcb64
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/bh_platform.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_
+#define DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_
+
+#include <stdbool.h>
+
+typedef unsigned char uint8;
+typedef char int8;
+typedef unsigned short uint16;
+typedef short int16;
+typedef unsigned int uint32;
+typedef int int32;
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#ifndef __cplusplus
+#define true 1
+#define false 0
+#define inline __inline
+#endif
+
+// all wasm-app<->native shared source files should use WA_MALLOC/WA_FREE.
+// they will be mapped to different implementations in each side
+#ifndef WA_MALLOC
+#define WA_MALLOC malloc
+#endif
+
+#ifndef WA_FREE
+#define WA_FREE free
+#endif
+
+uint32
+htonl(uint32 value);
+uint32
+ntohl(uint32 value);
+uint16
+htons(uint16 value);
+uint16
+ntohs(uint16 value);
+
+// We are not worried for the WASM world since the sandbox will catch it.
+#define bh_memcpy_s(dst, dst_len, src, src_len) memcpy(dst, src, src_len)
+
+#ifdef NDEBUG
+#define bh_assert(v) (void)0
+#else
+#define bh_assert(v) \
+ do { \
+ if (!(v)) { \
+ int _count; \
+ printf("ASSERTION FAILED: %s, at %s, line %d", #v, __FILE__, \
+ __LINE__); \
+ _count = printf("\n"); \
+ printf("%d\n", _count / (_count - 1)); \
+ } \
+ } while (0)
+#endif
+
+#endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/req_resp_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/req_resp_api.h
new file mode 100644
index 000000000..575c35732
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/req_resp_api.h
@@ -0,0 +1,31 @@
+/*
+ * 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(const char *buf, int size);
+
+void
+wasm_register_resource(const char *url);
+
+void
+wasm_post_request(const char *buf, int size);
+
+void
+wasm_sub_event(const char *url);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _REQ_RESP_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/request.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/request.c
new file mode 100644
index 000000000..3ba44fbc7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/request.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#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"
+
+#define TRANSACTION_TIMEOUT_MS 5000
+
+typedef enum { Reg_Event, Reg_Request } reg_type_t;
+
+typedef struct _res_register {
+ struct _res_register *next;
+ const char *url;
+ reg_type_t reg_type;
+ void (*request_handler)(request_t *);
+} res_register_t;
+
+typedef struct transaction {
+ struct transaction *next;
+ int mid;
+ unsigned int time; /* start time */
+ response_handler_f handler;
+ void *user_data;
+} transaction_t;
+
+static res_register_t *g_resources = NULL;
+
+static transaction_t *g_transactions = NULL;
+
+static user_timer_t g_trans_timer = NULL;
+
+static transaction_t *
+transaction_find(int mid)
+{
+ transaction_t *t = g_transactions;
+
+ while (t) {
+ if (t->mid == mid)
+ return t;
+ t = t->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * new transaction is added to the tail of the list, so the list
+ * is sorted by expiry time naturally.
+ */
+static void
+transaction_add(transaction_t *trans)
+{
+ transaction_t *t;
+
+ if (g_transactions == NULL) {
+ g_transactions = trans;
+ return;
+ }
+
+ t = g_transactions;
+ while (t) {
+ if (t->next == NULL) {
+ t->next = trans;
+ return;
+ }
+ }
+}
+
+static void
+transaction_remove(transaction_t *trans)
+{
+ transaction_t *prev = NULL, *current = g_transactions;
+
+ while (current) {
+ if (current == trans) {
+ if (prev == NULL) {
+ g_transactions = current->next;
+ free(current);
+ return;
+ }
+ prev->next = current->next;
+ free(current);
+ return;
+ }
+ prev = current;
+ current = current->next;
+ }
+}
+
+static bool
+is_event_type(request_t *req)
+{
+ return req->action == COAP_EVENT;
+}
+
+static bool
+register_url_handler(const char *url, request_handler_f request_handler,
+ reg_type_t reg_type)
+{
+ res_register_t *r = g_resources;
+
+ while (r) {
+ if (reg_type == r->reg_type && strcmp(r->url, url) == 0) {
+ r->request_handler = request_handler;
+ return true;
+ }
+ r = r->next;
+ }
+
+ r = (res_register_t *)malloc(sizeof(res_register_t));
+ if (r == NULL)
+ return false;
+
+ memset(r, 0, sizeof(*r));
+
+ r->url = strdup(url);
+ if (!r->url) {
+ free(r);
+ return false;
+ }
+
+ r->request_handler = request_handler;
+ r->reg_type = reg_type;
+ r->next = g_resources;
+ g_resources = r;
+
+ // tell app mgr to route this url to me
+ if (reg_type == Reg_Request)
+ wasm_register_resource(url);
+ else
+ wasm_sub_event(url);
+
+ return true;
+}
+
+bool
+api_register_resource_handler(const char *url,
+ request_handler_f request_handler)
+{
+ return register_url_handler(url, request_handler, Reg_Request);
+}
+
+static void
+transaction_timeout_handler(user_timer_t timer)
+{
+ transaction_t *cur, *expired = NULL;
+ unsigned int elpased_ms, now = wasm_get_sys_tick_ms();
+
+ /*
+ * Since he transaction list is sorted by expiry time naturally,
+ * we can easily get all expired transactions.
+ * */
+ cur = g_transactions;
+ while (cur) {
+ if (now < cur->time)
+ elpased_ms = now + (0xFFFFFFFF - cur->time) + 1;
+ else
+ elpased_ms = now - cur->time;
+
+ if (elpased_ms >= TRANSACTION_TIMEOUT_MS) {
+ g_transactions = cur->next;
+ cur->next = expired;
+ expired = cur;
+ cur = g_transactions;
+ }
+ else {
+ break;
+ }
+ }
+
+ /* call each transaction's handler with response set to NULL */
+ cur = expired;
+ while (cur) {
+ transaction_t *tmp = cur;
+ cur->handler(NULL, cur->user_data);
+ cur = cur->next;
+ free(tmp);
+ }
+
+ /*
+ * If the transaction list is not empty, restart the timer according
+ * to the first transaction. Otherwise, stop the timer.
+ */
+ if (g_transactions != NULL) {
+ unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
+ if (now < g_transactions->time) {
+ elpased_ms = now + (0xFFFFFFFF - g_transactions->time) + 1;
+ }
+ else {
+ elpased_ms = now - g_transactions->time;
+ }
+ ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
+ api_timer_restart(g_trans_timer, ms_to_expiry);
+ }
+ else {
+ api_timer_cancel(g_trans_timer);
+ g_trans_timer = NULL;
+ }
+}
+
+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;
+
+ 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);
+ }
+ }
+
+ wasm_post_request(buffer, size);
+
+ free_req_resp_packet(buffer);
+}
+
+/*
+ *
+ * APIs for the native layers to callback for request/response arrived to this
+ * app
+ *
+ */
+
+void
+on_response(char *buffer, int size)
+{
+ response_t response[1];
+ transaction_t *trans;
+
+ if (NULL == unpack_response(buffer, size, response)) {
+ printf("unpack response failed\n");
+ return;
+ }
+
+ if ((trans = transaction_find(response->mid)) == NULL) {
+ printf("cannot find the transaction\n");
+ return;
+ }
+
+ /*
+ * When the 1st transaction get response:
+ * 1. If the 2nd trans exist, restart the timer according to its expiry
+ * time;
+ * 2. Otherwise, stop the timer since there is no more transactions;
+ */
+ if (trans == g_transactions) {
+ if (trans->next != NULL) {
+ unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
+ if (now < trans->next->time) {
+ elpased_ms = now + (0xFFFFFFFF - trans->next->time) + 1;
+ }
+ else {
+ elpased_ms = now - trans->next->time;
+ }
+ ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
+ api_timer_restart(g_trans_timer, ms_to_expiry);
+ }
+ else {
+ api_timer_cancel(g_trans_timer);
+ g_trans_timer = NULL;
+ }
+ }
+
+ trans->handler(response, trans->user_data);
+ transaction_remove(trans);
+}
+
+void
+on_request(char *buffer, int size)
+{
+ request_t request[1];
+ bool is_event;
+ res_register_t *r = g_resources;
+
+ if (NULL == unpack_request(buffer, size, request)) {
+ printf("unpack request failed\n");
+ return;
+ }
+
+ is_event = is_event_type(request);
+
+ while (r) {
+ if ((is_event && r->reg_type == Reg_Event)
+ || (!is_event && r->reg_type == Reg_Request)) {
+ if (check_url_start(request->url, strlen(request->url), r->url)
+ > 0) {
+ r->request_handler(request);
+ return;
+ }
+ }
+
+ r = r->next;
+ }
+
+ printf("on_request: exit. no service handler\n");
+}
+
+void
+api_response_send(response_t *response)
+{
+ int size;
+ char *buffer = pack_response(response, &size);
+ if (buffer == NULL)
+ return;
+
+ wasm_response_send(buffer, size);
+ free_req_resp_packet(buffer);
+}
+
+/// event api
+
+bool
+api_publish_event(const char *url, int fmt, void *payload, int payload_len)
+{
+ int size;
+ request_t request[1];
+ init_request(request, (char *)url, COAP_EVENT, fmt, payload, payload_len);
+ char *buffer = pack_request(request, &size);
+ if (buffer == NULL)
+ return false;
+ wasm_post_request(buffer, size);
+
+ free_req_resp_packet(buffer);
+
+ return true;
+}
+
+bool
+api_subscribe_event(const char *url, request_handler_f handler)
+{
+ return register_url_handler(url, handler, Reg_Event);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer.c
new file mode 100644
index 000000000..692626ca3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "wa-inc/timer_wasm_app.h"
+#include "timer_api.h"
+
+#if 1
+#include <stdio.h>
+#else
+#define printf (...)
+#endif
+
+struct user_timer {
+ struct user_timer *next;
+ int timer_id;
+ void (*user_timer_callback)(user_timer_t);
+};
+
+struct user_timer *g_timers = NULL;
+
+user_timer_t
+api_timer_create(int interval, bool is_period, bool auto_start,
+ on_user_timer_update_f on_timer_update)
+{
+
+ int timer_id = wasm_create_timer(interval, is_period, auto_start);
+
+ // TODO
+ struct user_timer *timer =
+ (struct user_timer *)malloc(sizeof(struct user_timer));
+ if (timer == NULL) {
+ // TODO: remove the timer_id
+ printf("### api_timer_create malloc faild!!! \n");
+ return NULL;
+ }
+
+ memset(timer, 0, sizeof(*timer));
+ timer->timer_id = timer_id;
+ timer->user_timer_callback = on_timer_update;
+
+ if (g_timers == NULL)
+ g_timers = timer;
+ else {
+ timer->next = g_timers;
+ g_timers = timer;
+ }
+
+ return timer;
+}
+
+void
+api_timer_cancel(user_timer_t timer)
+{
+ user_timer_t t = g_timers, prev = NULL;
+
+ wasm_timer_cancel(timer->timer_id);
+
+ while (t) {
+ if (t == timer) {
+ if (prev == NULL) {
+ g_timers = t->next;
+ free(t);
+ }
+ else {
+ prev->next = t->next;
+ free(t);
+ }
+ return;
+ }
+ else {
+ prev = t;
+ t = t->next;
+ }
+ }
+}
+
+void
+api_timer_restart(user_timer_t timer, int interval)
+{
+ wasm_timer_restart(timer->timer_id, interval);
+}
+
+void
+on_timer_callback(int timer_id)
+{
+ struct user_timer *t = g_timers;
+
+ while (t) {
+ if (t->timer_id == timer_id) {
+ t->user_timer_callback(t);
+ break;
+ }
+ t = t->next;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer_api.h
new file mode 100644
index 000000000..1fc7555ef
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/timer_api.h
@@ -0,0 +1,36 @@
+/*
+ * 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/request.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/request.h
new file mode 100644
index 000000000..25830f0a4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/request.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AEE_REQUEST_H_
+#define _AEE_REQUEST_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
+ *
+ * @brief Define the signature of callback function for API
+ * api_register_resource_handler() to handle request or for API
+ * api_subscribe_event() to handle event.
+ *
+ * @param request pointer of the request to be handled
+ *
+ * @see api_register_resource_handler
+ * @see api_subscribe_event
+ */
+typedef void (*request_handler_f)(request_t *request);
+
+/**
+ * @typedef response_handler_f
+ *
+ * @brief Define the signature of callback function for API
+ * api_send_request() to handle response of a request.
+ *
+ * @param response pointer of the response to be handled
+ * @param user_data user data associated with the request which is set when
+ * calling api_send_request().
+ *
+ * @see api_send_request
+ */
+typedef void (*response_handler_f)(response_t *response, void *user_data);
+
+/*
+ *****************
+ * Request APIs
+ *****************
+ */
+
+/**
+ * @brief Register resource.
+ *
+ * @param url url of the resource
+ * @param handler callback function to handle the request to the resource
+ *
+ * @return true if success, false otherwise
+ */
+bool
+api_register_resource_handler(const char *url, request_handler_f handler);
+
+/**
+ * @brief Send request asynchronously.
+ *
+ * @param request pointer of the request to be sent
+ * @param response_handler callback function to handle the response
+ * @param user_data user data
+ */
+void
+api_send_request(request_t *request, response_handler_f response_handler,
+ void *user_data);
+
+/**
+ * @brief Send response.
+ *
+ * @param response pointer of the response to be sent
+ *
+ * @par
+ * @code
+ * void res1_handler(request_t *request)
+ * {
+ * response_t response[1];
+ * make_response_for_request(request, response);
+ * set_response(response, DELETED_2_02, 0, NULL, 0);
+ * api_response_send(response);
+ * }
+ * @endcode
+ */
+void
+api_response_send(response_t *response);
+
+/*
+ *****************
+ * Event APIs
+ *****************
+ */
+
+/**
+ * @brief Publish an event.
+ *
+ * @param url url of the event
+ * @param fmt format of the event payload
+ * @param payload payload of the event
+ * @param payload_len length in bytes of the event payload
+ *
+ * @return true if success, false otherwise
+ */
+bool
+api_publish_event(const char *url, int fmt, void *payload, int payload_len);
+
+/**
+ * @brief Subscribe an event.
+ *
+ * @param url url of the event
+ * @param handler callback function to handle the event.
+ *
+ * @return true if success, false otherwise
+ */
+bool
+api_subscribe_event(const char *url, request_handler_f handler);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/timer_wasm_app.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/timer_wasm_app.h
new file mode 100644
index 000000000..cf158a365
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wa-inc/timer_wasm_app.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AEE_TIMER_H_
+#define _AEE_TIMER_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* board producer define user_timer */
+struct user_timer;
+typedef struct user_timer *user_timer_t;
+
+/**
+ * @typedef on_user_timer_update_f
+ *
+ * @brief Define the signature of callback function for API api_timer_create().
+ *
+ * @param timer the timer
+ *
+ * @see api_timer_create
+ */
+typedef void (*on_user_timer_update_f)(user_timer_t timer);
+
+/*
+ *****************
+ * Timer APIs
+ *****************
+ */
+
+/**
+ * @brief Create timer.
+ *
+ * @param interval timer interval
+ * @param is_period whether the timer is periodic
+ * @param auto_start whether start the timer immediately after created
+ * @param on_timer_update callback function called when timer expired
+ *
+ * @return the timer created if success, NULL otherwise
+ */
+user_timer_t
+api_timer_create(int interval, bool is_period, bool auto_start,
+ on_user_timer_update_f on_timer_update);
+
+/**
+ * @brief Cancel timer.
+ *
+ * @param timer the timer to cancel
+ */
+void
+api_timer_cancel(user_timer_t timer);
+
+/**
+ * @brief Restart timer.
+ *
+ * @param timer the timer to cancel
+ * @param interval the timer interval
+ */
+void
+api_timer_restart(user_timer_t timer, int interval);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.cmake
new file mode 100644
index 000000000..2313df99d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.h
new file mode 100644
index 000000000..e7be8a4c1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/app/wasm_app.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _LIB_AEE_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib.inl b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib.inl
new file mode 100644
index 000000000..3c228cc93
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib.inl
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+ EXPORT_WASM_API_WITH_SIG(wasm_register_resource, "($)"),
+ EXPORT_WASM_API_WITH_SIG(wasm_response_send, "(*~)i"),
+ EXPORT_WASM_API_WITH_SIG(wasm_post_request, "(*~)"),
+ EXPORT_WASM_API_WITH_SIG(wasm_sub_event, "($)"),
+ EXPORT_WASM_API_WITH_SIG(wasm_create_timer, "(iii)i"),
+ EXPORT_WASM_API_WITH_SIG(wasm_timer_destroy, "(i)"),
+ EXPORT_WASM_API_WITH_SIG(wasm_timer_cancel, "(i)"),
+ EXPORT_WASM_API_WITH_SIG(wasm_timer_restart, "(ii)"),
+ EXPORT_WASM_API_WITH_SIG(wasm_get_sys_tick_ms, "()i"),
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib_export.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib_export.c
new file mode 100644
index 000000000..19ac7185c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/base_lib_export.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lib_export.h"
+#include "req_resp_native_api.h"
+#include "timer_native_api.h"
+
+static NativeSymbol extended_native_symbol_defs[] = {
+/* TODO: use macro EXPORT_WASM_API() or EXPORT_WASM_API2() to
+ add functions to register. */
+#include "base_lib.inl"
+};
+
+uint32
+get_base_lib_export_apis(NativeSymbol **p_base_lib_apis)
+{
+ *p_base_lib_apis = extended_native_symbol_defs;
+ return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/req_resp_native_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/req_resp_native_api.h
new file mode 100644
index 000000000..3e5938772
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/req_resp_native_api.h
@@ -0,0 +1,29 @@
+/*
+ * 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"
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size);
+void
+wasm_register_resource(wasm_exec_env_t exec_env, char *url);
+void
+wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size);
+void
+wasm_sub_event(wasm_exec_env_t exec_env, char *url);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _REQ_RESP_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/request_response.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/request_response.c
new file mode 100644
index 000000000..674ba5e9d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/request_response.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "app_manager_export.h"
+#include "coap_ext.h"
+#include "wasm_export.h"
+#include "bh_assert.h"
+
+extern void
+module_request_handler(request_t *request, void *user_data);
+
+bool
+wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size)
+{
+ if (buffer != NULL) {
+ response_t response[1];
+
+ if (NULL == unpack_response(buffer, size, response))
+ return false;
+
+ am_send_response(response);
+
+ return true;
+ }
+
+ return false;
+}
+
+void
+wasm_register_resource(wasm_exec_env_t exec_env, char *url)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (url != NULL) {
+ unsigned int mod_id =
+ app_manager_get_module_id(Module_WASM_App, module_inst);
+ bh_assert(mod_id != ID_NONE);
+ am_register_resource(url, module_request_handler, mod_id);
+ }
+}
+
+void
+wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (buffer != NULL) {
+ request_t req[1];
+
+ if (!unpack_request(buffer, size, req))
+ return;
+
+ // TODO: add permission check, ensure app can't do harm
+
+ // set sender to help dispatch the response to the sender ap
+ 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);
+ }
+}
+
+void
+wasm_sub_event(wasm_exec_env_t exec_env, char *url)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (url != NULL) {
+ unsigned int mod_id =
+ app_manager_get_module_id(Module_WASM_App, module_inst);
+
+ bh_assert(mod_id != ID_NONE);
+ am_register_event(url, mod_id);
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/runtime_lib.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/runtime_lib.h
new file mode 100644
index 000000000..477b663b2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/runtime_lib.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef LIB_BASE_RUNTIME_LIB_H_
+#define LIB_BASE_RUNTIME_LIB_H_
+
+#include "runtime_timer.h"
+
+bool
+init_wasm_timer();
+void
+exit_wasm_timer();
+timer_ctx_t
+get_wasm_timer_ctx();
+timer_ctx_t
+create_wasm_timer_ctx(unsigned int module_id, int prealloc_num);
+void
+destroy_module_timer_ctx(unsigned int module_id);
+
+#endif /* LIB_BASE_RUNTIME_LIB_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_native_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_native_api.h
new file mode 100644
index 000000000..138e7c60d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_native_api.h
@@ -0,0 +1,40 @@
+/*
+ * 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"
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int timer_id_t;
+
+/*
+ * timer interfaces
+ */
+
+typedef unsigned int timer_id_t;
+
+timer_id_t
+wasm_create_timer(wasm_exec_env_t exec_env, int interval, bool is_period,
+ bool auto_start);
+void
+wasm_timer_destroy(wasm_exec_env_t exec_env, timer_id_t timer_id);
+void
+wasm_timer_cancel(wasm_exec_env_t exec_env, timer_id_t timer_id);
+void
+wasm_timer_restart(wasm_exec_env_t exec_env, timer_id_t timer_id, int interval);
+uint32
+wasm_get_sys_tick_ms(wasm_exec_env_t exec_env);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _TIMER_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_wrapper.c
new file mode 100644
index 000000000..246868849
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/timer_wrapper.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "app_manager_export.h"
+#include "../app-manager/module_wasm_app.h"
+#include "timer_native_api.h"
+
+typedef struct {
+ bh_list_link l;
+ timer_ctx_t timer_ctx;
+} timer_ctx_node_t;
+
+static bool timer_thread_run = true;
+
+static bh_list g_timer_ctx_list;
+static korp_cond g_timer_ctx_list_cond;
+static korp_mutex g_timer_ctx_list_mutex;
+
+void
+wasm_timer_callback(timer_id_t id, unsigned int mod_id)
+{
+ module_data *module = module_data_list_lookup_id(mod_id);
+ if (module == NULL)
+ return;
+
+ // !!! the length parameter must be 0, so the receiver will
+ // not free the payload pointer.
+ bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *)(uintptr_t)id, 0);
+}
+
+/**
+ * why we create a separate link for module timer contexts
+ * rather than traverse the module list?
+ * It helps to reduce the lock frequency for the module list.
+ * Also when we lock the module list and then call the callback for
+ * timer expire, the callback is request the list lock again for lookup
+ * the module from module id. It is for avoiding that situation.
+ */
+
+void *
+thread_modulers_timer_check(void *arg)
+{
+ uint32 ms_to_expiry;
+ uint64 us_to_wait;
+
+ while (timer_thread_run) {
+ ms_to_expiry = (uint32)-1;
+ os_mutex_lock(&g_timer_ctx_list_mutex);
+ timer_ctx_node_t *elem =
+ (timer_ctx_node_t *)bh_list_first_elem(&g_timer_ctx_list);
+ while (elem) {
+ uint32 next = check_app_timers(elem->timer_ctx);
+ if (next != (uint32)-1) {
+ if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
+ ms_to_expiry = next;
+ }
+
+ elem = (timer_ctx_node_t *)bh_list_elem_next(elem);
+ }
+ os_mutex_unlock(&g_timer_ctx_list_mutex);
+
+ if (ms_to_expiry == (uint32)-1)
+ us_to_wait = BHT_WAIT_FOREVER;
+ else
+ us_to_wait = (uint64)ms_to_expiry * 1000;
+ os_mutex_lock(&g_timer_ctx_list_mutex);
+ os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
+ us_to_wait);
+ os_mutex_unlock(&g_timer_ctx_list_mutex);
+ }
+
+ return NULL;
+}
+
+void
+wakeup_modules_timer_thread(timer_ctx_t ctx)
+{
+ os_mutex_lock(&g_timer_ctx_list_mutex);
+ os_cond_signal(&g_timer_ctx_list_cond);
+ os_mutex_unlock(&g_timer_ctx_list_mutex);
+}
+
+bool
+init_wasm_timer()
+{
+ korp_tid tm_tid;
+ bh_list_init(&g_timer_ctx_list);
+
+ if (os_cond_init(&g_timer_ctx_list_cond) != 0) {
+ return false;
+ }
+ /* temp solution for: thread_modulers_timer_check thread
+ would recursive lock the mutex */
+ if (os_recursive_mutex_init(&g_timer_ctx_list_mutex) != 0) {
+ goto fail1;
+ }
+
+ if (0
+ != os_thread_create(&tm_tid, thread_modulers_timer_check, NULL,
+ BH_APPLET_PRESERVED_STACK_SIZE)) {
+ goto fail2;
+ }
+
+ return true;
+
+fail2:
+ os_mutex_destroy(&g_timer_ctx_list_mutex);
+
+fail1:
+ os_cond_destroy(&g_timer_ctx_list_cond);
+
+ return false;
+}
+
+void
+exit_wasm_timer()
+{
+ timer_thread_run = false;
+}
+
+timer_ctx_t
+create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
+{
+ timer_ctx_t ctx =
+ create_timer_ctx(wasm_timer_callback, wakeup_modules_timer_thread,
+ prealloc_num, module_id);
+
+ if (ctx == NULL)
+ return NULL;
+
+ timer_ctx_node_t *node =
+ (timer_ctx_node_t *)wasm_runtime_malloc(sizeof(timer_ctx_node_t));
+ if (node == NULL) {
+ destroy_timer_ctx(ctx);
+ return NULL;
+ }
+ memset(node, 0, sizeof(*node));
+ node->timer_ctx = ctx;
+
+ os_mutex_lock(&g_timer_ctx_list_mutex);
+ bh_list_insert(&g_timer_ctx_list, node);
+ os_mutex_unlock(&g_timer_ctx_list_mutex);
+
+ return ctx;
+}
+
+void
+destroy_module_timer_ctx(unsigned int module_id)
+{
+ timer_ctx_node_t *elem;
+
+ os_mutex_lock(&g_timer_ctx_list_mutex);
+ elem = (timer_ctx_node_t *)bh_list_first_elem(&g_timer_ctx_list);
+ while (elem) {
+ if (timer_ctx_get_owner(elem->timer_ctx) == module_id) {
+ bh_list_remove(&g_timer_ctx_list, elem);
+ destroy_timer_ctx(elem->timer_ctx);
+ wasm_runtime_free(elem);
+ break;
+ }
+
+ elem = (timer_ctx_node_t *)bh_list_elem_next(elem);
+ }
+ os_mutex_unlock(&g_timer_ctx_list_mutex);
+}
+
+timer_ctx_t
+get_wasm_timer_ctx(wasm_module_inst_t module_inst)
+{
+ module_data *m = app_manager_get_module_data(Module_WASM_App, module_inst);
+ if (m == NULL)
+ return NULL;
+ return m->timer_ctx;
+}
+
+timer_id_t
+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_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_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_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);
+}
+
+uint32
+wasm_get_sys_tick_ms(wasm_exec_env_t exec_env)
+{
+ return (uint32)bh_get_tick_ms();
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/wasm_lib.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/wasm_lib.cmake
new file mode 100644
index 000000000..223320b32
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/base/native/wasm_lib.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (WASM_LIB_BASE_DIR ${CMAKE_CURRENT_LIST_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_APP_LIB_CURRENT_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection.c
new file mode 100644
index 000000000..b5b2bfc54
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wa-inc/connection.h"
+#include "connection_api.h"
+
+/* Raw connection structure */
+typedef struct _connection {
+ /* Next connection */
+ struct _connection *next;
+
+ /* Handle of the connection */
+ uint32 handle;
+
+ /* Callback function called when event on this connection occurs */
+ on_connection_event_f on_event;
+
+ /* User data */
+ void *user_data;
+} connection_t;
+
+/* Raw connections list */
+static connection_t *g_conns = NULL;
+
+connection_t *
+api_open_connection(const char *name, attr_container_t *args,
+ on_connection_event_f on_event, void *user_data)
+{
+ connection_t *conn;
+ char *args_buffer = (char *)args;
+ uint32 handle, args_len = attr_container_get_serialize_length(args);
+
+ handle = wasm_open_connection(name, args_buffer, args_len);
+ if (handle == -1)
+ return NULL;
+
+ conn = (connection_t *)malloc(sizeof(*conn));
+ if (conn == NULL) {
+ wasm_close_connection(handle);
+ return NULL;
+ }
+
+ memset(conn, 0, sizeof(*conn));
+ conn->handle = handle;
+ conn->on_event = on_event;
+ conn->user_data = user_data;
+
+ if (g_conns != NULL) {
+ conn->next = g_conns;
+ g_conns = conn;
+ }
+ else {
+ g_conns = conn;
+ }
+
+ return conn;
+}
+
+void
+api_close_connection(connection_t *c)
+{
+ connection_t *conn = g_conns, *prev = NULL;
+
+ while (conn) {
+ if (conn == c) {
+ wasm_close_connection(c->handle);
+ if (prev != NULL)
+ prev->next = conn->next;
+ else
+ g_conns = conn->next;
+ free(conn);
+ return;
+ }
+ else {
+ prev = conn;
+ conn = conn->next;
+ }
+ }
+}
+
+int
+api_send_on_connection(connection_t *conn, const char *data, uint32 len)
+{
+ return wasm_send_on_connection(conn->handle, data, len);
+}
+
+bool
+api_config_connection(connection_t *conn, attr_container_t *cfg)
+{
+ char *cfg_buffer = (char *)cfg;
+ uint32 cfg_len = attr_container_get_serialize_length(cfg);
+
+ return wasm_config_connection(conn->handle, cfg_buffer, cfg_len);
+}
+
+void
+on_connection_data(uint32 handle, char *buffer, uint32 len)
+{
+ connection_t *conn = g_conns;
+
+ while (conn != NULL) {
+ if (conn->handle == handle) {
+ if (len == 0) {
+ conn->on_event(conn, CONN_EVENT_TYPE_DISCONNECT, NULL, 0,
+ conn->user_data);
+ }
+ else {
+ conn->on_event(conn, CONN_EVENT_TYPE_DATA, buffer, len,
+ conn->user_data);
+ }
+
+ return;
+ }
+ conn = conn->next;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection_api.h
new file mode 100644
index 000000000..22bd5a182
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/connection_api.h
@@ -0,0 +1,31 @@
+/*
+ * 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(const char *name, char *args_buf, uint32 args_buf_len);
+
+void
+wasm_close_connection(uint32 handle);
+
+int
+wasm_send_on_connection(uint32 handle, const char *data, uint32 data_len);
+
+bool
+wasm_config_connection(uint32 handle, const char *cfg_buf, uint32 cfg_buf_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of CONNECTION_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wa-inc/connection.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wa-inc/connection.h
new file mode 100644
index 000000000..823eaec74
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wa-inc/connection.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _CONNECTION_H_
+#define _CONNECTION_H_
+
+#include "bi-inc/attr_container.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _connection;
+typedef struct _connection connection_t;
+
+/* 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 on_connection_event_f
+ *
+ * @param conn the connection that the event belongs to
+ * @param type event type
+ * @param data the data received for CONN_EVENT_TYPE_DATA event
+ * @param len length of the data in byte
+ * @param user_data user data
+ */
+typedef void (*on_connection_event_f)(connection_t *conn,
+ conn_event_type_t type, const char *data,
+ uint32 len, void *user_data);
+
+/*
+ *****************
+ * Connection API's
+ *****************
+ */
+
+/*
+ * @brief Open a connection.
+ *
+ * @param name name of the connection, "TCP", "UDP" or "UART"
+ * @param args connection arguments, such as: ip:127.0.0.1, port:8888
+ * @param on_event callback function called when event occurs
+ * @param user_data user data
+ *
+ * @return the connection or NULL means fail
+ */
+connection_t *
+api_open_connection(const char *name, attr_container_t *args,
+ on_connection_event_f on_event, void *user_data);
+
+/*
+ * @brief Close a connection.
+ *
+ * @param conn connection
+ */
+void
+api_close_connection(connection_t *conn);
+
+/*
+ * Send data to the connection in non-blocking manner which returns immediately
+ *
+ * @param conn the connection
+ * @param data data buffer to be sent
+ * @param len length of the data in byte
+ *
+ * @return actual length sent, or -1 if fail(maybe underlying buffer is full)
+ */
+int
+api_send_on_connection(connection_t *conn, const char *data, uint32 len);
+
+/*
+ * @brief Configure connection.
+ *
+ * @param conn the connection
+ * @param cfg configurations
+ *
+ * @return true if success, false otherwise
+ */
+bool
+api_config_connection(connection_t *conn, attr_container_t *cfg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wasm_app.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/app/wasm_app.cmake
new file mode 100644
index 000000000..ca4e02599
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection.inl b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection.inl
new file mode 100644
index 000000000..b2d01aa9f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection.inl
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+EXPORT_WASM_API_WITH_SIG(wasm_open_connection, "($*~)i"),
+EXPORT_WASM_API_WITH_SIG(wasm_close_connection, "(i)"),
+EXPORT_WASM_API_WITH_SIG(wasm_send_on_connection, "(i*~)i"),
+EXPORT_WASM_API_WITH_SIG(wasm_config_connection, "(i*~)i"),
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_lib.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_lib.h
new file mode 100644
index 000000000..3e182cbb8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_lib.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef CONNECTION_LIB_H_
+#define CONNECTION_LIB_H_
+
+#include "bi-inc/attr_container.h"
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This file defines connection library which should be implemented by
+ * different platforms
+ */
+
+/*
+ * @brief Open a connection.
+ *
+ * @param name name of the connection, "TCP", "UDP" or "UART"
+ * @param args connection arguments, such as: ip:127.0.0.1, port:8888
+ *
+ * @return 0~0xFFFFFFFE means id of the connection, otherwise(-1) means fail
+ */
+typedef uint32 (*connection_open_f)(wasm_module_inst_t module_inst,
+ const char *name, attr_container_t *args);
+
+/*
+ * @brief Close a connection.
+ *
+ * @param handle of the connection
+ */
+typedef void (*connection_close_f)(uint32 handle);
+
+/*
+ * @brief Send data to the connection in non-blocking manner.
+ *
+ * @param handle of the connection
+ * @param data data buffer to be sent
+ * @param len length of the data in byte
+ *
+ * @return actual length sent, -1 if fail
+ */
+typedef int (*connection_send_f)(uint32 handle, const char *data, int len);
+
+/*
+ * @brief Configure connection.
+ *
+ * @param handle of the connection
+ * @param cfg configurations
+ *
+ * @return true if success, false otherwise
+ */
+typedef bool (*connection_config_f)(uint32 handle, attr_container_t *cfg);
+
+/* Raw connection interface for platform to implement */
+typedef struct _connection_interface {
+ connection_open_f _open;
+ connection_close_f _close;
+ connection_send_f _send;
+ connection_config_f _config;
+} connection_interface_t;
+
+/* Platform must define this interface */
+extern connection_interface_t connection_impl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONNECTION_LIB_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_native_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_native_api.h
new file mode 100644
index 000000000..42a2508f1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_native_api.h
@@ -0,0 +1,36 @@
+/*
+ * 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"
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * connection interfaces
+ */
+
+uint32
+wasm_open_connection(wasm_exec_env_t exec_env, char *name, char *args_buf,
+ uint32 len);
+void
+wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle);
+int
+wasm_send_on_connection(wasm_exec_env_t exec_env, uint32 handle, char *data,
+ uint32 len);
+bool
+wasm_config_connection(wasm_exec_env_t exec_env, uint32 handle, char *cfg_buf,
+ uint32 len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of CONNECTION_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_wrapper.c
new file mode 100644
index 000000000..7c20b51d0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/connection_wrapper.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "connection_lib.h"
+#include "wasm_export.h"
+#include "native_interface.h"
+#include "connection_native_api.h"
+
+/* Note:
+ *
+ * This file is the consumer of connection lib which is implemented by different
+ * platforms
+ */
+
+uint32
+wasm_open_connection(wasm_exec_env_t exec_env, char *name, char *args_buf,
+ uint32 len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ attr_container_t *args;
+
+ args = (attr_container_t *)args_buf;
+
+ if (connection_impl._open != NULL)
+ return connection_impl._open(module_inst, name, args);
+
+ return -1;
+}
+
+void
+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_exec_env_t exec_env, uint32 handle, char *data,
+ uint32 len)
+{
+ if (connection_impl._send != NULL)
+ return connection_impl._send(handle, data, len);
+
+ return -1;
+}
+
+bool
+wasm_config_connection(wasm_exec_env_t exec_env, uint32 handle, char *cfg_buf,
+ uint32 len)
+{
+ attr_container_t *cfg;
+
+ cfg = (attr_container_t *)cfg_buf;
+
+ if (connection_impl._config != NULL)
+ return connection_impl._config(handle, cfg);
+
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.c
new file mode 100644
index 000000000..054eb59fd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "conn_tcp.h"
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int
+tcp_open(char *address, uint16 port)
+{
+ int sock, ret;
+ struct sockaddr_in servaddr;
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = inet_addr(address);
+ servaddr.sin_port = htons(port);
+
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock == -1)
+ return -1;
+
+ ret = connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr));
+ if (ret == -1) {
+ close(sock);
+ return -1;
+ }
+
+ /* Put the socket in non-blocking mode */
+ if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+tcp_send(int sock, const char *data, int size)
+{
+ return send(sock, data, size, 0);
+}
+
+int
+tcp_recv(int sock, char *buffer, int buf_size)
+{
+ return recv(sock, buffer, buf_size, 0);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.h
new file mode 100644
index 000000000..c4d5cc86a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_tcp.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef CONN_LINUX_TCP_H_
+#define CONN_LINUX_TCP_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+tcp_open(char *address, uint16 port);
+
+int
+tcp_send(int sock, const char *data, int size);
+
+int
+tcp_recv(int sock, char *buffer, int buf_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.c
new file mode 100644
index 000000000..0bcdc93f7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "conn_uart.h"
+
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+static int
+parse_baudrate(int baud)
+{
+ switch (baud) {
+ case 9600:
+ return B9600;
+ case 19200:
+ return B19200;
+ case 38400:
+ return B38400;
+ case 57600:
+ return B57600;
+ case 115200:
+ return B115200;
+ case 230400:
+ return B230400;
+ case 460800:
+ return B460800;
+ case 500000:
+ return B500000;
+ case 576000:
+ return B576000;
+ case 921600:
+ return B921600;
+ case 1000000:
+ return B1000000;
+ case 1152000:
+ return B1152000;
+ case 1500000:
+ return B1500000;
+ case 2000000:
+ return B2000000;
+ case 2500000:
+ return B2500000;
+ case 3000000:
+ return B3000000;
+ case 3500000:
+ return B3500000;
+ case 4000000:
+ return B4000000;
+ default:
+ return -1;
+ }
+}
+
+int
+uart_open(char *device, int baudrate)
+{
+ int uart_fd;
+ struct termios uart_term;
+
+ uart_fd = open(device, O_RDWR | O_NOCTTY);
+
+ if (uart_fd < 0)
+ return -1;
+
+ memset(&uart_term, 0, sizeof(uart_term));
+ uart_term.c_cflag = parse_baudrate(baudrate) | CS8 | CLOCAL | CREAD;
+ uart_term.c_iflag = IGNPAR;
+ uart_term.c_oflag = 0;
+
+ /* set noncanonical mode */
+ uart_term.c_lflag = 0;
+ uart_term.c_cc[VTIME] = 30;
+ uart_term.c_cc[VMIN] = 1;
+ tcflush(uart_fd, TCIFLUSH);
+
+ if (tcsetattr(uart_fd, TCSANOW, &uart_term) != 0) {
+ close(uart_fd);
+ return -1;
+ }
+
+ /* Put the fd in non-blocking mode */
+ if (fcntl(uart_fd, F_SETFL, fcntl(uart_fd, F_GETFL) | O_NONBLOCK) < 0) {
+ close(uart_fd);
+ return -1;
+ }
+
+ return uart_fd;
+}
+
+int
+uart_send(int fd, const char *data, int size)
+{
+ return write(fd, data, size);
+}
+
+int
+uart_recv(int fd, char *buffer, int buf_size)
+{
+ return read(fd, buffer, buf_size);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.h
new file mode 100644
index 000000000..443167026
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_uart.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef CONN_LINUX_UART_H_
+#define CONN_LINUX_UART_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+uart_open(char *device, int baudrate);
+
+int
+uart_send(int fd, const char *data, int size);
+
+int
+uart_recv(int fd, char *buffer, int buf_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.c
new file mode 100644
index 000000000..61652b14d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "conn_udp.h"
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int
+udp_open(uint16 port)
+{
+ int sock, ret;
+ struct sockaddr_in addr;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1)
+ return -1;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+
+ ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret == -1) {
+ close(sock);
+ return -1;
+ }
+
+ /* Put the socket in non-blocking mode */
+ if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+udp_send(int sock, struct sockaddr *dest, const char *data, int size)
+{
+ return sendto(sock, data, size, MSG_CONFIRM, dest, sizeof(*dest));
+}
+
+int
+udp_recv(int sock, char *buffer, int buf_size)
+{
+ struct sockaddr_in remaddr;
+ socklen_t addrlen = sizeof(remaddr);
+
+ return recvfrom(sock, buffer, buf_size, 0, (struct sockaddr *)&remaddr,
+ &addrlen);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.h
new file mode 100644
index 000000000..377c26eb1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/conn_udp.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef CONN_LINUX_UDP_H_
+#define CONN_LINUX_UDP_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+udp_open(uint16 port);
+
+int
+udp_send(int sock, struct sockaddr *dest, const char *data, int size);
+
+int
+udp_recv(int sock, char *buffer, int buf_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.c
new file mode 100644
index 000000000..001446206
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/*
+ * Note:
+ * This file implements the linux version connection library which is
+ * defined in connection_lib.h.
+ * It also provides a reference implementation of connections manager.
+ */
+
+#include "connection_lib.h"
+#include "bh_platform.h"
+#include "app_manager_export.h"
+#include "module_wasm_app.h"
+#include "conn_tcp.h"
+#include "conn_udp.h"
+#include "conn_uart.h"
+
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+
+#define MAX_EVENTS 10
+#define IO_BUF_SIZE 256
+
+static bool polling_thread_run = true;
+
+/* Connection type */
+typedef enum conn_type {
+ CONN_TYPE_TCP,
+ CONN_TYPE_UDP,
+ CONN_TYPE_UART,
+ CONN_TYPE_UNKNOWN
+} conn_type_t;
+
+/* Sys connection */
+typedef struct sys_connection {
+ /* Next connection */
+ struct sys_connection *next;
+
+ /* Type */
+ conn_type_t type;
+
+ /* Handle to interact with wasm app */
+ uint32 handle;
+
+ /* Underlying connection ID, may be socket fd */
+ int fd;
+
+ /* Module id that the connection belongs to */
+ uint32 module_id;
+
+ /* Argument, such as dest addr for udp */
+ void *arg;
+} sys_connection_t;
+
+/* Epoll instance */
+static int epollfd;
+
+/* Connections list */
+static sys_connection_t *g_connections = NULL;
+
+/* Max handle */
+static uint32 g_handle_max = 0;
+
+/* Lock to protect g_connections and g_handle_max */
+static korp_mutex g_lock;
+
+/* Epoll events */
+static struct epoll_event epoll_events[MAX_EVENTS];
+
+/* Buffer to receive data */
+static char io_buf[IO_BUF_SIZE];
+
+static uint32
+_conn_open(wasm_module_inst_t module_inst, const char *name,
+ attr_container_t *args);
+static void
+_conn_close(uint32 handle);
+static int
+_conn_send(uint32 handle, const char *data, int len);
+static bool
+_conn_config(uint32 handle, attr_container_t *cfg);
+
+/* clang-format off */
+/*
+ * Platform implementation of connection library
+ */
+connection_interface_t connection_impl = {
+ ._open = _conn_open,
+ ._close = _conn_close,
+ ._send = _conn_send,
+ ._config = _conn_config
+};
+/* clang-format on */
+
+static void
+add_connection(sys_connection_t *conn)
+{
+ os_mutex_lock(&g_lock);
+
+ g_handle_max++;
+ if (g_handle_max == -1)
+ g_handle_max++;
+ conn->handle = g_handle_max;
+
+ if (g_connections) {
+ conn->next = g_connections;
+ g_connections = conn;
+ }
+ else {
+ g_connections = conn;
+ }
+
+ os_mutex_unlock(&g_lock);
+}
+
+#define FREE_CONNECTION(conn) \
+ do { \
+ if (conn->arg) \
+ wasm_runtime_free(conn->arg); \
+ wasm_runtime_free(conn); \
+ } while (0)
+
+static int
+get_app_conns_num(uint32 module_id)
+{
+ sys_connection_t *conn;
+ int num = 0;
+
+ os_mutex_lock(&g_lock);
+
+ conn = g_connections;
+ while (conn) {
+ if (conn->module_id == module_id)
+ num++;
+ conn = conn->next;
+ }
+
+ os_mutex_unlock(&g_lock);
+
+ return num;
+}
+
+static sys_connection_t *
+find_connection(uint32 handle, bool remove_found)
+{
+ sys_connection_t *conn, *prev = NULL;
+
+ os_mutex_lock(&g_lock);
+
+ conn = g_connections;
+ while (conn) {
+ if (conn->handle == handle) {
+ if (remove_found) {
+ if (prev != NULL) {
+ prev->next = conn->next;
+ }
+ else {
+ g_connections = conn->next;
+ }
+ }
+ os_mutex_unlock(&g_lock);
+ return conn;
+ }
+ else {
+ prev = conn;
+ conn = conn->next;
+ }
+ }
+
+ os_mutex_unlock(&g_lock);
+
+ return NULL;
+}
+
+static void
+cleanup_connections(uint32 module_id)
+{
+ sys_connection_t *conn, *prev = NULL;
+
+ os_mutex_lock(&g_lock);
+
+ conn = g_connections;
+ while (conn) {
+ if (conn->module_id == module_id) {
+ epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL);
+ close(conn->fd);
+
+ if (prev != NULL) {
+ prev->next = conn->next;
+ FREE_CONNECTION(conn);
+ conn = prev->next;
+ }
+ else {
+ g_connections = conn->next;
+ FREE_CONNECTION(conn);
+ conn = g_connections;
+ }
+ }
+ else {
+ prev = conn;
+ conn = conn->next;
+ }
+ }
+
+ os_mutex_unlock(&g_lock);
+}
+
+static conn_type_t
+get_conn_type(const char *name)
+{
+ if (strcmp(name, "TCP") == 0)
+ return CONN_TYPE_TCP;
+ if (strcmp(name, "UDP") == 0)
+ return CONN_TYPE_UDP;
+ if (strcmp(name, "UART") == 0)
+ return CONN_TYPE_UART;
+
+ return CONN_TYPE_UNKNOWN;
+}
+
+/* --- connection lib function --- */
+static uint32
+_conn_open(wasm_module_inst_t module_inst, const char *name,
+ attr_container_t *args)
+{
+ int fd;
+ sys_connection_t *conn;
+ struct epoll_event ev;
+ uint32 module_id = app_manager_get_module_id(Module_WASM_App, module_inst);
+ bh_assert(module_id != ID_NONE);
+
+ if (get_app_conns_num(module_id) >= MAX_CONNECTION_PER_APP)
+ return -1;
+
+ conn = (sys_connection_t *)wasm_runtime_malloc(sizeof(*conn));
+ if (conn == NULL)
+ return -1;
+
+ memset(conn, 0, sizeof(*conn));
+ conn->module_id = module_id;
+ conn->type = get_conn_type(name);
+
+ /* Generate a handle and add to list */
+ add_connection(conn);
+
+ if (conn->type == CONN_TYPE_TCP) {
+ char *address;
+ uint16 port;
+
+ /* Check and parse connection parameters */
+ if (!attr_container_contain_key(args, "address")
+ || !attr_container_contain_key(args, "port"))
+ goto fail;
+
+ address = attr_container_get_as_string(args, "address");
+ port = attr_container_get_as_uint16(args, "port");
+
+ /* Connect to TCP server */
+ if (!address || (fd = tcp_open(address, port)) == -1)
+ goto fail;
+ }
+ else if (conn->type == CONN_TYPE_UDP) {
+ uint16 port;
+
+ /* Check and parse connection parameters */
+ if (!attr_container_contain_key(args, "bind port"))
+ goto fail;
+ port = attr_container_get_as_uint16(args, "bind port");
+
+ /* Bind port */
+ if ((fd = udp_open(port)) == -1)
+ goto fail;
+ }
+ else if (conn->type == CONN_TYPE_UART) {
+ char *device;
+ int baud;
+
+ /* Check and parse connection parameters */
+ if (!attr_container_contain_key(args, "device")
+ || !attr_container_contain_key(args, "baudrate"))
+ goto fail;
+ device = attr_container_get_as_string(args, "device");
+ baud = attr_container_get_as_int(args, "baudrate");
+
+ /* Open device */
+ if (!device || (fd = uart_open(device, baud)) == -1)
+ goto fail;
+ }
+ else {
+ goto fail;
+ }
+
+ conn->fd = fd;
+
+ /* Set current connection as event data */
+ ev.events = EPOLLIN;
+ ev.data.ptr = conn;
+
+ /* Monitor incoming data */
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+ close(fd);
+ goto fail;
+ }
+
+ return conn->handle;
+
+fail:
+ find_connection(conn->handle, true);
+ wasm_runtime_free(conn);
+ return -1;
+}
+
+/* --- connection lib function --- */
+static void
+_conn_close(uint32 handle)
+{
+ sys_connection_t *conn = find_connection(handle, true);
+
+ if (conn != NULL) {
+ epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL);
+ close(conn->fd);
+ FREE_CONNECTION(conn);
+ }
+}
+
+/* --- connection lib function --- */
+static int
+_conn_send(uint32 handle, const char *data, int len)
+{
+ sys_connection_t *conn = find_connection(handle, false);
+
+ if (conn == NULL)
+ return -1;
+
+ if (conn->type == CONN_TYPE_TCP)
+ return tcp_send(conn->fd, data, len);
+
+ if (conn->type == CONN_TYPE_UDP) {
+ struct sockaddr *addr = (struct sockaddr *)conn->arg;
+ return udp_send(conn->fd, addr, data, len);
+ }
+
+ if (conn->type == CONN_TYPE_UART)
+ return uart_send(conn->fd, data, len);
+
+ return -1;
+}
+
+/* --- connection lib function --- */
+static bool
+_conn_config(uint32 handle, attr_container_t *cfg)
+{
+ sys_connection_t *conn = find_connection(handle, false);
+
+ if (conn == NULL)
+ return false;
+
+ if (conn->type == CONN_TYPE_UDP) {
+ char *address;
+ uint16_t port;
+ struct sockaddr_in *addr;
+
+ /* Parse remote address/port */
+ if (!attr_container_contain_key(cfg, "address")
+ || !attr_container_contain_key(cfg, "port"))
+ return false;
+ if (!(address = attr_container_get_as_string(cfg, "address")))
+ return false;
+ port = attr_container_get_as_uint16(cfg, "port");
+
+ if (conn->arg == NULL) {
+ addr = (struct sockaddr_in *)wasm_runtime_malloc(sizeof(*addr));
+ if (addr == NULL)
+ return false;
+
+ memset(addr, 0, sizeof(*addr));
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = inet_addr(address);
+ addr->sin_port = htons(port);
+
+ /* Set remote address as connection arg */
+ conn->arg = addr;
+ }
+ else {
+ addr = (struct sockaddr_in *)conn->arg;
+ addr->sin_addr.s_addr = inet_addr(address);
+ addr->sin_port = htons(port);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/* --- connection manager reference implementation ---*/
+
+typedef struct connection_event {
+ uint32 handle;
+ char *data;
+ uint32 len;
+} connection_event_t;
+
+static void
+connection_event_cleaner(connection_event_t *conn_event)
+{
+ if (conn_event->data != NULL)
+ wasm_runtime_free(conn_event->data);
+ wasm_runtime_free(conn_event);
+}
+
+static void
+post_msg_to_module(sys_connection_t *conn, char *data, uint32 len)
+{
+ module_data *module = module_data_list_lookup_id(conn->module_id);
+ char *data_copy = NULL;
+ connection_event_t *conn_data_event;
+ bh_message_t msg;
+
+ if (module == NULL)
+ return;
+
+ conn_data_event =
+ (connection_event_t *)wasm_runtime_malloc(sizeof(*conn_data_event));
+ if (conn_data_event == NULL)
+ return;
+
+ if (len > 0) {
+ data_copy = (char *)wasm_runtime_malloc(len);
+ if (data_copy == NULL) {
+ wasm_runtime_free(conn_data_event);
+ return;
+ }
+ bh_memcpy_s(data_copy, len, data, len);
+ }
+
+ memset(conn_data_event, 0, sizeof(*conn_data_event));
+ conn_data_event->handle = conn->handle;
+ conn_data_event->data = data_copy;
+ conn_data_event->len = len;
+
+ msg = bh_new_msg(CONNECTION_EVENT_WASM, conn_data_event,
+ sizeof(*conn_data_event), connection_event_cleaner);
+ if (!msg) {
+ connection_event_cleaner(conn_data_event);
+ return;
+ }
+
+ bh_post_msg2(module->queue, msg);
+}
+
+static void *
+polling_thread_routine(void *arg)
+{
+ while (polling_thread_run) {
+ int i, n;
+
+ n = epoll_wait(epollfd, epoll_events, MAX_EVENTS, -1);
+
+ if (n == -1 && errno != EINTR)
+ continue;
+
+ for (i = 0; i < n; i++) {
+ sys_connection_t *conn =
+ (sys_connection_t *)epoll_events[i].data.ptr;
+
+ if (conn->type == CONN_TYPE_TCP) {
+ int count = tcp_recv(conn->fd, io_buf, IO_BUF_SIZE);
+ if (count <= 0) {
+ /* Connection is closed by peer */
+ post_msg_to_module(conn, NULL, 0);
+ _conn_close(conn->handle);
+ }
+ else {
+ /* Data is received */
+ post_msg_to_module(conn, io_buf, count);
+ }
+ }
+ else if (conn->type == CONN_TYPE_UDP) {
+ int count = udp_recv(conn->fd, io_buf, IO_BUF_SIZE);
+ if (count > 0)
+ post_msg_to_module(conn, io_buf, count);
+ }
+ else if (conn->type == CONN_TYPE_UART) {
+ int count = uart_recv(conn->fd, io_buf, IO_BUF_SIZE);
+ if (count > 0)
+ post_msg_to_module(conn, io_buf, count);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+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_module_inst_t inst = wasm_app_data->wasm_module_inst;
+ connection_event_t *conn_event =
+ (connection_event_t *)bh_message_payload(msg);
+ int32 data_offset;
+
+ if (conn_event == NULL)
+ return;
+
+ func_on_conn_data = wasm_runtime_lookup_function(
+ inst, "_on_connection_data", "(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");
+ return;
+ }
+
+ /* 0 len means connection closed */
+ if (conn_event->len == 0) {
+ argv[0] = conn_event->handle;
+ argv[1] = 0;
+ argv[2] = 0;
+ 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", exception);
+ wasm_runtime_clear_exception(inst);
+ return;
+ }
+ }
+ else {
+ data_offset = wasm_runtime_module_dup_data(inst, conn_event->data,
+ conn_event->len);
+ if (data_offset == 0) {
+ const char *exception = wasm_runtime_get_exception(inst);
+ if (exception) {
+ printf("Got exception running wasm code: %s\n", exception);
+ wasm_runtime_clear_exception(inst);
+ }
+ return;
+ }
+
+ argv[0] = conn_event->handle;
+ argv[1] = (uint32)data_offset;
+ argv[2] = conn_event->len;
+ 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", exception);
+ wasm_runtime_clear_exception(inst);
+ wasm_runtime_module_free(inst, data_offset);
+ return;
+ }
+ wasm_runtime_module_free(inst, data_offset);
+ }
+}
+
+bool
+init_connection_framework()
+{
+ korp_tid tid;
+
+ epollfd = epoll_create(MAX_EVENTS);
+ if (epollfd == -1)
+ return false;
+
+ if (os_mutex_init(&g_lock) != 0) {
+ close(epollfd);
+ return false;
+ }
+
+ if (!wasm_register_cleanup_callback(cleanup_connections)) {
+ goto fail;
+ }
+
+ if (!wasm_register_msg_callback(CONNECTION_EVENT_WASM,
+ app_mgr_connection_event_callback)) {
+ goto fail;
+ }
+
+ if (os_thread_create(&tid, polling_thread_routine, NULL,
+ BH_APPLET_PRESERVED_STACK_SIZE)
+ != 0) {
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ os_mutex_destroy(&g_lock);
+ close(epollfd);
+ return false;
+}
+
+void
+exit_connection_framework()
+{
+ polling_thread_run = false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.cmake
new file mode 100644
index 000000000..c8f2b487e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/linux/connection_mgr.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (WASM_LIB_CONN_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${WASM_LIB_CONN_MGR_DIR})
+
+
+file (GLOB_RECURSE source_all ${WASM_LIB_CONN_MGR_DIR}/*.c)
+
+set (WASM_LIB_CONN_MGR_SOURCE ${source_all})
+
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/wasm_lib.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/wasm_lib.cmake
new file mode 100644
index 000000000..58db0c1d8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/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_CONN_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${WASM_LIB_CONN_DIR})
+
+add_definitions (-DAPP_FRAMEWORK_CONNECTION)
+
+
+include (${CMAKE_CURRENT_LIST_DIR}/${WAMR_BUILD_PLATFORM}/connection_mgr.cmake)
+
+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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_lib_impl.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_lib_impl.c
new file mode 100644
index 000000000..a812a71a2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_lib_impl.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/*
+ * Note:
+ * This file implements the linux version connection library which is
+ * defined in connection_lib.h.
+ * It also provides a reference impl of connections manager.
+ */
+
+#include "connection_lib.h"
+
+/* clang-format off */
+/*
+ * Platform implementation of connection library
+ */
+connection_interface_t connection_impl = {
+ ._open = NULL,
+ ._close = NULL,
+ ._send = NULL,
+ ._config = NULL
+};
+/* clang-format on */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_mgr.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_mgr.cmake
new file mode 100644
index 000000000..c8f2b487e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/connection/native/zephyr/connection_mgr.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (WASM_LIB_CONN_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${WASM_LIB_CONN_MGR_DIR})
+
+
+file (GLOB_RECURSE source_all ${WASM_LIB_CONN_MGR_DIR}/*.c)
+
+set (WASM_LIB_CONN_MGR_SOURCE ${source_all})
+
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor.c
new file mode 100644
index 000000000..d898a1d3a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wa-inc/sensor.h"
+
+#include "sensor_api.h"
+
+typedef struct _sensor {
+ struct _sensor *next;
+ char *name;
+ uint32 handle;
+ void (*sensor_callback)(sensor_t, attr_container_t *, void *);
+ void *user_data;
+} sensor;
+
+static sensor_t g_sensors = NULL;
+
+sensor_t
+sensor_open(const char *name, int index,
+ sensor_event_handler_f sensor_event_handler, void *user_data)
+{
+ uint32 id = wasm_sensor_open(name, index);
+ if (id == -1)
+ return NULL;
+
+ // create local node for holding the user callback
+ sensor_t sensor = (sensor_t)malloc(sizeof(struct _sensor));
+ if (sensor == NULL)
+ return NULL;
+
+ memset(sensor, 0, sizeof(struct _sensor));
+ sensor->handle = id;
+ sensor->name = strdup(name);
+ sensor->user_data = user_data;
+ sensor->sensor_callback = sensor_event_handler;
+
+ if (!sensor->name) {
+ free(sensor);
+ return NULL;
+ }
+
+ if (g_sensors == NULL) {
+ g_sensors = sensor;
+ }
+ else {
+ sensor->next = g_sensors;
+ g_sensors = sensor;
+ }
+
+ return sensor;
+}
+
+bool
+sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg)
+{
+ char *buffer = (char *)cfg;
+ int len = attr_container_get_serialize_length(cfg);
+
+ return wasm_sensor_config_with_attr_container(sensor->handle, buffer, len);
+}
+
+bool
+sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay)
+{
+ bool ret = wasm_sensor_config(sensor->handle, interval, bit_cfg, delay);
+ return ret;
+}
+
+bool
+sensor_close(sensor_t sensor)
+{
+ wasm_sensor_close(sensor->handle);
+
+ // remove local node
+ sensor_t s = g_sensors;
+ sensor_t prev = NULL;
+ while (s) {
+ if (s == sensor) {
+ if (prev == NULL) {
+ g_sensors = s->next;
+ }
+ else {
+ prev->next = s->next;
+ }
+ free(s->name);
+ free(s);
+ return true;
+ }
+ else {
+ prev = s;
+ s = s->next;
+ }
+ }
+
+ return false;
+}
+
+/*
+ *
+ * API for native layer to callback for sensor events
+ *
+ */
+
+void
+on_sensor_event(uint32 sensor_id, char *buffer, int len)
+{
+ attr_container_t *sensor_data = (attr_container_t *)buffer;
+
+ // lookup the sensor and call the handlers
+ sensor_t s = g_sensors;
+ sensor_t prev = NULL;
+ while (s) {
+ if (s->handle == sensor_id) {
+ s->sensor_callback(s, sensor_data, s->user_data);
+ break;
+ }
+
+ s = s->next;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor_api.h
new file mode 100644
index 000000000..ad6a7aa24
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/sensor_api.h
@@ -0,0 +1,31 @@
+/*
+ * 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(const char *name, int instance);
+
+bool
+wasm_sensor_config(uint32 sensor, uint32 interval, int bit_cfg, uint32 delay);
+
+bool
+wasm_sensor_config_with_attr_container(uint32 sensor, char *buffer, uint32 len);
+
+bool
+wasm_sensor_close(uint32 sensor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SENSOR_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wa-inc/sensor.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wa-inc/sensor.h
new file mode 100644
index 000000000..109f895d3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wa-inc/sensor.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AEE_SENSOR_H_
+#define _AEE_SENSOR_H_
+
+#include "bi-inc/attr_container.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* board producer define sensor */
+struct _sensor;
+typedef struct _sensor *sensor_t;
+
+/**
+ * @typedef sensor_event_handler_f
+ *
+ * @brief Define the signature of callback function for API
+ * sensor_open() to handle sensor event.
+ *
+ * @param sensor the sensor which the event belong to
+ * @param sensor_event the sensor event
+ * @param user_data user data associated with the sensor which is set when
+ * calling sensor_open().
+ *
+ * @see sensor_open
+ */
+typedef void (*sensor_event_handler_f)(sensor_t sensor,
+ attr_container_t *sensor_event,
+ void *user_data);
+
+/*
+ *****************
+ * Sensor APIs
+ *****************
+ */
+
+/**
+ * @brief Open sensor.
+ *
+ * @param name sensor name
+ * @param index sensor index
+ * @param handler callback function to handle the sensor event
+ * @param user_data user data
+ *
+ * @return the sensor opened if success, NULL otherwise
+ */
+sensor_t
+sensor_open(const char *name, int index, sensor_event_handler_f handler,
+ void *user_data);
+
+/**
+ * @brief Configure sensor with interval/bit_cfg/delay values.
+ *
+ * @param sensor the sensor to be configured
+ * @param interval sensor event interval
+ * @param bit_cfg sensor bit config
+ * @param delay sensor delay
+ *
+ * @return true if success, false otherwise
+ */
+bool
+sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay);
+
+/**
+ * @brief Configure sensor with attr_container_t object.
+ *
+ * @param sensor the sensor to be configured
+ * @param cfg the configuration
+ *
+ * @return true if success, false otherwise
+ */
+bool
+sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg);
+
+/**
+ * @brief Close sensor.
+ *
+ * @param sensor the sensor to be closed
+ *
+ * @return true if success, false otherwise
+ */
+bool
+sensor_close(sensor_t sensor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wasm_app.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/app/wasm_app.cmake
new file mode 100644
index 000000000..4b14a8bef
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.c
new file mode 100644
index 000000000..ad7a3fbf5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "runtime_sensor.h"
+#include "app_manager_export.h"
+#include "module_wasm_app.h"
+#include "bh_platform.h"
+
+static sys_sensor_t *g_sys_sensors = NULL;
+static uint32 g_sensor_id_max = 0;
+
+static sensor_client_t *
+find_sensor_client(sys_sensor_t *sensor, unsigned int client_id,
+ bool remove_if_found);
+
+void (*rechedule_sensor_callback)() = NULL;
+
+/*
+ * API for the applications to call - don't call it from the runtime
+ *
+ */
+
+static void
+sensor_event_cleaner(sensor_event_data_t *sensor_event)
+{
+ if (sensor_event->data != NULL) {
+ if (sensor_event->data_fmt == FMT_ATTR_CONTAINER)
+ attr_container_destroy(sensor_event->data);
+ else
+ wasm_runtime_free(sensor_event->data);
+ }
+
+ wasm_runtime_free(sensor_event);
+}
+
+static void
+wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data)
+{
+ attr_container_t *sensor_data = (attr_container_t *)user_data;
+ attr_container_t *sensor_data_clone;
+ int sensor_data_len;
+ sensor_event_data_t *sensor_event;
+ bh_message_t msg;
+ sensor_client_t *c = (sensor_client_t *)client;
+
+ module_data *module = module_data_list_lookup_id(c->client_id);
+ if (module == NULL)
+ return;
+
+ if (sensor_data == NULL)
+ return;
+
+ sensor_data_len = attr_container_get_serialize_length(sensor_data);
+ sensor_data_clone =
+ (attr_container_t *)wasm_runtime_malloc(sensor_data_len);
+ if (sensor_data_clone == NULL)
+ return;
+
+ /* multiple sensor clients may use/free the sensor data, so make a copy */
+ bh_memcpy_s(sensor_data_clone, sensor_data_len, sensor_data,
+ sensor_data_len);
+
+ sensor_event =
+ (sensor_event_data_t *)wasm_runtime_malloc(sizeof(*sensor_event));
+ if (sensor_event == NULL) {
+ wasm_runtime_free(sensor_data_clone);
+ return;
+ }
+
+ memset(sensor_event, 0, sizeof(*sensor_event));
+ sensor_event->sensor_id = sensor_id;
+ sensor_event->data = sensor_data_clone;
+ sensor_event->data_fmt = FMT_ATTR_CONTAINER;
+
+ msg = bh_new_msg(SENSOR_EVENT_WASM, sensor_event, sizeof(*sensor_event),
+ sensor_event_cleaner);
+ if (!msg) {
+ sensor_event_cleaner(sensor_event);
+ return;
+ }
+
+ bh_post_msg2(module->queue, msg);
+}
+
+bool
+wasm_sensor_config(wasm_exec_env_t exec_env, uint32 sensor, uint32 interval,
+ int bit_cfg, uint32 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);
+ if (s == NULL)
+ return false;
+
+ unsigned int mod_id =
+ app_manager_get_module_id(Module_WASM_App, module_inst);
+ bh_assert(mod_id != ID_NONE);
+
+ os_mutex_lock(&s->lock);
+
+ c = find_sensor_client(s, mod_id, false);
+ if (c == NULL) {
+ os_mutex_unlock(&s->lock);
+ return false;
+ }
+
+ c->interval = interval;
+ c->bit_cfg = bit_cfg;
+ c->delay = delay;
+
+ os_mutex_unlock(&s->lock);
+
+ if (s->config != NULL) {
+ attr_cont = attr_container_create("config sensor");
+ attr_container_set_int(&attr_cont, "interval", (int)interval);
+ attr_container_set_int(&attr_cont, "bit_cfg", bit_cfg);
+ attr_container_set_int(&attr_cont, "delay", (int)delay);
+ s->config(s, attr_cont);
+ attr_container_destroy(attr_cont);
+ }
+
+ refresh_read_interval(s);
+
+ reschedule_sensor_read();
+
+ return true;
+}
+
+uint32
+wasm_sensor_open(wasm_exec_env_t exec_env, char *name, int instance)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (name != NULL) {
+ sensor_client_t *c;
+ sys_sensor_t *s = find_sys_sensor(name, instance);
+ if (s == NULL)
+ return (uint32)-1;
+
+ unsigned int mod_id =
+ app_manager_get_module_id(Module_WASM_App, module_inst);
+ bh_assert(mod_id != ID_NONE);
+
+ os_mutex_lock(&s->lock);
+
+ c = find_sensor_client(s, mod_id, false);
+ if (c) {
+ // the app already opened this sensor
+ os_mutex_unlock(&s->lock);
+ return (uint32)-1;
+ }
+
+ sensor_client_t *client =
+ (sensor_client_t *)wasm_runtime_malloc(sizeof(sensor_client_t));
+ if (client == NULL) {
+ os_mutex_unlock(&s->lock);
+ return (uint32)-1;
+ }
+
+ memset(client, 0, sizeof(sensor_client_t));
+ client->client_id = mod_id;
+ client->client_callback = (void *)wasm_sensor_callback;
+ client->interval = s->default_interval;
+ client->next = s->clients;
+ s->clients = client;
+
+ os_mutex_unlock(&s->lock);
+
+ refresh_read_interval(s);
+
+ reschedule_sensor_read();
+
+ return s->sensor_id;
+ }
+
+ return (uint32)-1;
+}
+
+bool
+wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, uint32 sensor,
+ char *buffer, int len)
+{
+ if (buffer != NULL) {
+ attr_container_t *cfg = (attr_container_t *)buffer;
+ sensor_obj_t s = find_sys_sensor_id(sensor);
+ if (s == NULL)
+ return false;
+
+ if (s->config == NULL)
+ return false;
+
+ return s->config(s, cfg);
+ }
+
+ return false;
+}
+
+bool
+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;
+ sensor_obj_t s = find_sys_sensor_id(sensor);
+ sensor_client_t *c;
+
+ bh_assert(mod_id != ID_NONE);
+
+ if (s == NULL)
+ return false;
+
+ os_mutex_lock(&s->lock);
+ if ((c = find_sensor_client(s, client_id, true)) != NULL)
+ wasm_runtime_free(c);
+ os_mutex_unlock(&s->lock);
+
+ refresh_read_interval(s);
+
+ reschedule_sensor_read();
+
+ return true;
+}
+
+/*
+ *
+ * sensor framework API - don't expose to the applications
+ *
+ */
+void
+set_sensor_reshceduler(void (*callback)())
+{
+ rechedule_sensor_callback = callback;
+}
+
+// used for other threads to wakeup the sensor read thread
+void
+reschedule_sensor_read()
+{
+ if (rechedule_sensor_callback)
+ rechedule_sensor_callback();
+}
+
+void
+refresh_read_interval(sensor_obj_t sensor)
+{
+ sensor_client_t *c;
+ uint32 interval = sensor->default_interval;
+ os_mutex_lock(&sensor->lock);
+
+ c = sensor->clients;
+ if (c)
+ interval = c->interval;
+
+ while (c) {
+ if (c->interval < interval)
+ interval = c->interval;
+ c = c->next;
+ }
+
+ os_mutex_unlock(&sensor->lock);
+
+ sensor->read_interval = interval;
+}
+
+sensor_obj_t
+add_sys_sensor(char *name, char *description, int instance,
+ uint32 default_interval, void *read_func, void *config_func)
+{
+ sys_sensor_t *s = (sys_sensor_t *)wasm_runtime_malloc(sizeof(sys_sensor_t));
+ if (s == NULL)
+ return NULL;
+
+ memset(s, 0, sizeof(*s));
+ s->name = bh_strdup(name);
+ s->sensor_instance = instance;
+ s->default_interval = default_interval;
+
+ if (!s->name) {
+ wasm_runtime_free(s);
+ return NULL;
+ }
+
+ if (description) {
+ s->description = bh_strdup(description);
+ if (!s->description) {
+ wasm_runtime_free(s->name);
+ wasm_runtime_free(s);
+ return NULL;
+ }
+ }
+
+ g_sensor_id_max++;
+ if (g_sensor_id_max == UINT32_MAX)
+ g_sensor_id_max++;
+ s->sensor_id = g_sensor_id_max;
+
+ s->read = read_func;
+ s->config = config_func;
+
+ if (g_sys_sensors == NULL) {
+ g_sys_sensors = s;
+ }
+ else {
+ s->next = g_sys_sensors;
+ g_sys_sensors = s;
+ }
+
+ if (os_mutex_init(&s->lock) != 0) {
+ if (s->description) {
+ wasm_runtime_free(s->description);
+ }
+ wasm_runtime_free(s->name);
+ wasm_runtime_free(s);
+ }
+
+ return s;
+}
+
+sensor_obj_t
+find_sys_sensor(const char *name, int instance)
+{
+ sys_sensor_t *s = g_sys_sensors;
+ while (s) {
+ if (strcmp(s->name, name) == 0 && s->sensor_instance == instance)
+ return s;
+
+ s = s->next;
+ }
+ return NULL;
+}
+
+sensor_obj_t
+find_sys_sensor_id(uint32 sensor_id)
+{
+ sys_sensor_t *s = g_sys_sensors;
+ while (s) {
+ if (s->sensor_id == sensor_id)
+ return s;
+
+ s = s->next;
+ }
+ return NULL;
+}
+
+sensor_client_t *
+find_sensor_client(sys_sensor_t *sensor, unsigned int client_id,
+ bool remove_if_found)
+{
+ sensor_client_t *prev = NULL, *c = sensor->clients;
+
+ while (c) {
+ sensor_client_t *next = c->next;
+ if (c->client_id == client_id) {
+ if (remove_if_found) {
+ if (prev)
+ prev->next = next;
+ else
+ sensor->clients = next;
+ }
+ return c;
+ }
+ else {
+ prev = c;
+ c = c->next;
+ }
+ }
+
+ return NULL;
+}
+
+// return the milliseconds to next check
+uint32
+check_sensor_timers()
+{
+ uint32 ms_to_next_check = UINT32_MAX;
+ uint32 now = (uint32)bh_get_tick_ms();
+
+ sys_sensor_t *s = g_sys_sensors;
+ while (s) {
+ uint32 last_read = s->last_read;
+ uint32 elpased_ms = bh_get_elpased_ms(&last_read);
+
+ if (s->read_interval <= 0 || s->clients == NULL) {
+ s = s->next;
+ continue;
+ }
+
+ if (elpased_ms >= s->read_interval) {
+ attr_container_t *data = s->read(s);
+ if (data) {
+ sensor_client_t *client = s->clients;
+ while (client) {
+ client->client_callback(client, s->sensor_id, data);
+ client = client->next;
+ }
+ attr_container_destroy(data);
+ }
+
+ s->last_read = now;
+
+ if (s->read_interval < ms_to_next_check)
+ ms_to_next_check = s->read_interval;
+ }
+ else {
+ uint32 remaining = s->read_interval - elpased_ms;
+ if (remaining < ms_to_next_check)
+ ms_to_next_check = remaining;
+ }
+
+ s = s->next;
+ }
+
+ return ms_to_next_check;
+}
+
+void
+sensor_cleanup_callback(uint32 module_id)
+{
+ sys_sensor_t *s = g_sys_sensors;
+
+ while (s) {
+ sensor_client_t *c;
+ os_mutex_lock(&s->lock);
+ if ((c = find_sensor_client(s, module_id, true)) != NULL) {
+ wasm_runtime_free(c);
+ }
+ os_mutex_unlock(&s->lock);
+ s = s->next;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.h
new file mode 100644
index 000000000..d7c893111
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef LIB_EXTENSION_RUNTIME_SENSOR_H_
+#define LIB_EXTENSION_RUNTIME_SENSOR_H_
+
+#include "bh_platform.h"
+#include "bi-inc/attr_container.h"
+#include "wasm_export.h"
+#include "sensor_native_api.h"
+
+struct _sys_sensor;
+typedef struct _sys_sensor *sensor_obj_t;
+
+typedef struct _sensor_client {
+ struct _sensor_client *next;
+ unsigned int client_id; // the app id
+ uint32 interval;
+ int bit_cfg;
+ uint32 delay;
+ void (*client_callback)(void *client, uint32, attr_container_t *);
+} sensor_client_t;
+
+typedef struct _sys_sensor {
+ struct _sys_sensor *next;
+ char *name;
+ int sensor_instance;
+ char *description;
+ uint32 sensor_id;
+ sensor_client_t *clients;
+ /* app, sensor mgr and app mgr may access the clients at the same time,
+ so need a lock to protect the clients */
+ korp_mutex lock;
+ uint32 last_read;
+ uint32 read_interval;
+ uint32 default_interval;
+
+ /* TODO: may support other type return value, such as 'cbor' */
+ attr_container_t *(*read)(void *);
+ bool (*config)(void *, void *);
+
+} sys_sensor_t;
+
+sensor_obj_t
+add_sys_sensor(char *name, char *description, int instance,
+ uint32 default_interval, void *read_func, void *config_func);
+sensor_obj_t
+find_sys_sensor(const char *name, int instance);
+sensor_obj_t
+find_sys_sensor_id(uint32 sensor_id);
+void
+refresh_read_interval(sensor_obj_t sensor);
+void
+sensor_cleanup_callback(uint32 module_id);
+uint32
+check_sensor_timers();
+void
+reschedule_sensor_read();
+
+bool
+init_sensor_framework();
+void
+start_sensor_framework();
+void
+exit_sensor_framework();
+
+#endif /* LIB_EXTENSION_RUNTIME_SENSOR_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.inl b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.inl
new file mode 100644
index 000000000..a7b9f4778
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/runtime_sensor.inl
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+EXPORT_WASM_API_WITH_SIG(wasm_sensor_open, "($i)i"),
+EXPORT_WASM_API_WITH_SIG(wasm_sensor_config, "(iiii)i"),
+EXPORT_WASM_API_WITH_SIG(wasm_sensor_config_with_attr_container, "(i*~)i"),
+EXPORT_WASM_API_WITH_SIG(wasm_sensor_close, "(i)i"),
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_mgr_ref.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_mgr_ref.c
new file mode 100644
index 000000000..474ec738d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_mgr_ref.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "runtime_sensor.h"
+#include "bi-inc/attr_container.h"
+#include "module_wasm_app.h"
+#include "wasm_export.h"
+
+/*
+ *
+ * One reference implementation for sensor manager
+ *
+ *
+ */
+static korp_cond cond;
+static korp_mutex mutex;
+static bool sensor_check_thread_run = true;
+
+void
+app_mgr_sensor_event_callback(module_data *m_data, bh_message_t msg)
+{
+ uint32 argv[3];
+ 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_module_inst_t inst = wasm_app_data->wasm_module_inst;
+
+ sensor_event_data_t *payload =
+ (sensor_event_data_t *)bh_message_payload(msg);
+ if (payload == NULL)
+ return;
+
+ 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 on_sensor_event\n");
+ }
+ else {
+ int32 sensor_data_offset;
+ uint32 sensor_data_len;
+
+ if (payload->data_fmt == FMT_ATTR_CONTAINER) {
+ sensor_data_len =
+ attr_container_get_serialize_length(payload->data);
+ }
+ else {
+ printf("Unsupported sensor data format: %d\n", payload->data_fmt);
+ return;
+ }
+
+ sensor_data_offset =
+ wasm_runtime_module_dup_data(inst, payload->data, sensor_data_len);
+ if (sensor_data_offset == 0) {
+ const char *exception = wasm_runtime_get_exception(inst);
+ if (exception) {
+ printf("Got exception running wasm code: %s\n", exception);
+ wasm_runtime_clear_exception(inst);
+ }
+ return;
+ }
+
+ argv[0] = payload->sensor_id;
+ argv[1] = (uint32)sensor_data_offset;
+ argv[2] = sensor_data_len;
+
+ 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", exception);
+ wasm_runtime_clear_exception(inst);
+ wasm_runtime_module_free(inst, sensor_data_offset);
+ return;
+ }
+
+ wasm_runtime_module_free(inst, sensor_data_offset);
+ }
+}
+
+static void
+thread_sensor_check(void *arg)
+{
+ while (sensor_check_thread_run) {
+ uint32 ms_to_expiry = check_sensor_timers();
+ if (ms_to_expiry == UINT32_MAX)
+ ms_to_expiry = 5000;
+ os_mutex_lock(&mutex);
+ os_cond_reltimedwait(&cond, &mutex, ms_to_expiry * 1000);
+ os_mutex_unlock(&mutex);
+ }
+}
+
+static void
+cb_wakeup_thread()
+{
+ os_cond_signal(&cond);
+}
+
+void
+set_sensor_reshceduler(void (*callback)());
+
+bool
+init_sensor_framework()
+{
+ /* init the mutext and conditions */
+ if (os_cond_init(&cond) != 0) {
+ return false;
+ }
+
+ if (os_mutex_init(&mutex) != 0) {
+ os_cond_destroy(&cond);
+ return false;
+ }
+
+ set_sensor_reshceduler(cb_wakeup_thread);
+
+ wasm_register_msg_callback(SENSOR_EVENT_WASM,
+ app_mgr_sensor_event_callback);
+
+ wasm_register_cleanup_callback(sensor_cleanup_callback);
+
+ return true;
+}
+
+void
+start_sensor_framework()
+{
+ korp_tid tid;
+
+ os_thread_create(&tid, (void *)thread_sensor_check, NULL,
+ BH_APPLET_PRESERVED_STACK_SIZE);
+}
+
+void
+exit_sensor_framework()
+{
+ sensor_check_thread_run = false;
+ reschedule_sensor_read();
+
+ // todo: wait the sensor thread termination
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_native_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_native_api.h
new file mode 100644
index 000000000..0bbb315ca
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/sensor_native_api.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SENSOR_NATIVE_API_H_
+#define _SENSOR_NATIVE_API_H_
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+wasm_sensor_config(wasm_exec_env_t exec_env, uint32 sensor, uint32 interval,
+ int bit_cfg, uint32 delay);
+uint32
+wasm_sensor_open(wasm_exec_env_t exec_env, char *name, int instance);
+
+bool
+wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, uint32 sensor,
+ char *buffer, int len);
+
+bool
+wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SENSOR_NATIVE_API_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/wasm_lib.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/wasm_lib.cmake
new file mode 100644
index 000000000..65a83ba59
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/sensor/native/wasm_lib.cmake
@@ -0,0 +1,14 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (WASM_LIB_SENSOR_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DAPP_FRAMEWORK_SENSOR)
+
+include_directories(${WASM_LIB_SENSOR_DIR})
+
+
+file (GLOB_RECURSE source_all ${WASM_LIB_SENSOR_DIR}/*.c)
+
+set (WASM_APP_LIB_CURRENT_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wa-inc/app_xxx.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wa-inc/app_xxx.h
new file mode 100644
index 000000000..ac30842f0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wa-inc/app_xxx.h
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/*
+ header file for wasm application
+*/ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wasm_app.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/app/wasm_app.cmake
new file mode 100644
index 000000000..16ca237ae
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/native/app_xxx.inl b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/native/app_xxx.inl
new file mode 100644
index 000000000..2503fe454
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/native/wasm_lib.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/template/native/wasm_lib.cmake
new file mode 100644
index 000000000..2601c1d27
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/README.md
new file mode 100644
index 000000000..31c705e1f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/README.md
@@ -0,0 +1,8 @@
+# Remote application management
+
+The WAMR application manager supports [remote application management](../core/app-mgr) from the 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.
+
+The tool [host_tool](../test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from the host system. And the [IoT App Store Demo](../test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from the cloud.
+
+
+<img src="../../doc/pics/wamr-arch.JPG" width="80%">
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.c
new file mode 100644
index 000000000..b27ee96eb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "app_manager.h"
+#include "app_manager_host.h"
+#include "bh_platform.h"
+#include "bi-inc/attr_container.h"
+#include "event.h"
+#include "watchdog.h"
+#include "coap_ext.h"
+
+/* Queue of app manager */
+static bh_queue *g_app_mgr_queue;
+static bool g_app_mgr_started;
+
+void *
+get_app_manager_queue()
+{
+ return g_app_mgr_queue;
+}
+
+void
+app_manager_post_applets_update_event()
+{
+ module_data *m_data;
+ attr_container_t *attr_cont;
+ request_t msg;
+ int num = 0, i = 0;
+ char *url = "/applets";
+
+ if (!event_is_registered(url))
+ return;
+
+ if (!(attr_cont = attr_container_create("All Applets"))) {
+ app_manager_printf("Post applets update event failed: "
+ "allocate memory failed.");
+ return;
+ }
+
+ os_mutex_lock(&module_data_list_lock);
+
+ m_data = module_data_list;
+ while (m_data) {
+ num++;
+ m_data = m_data->next;
+ }
+
+ if (!(attr_container_set_int(&attr_cont, "num", num))) {
+ app_manager_printf("Post applets update event failed: "
+ "set attr container key failed.");
+ goto fail;
+ }
+
+ m_data = module_data_list;
+ while (m_data) {
+ char buf[32];
+ i++;
+ snprintf(buf, sizeof(buf), "%s%d", "applet", i);
+ if (!(attr_container_set_string(&attr_cont, buf,
+ m_data->module_name))) {
+ app_manager_printf("Post applets update event failed: "
+ "set attr applet name key failed.");
+ goto fail;
+ }
+ snprintf(buf, sizeof(buf), "%s%d", "heap", i);
+ if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
+ app_manager_printf("Post applets update event failed: "
+ "set attr heap key failed.");
+ goto fail;
+ }
+ m_data = m_data->next;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.url = url;
+ msg.action = COAP_EVENT;
+ msg.payload = (char *)attr_cont;
+ send_request_to_host(&msg);
+
+ app_manager_printf("Post applets update event success!\n");
+ attr_container_dump(attr_cont);
+
+fail:
+ os_mutex_unlock(&module_data_list_lock);
+ attr_container_destroy(attr_cont);
+}
+
+static int
+get_applets_count()
+{
+ module_data *m_data;
+ int num = 0;
+
+ os_mutex_lock(&module_data_list_lock);
+
+ m_data = module_data_list;
+ while (m_data) {
+ num++;
+ m_data = m_data->next;
+ }
+
+ os_mutex_unlock(&module_data_list_lock);
+
+ return num;
+}
+
+/* Query fw apps info if name = NULL, otherwise query specify app */
+static bool
+app_manager_query_applets(request_t *msg, const char *name)
+{
+ module_data *m_data;
+ attr_container_t *attr_cont;
+ int num = 0, i = 0, len;
+ bool ret = false, found = false;
+ response_t response[1] = { 0 };
+
+ attr_cont = attr_container_create("Applets Info");
+ if (!attr_cont) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Query Applets failed: allocate memory failed.");
+ return false;
+ }
+
+ os_mutex_lock(&module_data_list_lock);
+
+ m_data = module_data_list;
+ while (m_data) {
+ num++;
+ m_data = m_data->next;
+ }
+
+ if (name == NULL && !(attr_container_set_int(&attr_cont, "num", num))) {
+ SEND_ERR_RESPONSE(
+ msg->mid, "Query Applets failed: set attr container key failed.");
+ goto fail;
+ }
+
+ m_data = module_data_list;
+ while (m_data) {
+ char buf[32];
+
+ if (name == NULL) {
+ i++;
+ snprintf(buf, sizeof(buf), "%s%d", "applet", i);
+ if (!(attr_container_set_string(&attr_cont, buf,
+ m_data->module_name))) {
+ SEND_ERR_RESPONSE(msg->mid, "Query Applets failed: "
+ "set attr container key failed.");
+ goto fail;
+ }
+ snprintf(buf, sizeof(buf), "%s%d", "heap", i);
+ if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Query Applets failed: "
+ "set attr container heap key failed.");
+ goto fail;
+ }
+ }
+ else if (!strcmp(name, m_data->module_name)) {
+ found = true;
+ if (!(attr_container_set_string(&attr_cont, "name",
+ m_data->module_name))) {
+ SEND_ERR_RESPONSE(msg->mid, "Query Applet failed: "
+ "set attr container key failed.");
+ goto fail;
+ }
+ if (!(attr_container_set_int(&attr_cont, "heap",
+ m_data->heap_size))) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Query Applet failed: "
+ "set attr container heap key failed.");
+ goto fail;
+ }
+ }
+
+ m_data = m_data->next;
+ }
+
+ if (name != NULL && !found) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Query Applet failed: the app is not found.");
+ goto fail;
+ }
+
+ len = attr_container_get_serialize_length(attr_cont);
+
+ make_response_for_request(msg, response);
+ set_response(response, CONTENT_2_05, FMT_ATTR_CONTAINER, (char *)attr_cont,
+ len);
+ send_response_to_host(response);
+
+ ret = true;
+ app_manager_printf("Query Applets success!\n");
+ attr_container_dump(attr_cont);
+
+fail:
+ os_mutex_unlock(&module_data_list_lock);
+ attr_container_destroy(attr_cont);
+ return ret;
+}
+
+void
+applet_mgt_reqeust_handler(request_t *request, void *unused)
+{
+ bh_message_t msg;
+ /* deep copy, but not use app self heap, but use global heap */
+ request_t *req = clone_request(request);
+
+ if (!req)
+ return;
+
+ msg = bh_new_msg(RESTFUL_REQUEST, req, sizeof(*req), request_cleaner);
+ if (!msg) {
+ request_cleaner(req);
+ return;
+ }
+
+ bh_post_msg2(get_app_manager_queue(), msg);
+}
+
+/* return -1 for error */
+static int
+get_module_type(char *kv_str)
+{
+ int module_type = -1;
+ char type_str[16] = { 0 };
+
+ find_key_value(kv_str, strlen(kv_str), "type", type_str,
+ sizeof(type_str) - 1, '&');
+
+ if (strlen(type_str) == 0)
+ module_type = Module_WASM_App;
+ else if (strcmp(type_str, "jeff") == 0)
+ module_type = Module_Jeff;
+ else if (strcmp(type_str, "wasm") == 0)
+ module_type = Module_WASM_App;
+ else if (strcmp(type_str, "wasmlib") == 0)
+ module_type = Module_WASM_Lib;
+
+ return module_type;
+}
+
+#define APP_NAME_MAX_LEN 128
+
+/* Queue callback of App Manager */
+
+static void
+app_manager_queue_callback(void *message, void *arg)
+{
+ request_t *request = (request_t *)bh_message_payload((bh_message_t)message);
+ int mid = request->mid, module_type, offset;
+
+ (void)arg;
+
+ if ((offset =
+ check_url_start(request->url, strlen(request->url), "/applet"))
+ > 0) {
+ module_type = get_module_type(request->url + offset);
+
+ if (module_type == -1) {
+ SEND_ERR_RESPONSE(mid,
+ "Applet Management failed: invalid module type.");
+ goto fail;
+ }
+
+ /* Install Applet */
+ if (request->action == COAP_PUT) {
+ if (get_applets_count() >= MAX_APP_INSTALLATIONS) {
+ SEND_ERR_RESPONSE(
+ mid,
+ "Install Applet failed: exceed max app installations.");
+ goto fail;
+ }
+
+ if (!request->payload) {
+ SEND_ERR_RESPONSE(mid,
+ "Install Applet failed: invalid payload.");
+ goto fail;
+ }
+ if (g_module_interfaces[module_type]
+ && g_module_interfaces[module_type]->module_install) {
+ if (!g_module_interfaces[module_type]->module_install(request))
+ goto fail;
+ }
+ }
+ /* Uninstall Applet */
+ else if (request->action == COAP_DELETE) {
+ module_type = get_module_type(request->url + offset);
+ if (module_type == -1) {
+ SEND_ERR_RESPONSE(
+ mid, "Uninstall Applet failed: invalid module type.");
+ goto fail;
+ }
+
+ if (g_module_interfaces[module_type]
+ && g_module_interfaces[module_type]->module_uninstall) {
+ if (!g_module_interfaces[module_type]->module_uninstall(
+ request))
+ goto fail;
+ }
+ }
+ /* Query Applets installed */
+ else if (request->action == COAP_GET) {
+ char name[APP_NAME_MAX_LEN] = { 0 };
+ char *properties = request->url + offset;
+ find_key_value(properties, strlen(properties), "name", name,
+ sizeof(name) - 1, '&');
+ if (strlen(name) > 0)
+ app_manager_query_applets(request, name);
+ else
+ app_manager_query_applets(request, NULL);
+ }
+ else {
+ SEND_ERR_RESPONSE(mid, "Invalid request of applet: invalid action");
+ }
+ }
+ /* Event Register/Unregister */
+ else if ((offset = check_url_start(request->url, strlen(request->url),
+ "/event/"))
+ > 0) {
+ char url_buf[256] = { 0 };
+
+ strncpy(url_buf, request->url + offset, sizeof(url_buf) - 1);
+
+ if (!event_handle_event_request(request->action, url_buf, ID_HOST)) {
+ SEND_ERR_RESPONSE(mid, "Handle event request failed.");
+ goto fail;
+ }
+ send_error_response_to_host(mid, CONTENT_2_05, NULL); /* OK */
+ }
+ else {
+ int i;
+ for (i = 0; i < Module_Max; i++) {
+ if (g_module_interfaces[i]
+ && g_module_interfaces[i]->module_handle_host_url) {
+ if (g_module_interfaces[i]->module_handle_host_url(request))
+ break;
+ }
+ }
+ }
+
+fail:
+ return;
+}
+
+static void
+module_interfaces_init()
+{
+ int i;
+ for (i = 0; i < Module_Max; i++) {
+ if (g_module_interfaces[i] && g_module_interfaces[i]->module_init)
+ g_module_interfaces[i]->module_init();
+ }
+}
+
+void
+app_manager_startup(host_interface *interface)
+{
+ module_interfaces_init();
+
+ /* Create queue of App Manager */
+ g_app_mgr_queue = bh_queue_create();
+ if (!g_app_mgr_queue)
+ return;
+
+ if (!module_data_list_init())
+ goto fail1;
+
+ if (!watchdog_startup())
+ goto fail2;
+
+ /* Initialize Host */
+ app_manager_host_init(interface);
+
+ am_register_resource("/app/", targeted_app_request_handler, ID_APP_MGR);
+
+ /* /app/ and /event/ are both processed by applet_mgt_reqeust_handler */
+ am_register_resource("/applet", applet_mgt_reqeust_handler, ID_APP_MGR);
+ am_register_resource("/event/", applet_mgt_reqeust_handler, ID_APP_MGR);
+
+ app_manager_printf("App Manager started.\n");
+
+ g_app_mgr_started = true;
+
+ /* Enter loop run */
+ bh_queue_enter_loop_run(g_app_mgr_queue, app_manager_queue_callback, NULL);
+
+ g_app_mgr_started = false;
+
+ /* Destroy registered resources */
+ am_cleanup_registeration(ID_APP_MGR);
+
+ /* Destroy watchdog */
+ watchdog_destroy();
+
+fail2:
+ module_data_list_destroy();
+
+fail1:
+ bh_queue_destroy(g_app_mgr_queue);
+}
+
+bool
+app_manager_is_started(void)
+{
+ return g_app_mgr_started;
+}
+
+#include "module_config.h"
+
+module_interface *g_module_interfaces[Module_Max] = {
+#if ENABLE_MODULE_JEFF != 0
+ &jeff_module_interface,
+#else
+ NULL,
+#endif
+
+#if ENABLE_MODULE_WASM_APP != 0
+ &wasm_app_module_interface,
+#else
+ NULL,
+#endif
+
+#if ENABLE_MODULE_WASM_LIB != 0
+ &wasm_lib_module_interface
+#else
+ NULL
+#endif
+};
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.h
new file mode 100644
index 000000000..ce83bd170
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef APP_MANAGER_H
+#define APP_MANAGER_H
+
+#include "bh_platform.h"
+#include "app_manager_export.h"
+#include "native_interface.h"
+#include "bi-inc/shared_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define APP_MGR_MALLOC wasm_runtime_malloc
+#define APP_MGR_FREE wasm_runtime_free
+
+/* os_printf is defined in each platform */
+#define app_manager_printf os_printf
+
+#define SEND_ERR_RESPONSE(mid, err_msg) \
+ do { \
+ app_manager_printf("%s\n", err_msg); \
+ send_error_response_to_host(mid, INTERNAL_SERVER_ERROR_5_00, err_msg); \
+ } while (0)
+
+extern module_interface *g_module_interfaces[Module_Max];
+
+/* Lock of the module data list */
+extern korp_mutex module_data_list_lock;
+
+/* Module data list */
+extern module_data *module_data_list;
+
+void
+app_manager_add_module_data(module_data *m_data);
+
+void
+app_manager_del_module_data(module_data *m_data);
+
+bool
+module_data_list_init();
+
+void
+module_data_list_destroy();
+
+bool
+app_manager_is_interrupting_module(uint32 module_type, void *module_inst);
+
+void
+release_module(module_data *m_data);
+
+void
+module_data_list_remove(module_data *m_data);
+
+void *
+app_manager_timer_create(void (*timer_callback)(void *),
+ watchdog_timer *wd_timer);
+
+void
+app_manager_timer_destroy(void *timer);
+
+void
+app_manager_timer_start(void *timer, int timeout);
+
+void
+app_manager_timer_stop(void *timer);
+
+watchdog_timer *
+app_manager_get_wd_timer_from_timer_handle(void *timer);
+
+int
+app_manager_signature_verify(const uint8_t *file, unsigned int file_len,
+ const uint8_t *signature, unsigned int sig_size);
+
+void
+targeted_app_request_handler(request_t *request, void *unused);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.c
new file mode 100644
index 000000000..08b5df309
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "app_manager_host.h"
+#include "app_manager.h"
+#include "app_manager_export.h"
+#include "coap_ext.h"
+
+/* host communication interface */
+static host_interface host_commu;
+
+/* IMRTLink Two leading bytes */
+static unsigned char leadings[] = { (unsigned char)0x12, (unsigned char)0x34 };
+
+/* IMRTLink Receiving Phase */
+typedef enum recv_phase_t {
+ Phase_Non_Start,
+ Phase_Leading,
+ Phase_Type,
+ Phase_Size,
+ Phase_Payload,
+ Phase_Ignoring
+} recv_phase_t;
+
+/* IMRTLink Receive Context */
+typedef struct recv_context_t {
+ recv_phase_t phase;
+ bh_link_msg_t message;
+ int size_in_phase;
+} recv_context_t;
+
+/* Current IMRTLink receive context */
+static recv_context_t recv_ctx;
+
+/* Lock for device write */
+static korp_mutex host_lock;
+
+static bool enable_log = false;
+
+static bool
+is_little_endian()
+{
+ long i = 0x01020304;
+ unsigned char *c = (unsigned char *)&i;
+ return (*c == 0x04) ? true : false;
+}
+
+static void
+exchange32(uint8 *pData)
+{
+ uint8 value = *pData;
+ *pData = *(pData + 3);
+ *(pData + 3) = value;
+
+ value = *(pData + 1);
+ *(pData + 1) = *(pData + 2);
+ *(pData + 2) = value;
+}
+
+/* return:
+ * 1: complete message received
+ * 0: incomplete message received
+ */
+static int
+on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
+{
+ if (ctx->phase == Phase_Non_Start) {
+ ctx->message.payload_size = 0;
+
+ if (ctx->message.payload) {
+ APP_MGR_FREE(ctx->message.payload);
+ ctx->message.payload = NULL;
+ }
+
+ if (ch == leadings[0]) {
+ if (enable_log)
+ app_manager_printf("##On byte arrive: got leading 0\n");
+ ctx->phase = Phase_Leading;
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Leading) {
+ if (ch == leadings[1]) {
+ if (enable_log)
+ app_manager_printf("##On byte arrive: got leading 1\n");
+ ctx->phase = Phase_Type;
+ }
+ else
+ ctx->phase = Phase_Non_Start;
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Type) {
+ if (ctx->size_in_phase++ == 0) {
+ if (enable_log)
+ app_manager_printf("##On byte arrive: got type 0\n");
+ ctx->message.message_type = ch;
+ }
+ else {
+ if (enable_log)
+ app_manager_printf("##On byte arrive: got type 1\n");
+ ctx->message.message_type |= (ch << 8);
+ ctx->message.message_type = ntohs(ctx->message.message_type);
+ ctx->phase = Phase_Size;
+ ctx->size_in_phase = 0;
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Size) {
+ unsigned char *p = (unsigned char *)&ctx->message.payload_size;
+
+ if (enable_log)
+ app_manager_printf("##On byte arrive: got payload_size, byte %d\n",
+ ctx->size_in_phase);
+ p[ctx->size_in_phase++] = ch;
+
+ if (ctx->size_in_phase == sizeof(ctx->message.payload_size)) {
+ ctx->message.payload_size = ntohl(ctx->message.payload_size);
+ ctx->phase = Phase_Payload;
+
+ if (enable_log)
+ app_manager_printf("##On byte arrive: payload_size: %d\n",
+ ctx->message.payload_size);
+ if (ctx->message.payload) {
+ APP_MGR_FREE(ctx->message.payload);
+ ctx->message.payload = NULL;
+ }
+
+ /* message completion */
+ if (ctx->message.payload_size == 0) {
+ ctx->phase = Phase_Non_Start;
+ if (enable_log)
+ app_manager_printf("##On byte arrive: receive end, "
+ "payload_size is 0.\n");
+ return 1;
+ }
+
+ if (ctx->message.message_type != INSTALL_WASM_APP) {
+ ctx->message.payload =
+ (char *)APP_MGR_MALLOC(ctx->message.payload_size);
+ if (!ctx->message.payload) {
+ ctx->phase = Phase_Non_Start;
+ return 0;
+ }
+ }
+
+ ctx->phase = Phase_Payload;
+ ctx->size_in_phase = 0;
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Payload) {
+ 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;
+
+ ctx->size_in_phase++;
+
+ if (module_on_install != NULL) {
+ if (module_on_install(ch, ctx->message.payload_size,
+ &received_size)) {
+ if (received_size == ctx->message.payload_size) {
+ /* whole wasm app received */
+ ctx->phase = Phase_Non_Start;
+ return 1;
+ }
+ }
+ else {
+ /* receive or handle fail */
+ if (ctx->size_in_phase < ctx->message.payload_size) {
+ ctx->phase = Phase_Ignoring;
+ }
+ else {
+ ctx->phase = Phase_Non_Start;
+ ctx->size_in_phase = 0;
+ }
+ return 0;
+ }
+ }
+ else {
+ ctx->phase = Phase_Non_Start;
+ ctx->size_in_phase = 0;
+ return 0;
+ }
+ }
+ else {
+ ctx->message.payload[ctx->size_in_phase++] = ch;
+
+ 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);
+ return 1;
+ }
+ return 0;
+ }
+ }
+ else if (ctx->phase == Phase_Ignoring) {
+ ctx->size_in_phase++;
+ if (ctx->size_in_phase == ctx->message.payload_size) {
+ if (ctx->message.payload)
+ APP_MGR_FREE(ctx->message.payload);
+ memset(ctx, 0, sizeof(*ctx));
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+int
+aee_host_msg_callback(void *msg, uint32_t msg_len)
+{
+ unsigned char *p = msg, *p_end = p + msg_len;
+
+ /*app_manager_printf("App Manager receive %d bytes from Host\n", msg_len);*/
+
+ for (; p < p_end; p++) {
+ int ret = on_imrt_link_byte_arrive(*p, &recv_ctx);
+
+ if (ret == 1) {
+ if (recv_ctx.message.payload) {
+ int msg_type = recv_ctx.message.message_type;
+
+ if (msg_type == REQUEST_PACKET) {
+ request_t request;
+ memset(&request, 0, sizeof(request));
+
+ if (!unpack_request(recv_ctx.message.payload,
+ recv_ctx.message.payload_size,
+ &request))
+ continue;
+
+ request.sender = ID_HOST;
+
+ am_dispatch_request(&request);
+ }
+ else {
+ app_manager_printf("unexpected host msg type: %d\n",
+ msg_type);
+ }
+
+ APP_MGR_FREE(recv_ctx.message.payload);
+ recv_ctx.message.payload = NULL;
+ recv_ctx.message.payload_size = 0;
+ }
+
+ memset(&recv_ctx, 0, sizeof(recv_ctx));
+ }
+ }
+
+ return 0;
+}
+
+bool
+app_manager_host_init(host_interface *interface)
+{
+ if (os_mutex_init(&host_lock) != 0) {
+ return false;
+ }
+ memset(&recv_ctx, 0, sizeof(recv_ctx));
+
+ host_commu.init = interface->init;
+ host_commu.send = interface->send;
+ host_commu.destroy = interface->destroy;
+
+ if (host_commu.init != NULL) {
+ if (!host_commu.init()) {
+ os_mutex_destroy(&host_lock);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int
+app_manager_host_send_msg(int msg_type, const char *buf, int size)
+{
+ /* send an IMRT LINK message contains the buf as payload */
+ if (host_commu.send != NULL) {
+ int size_s = size, n;
+ char header[16];
+
+ os_mutex_lock(&host_lock);
+ /* leading bytes */
+ bh_memcpy_s(header, 2, leadings, 2);
+
+ /* message type */
+ /* TODO: check if use network byte order!!! */
+ *((uint16 *)(header + 2)) = htons(msg_type);
+
+ /* payload length */
+ if (is_little_endian())
+ exchange32((uint8 *)&size_s);
+
+ bh_memcpy_s(header + 4, 4, &size_s, 4);
+ n = host_commu.send(NULL, header, 8);
+ if (n != 8) {
+ os_mutex_unlock(&host_lock);
+ return 0;
+ }
+
+ /* payload */
+ n = host_commu.send(NULL, buf, size);
+ os_mutex_unlock(&host_lock);
+
+ app_manager_printf("sent %d bytes to host\n", n);
+ return n;
+ }
+ else {
+ app_manager_printf("no send api provided\n");
+ }
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.h
new file mode 100644
index 000000000..b19404f91
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_manager_host.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _APP_MANAGER_HOST_H_
+#define _APP_MANAGER_HOST_H_
+
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HOST_MODE_AON 1
+#define HOST_MODE_UART 2
+#define HOST_MODE_TEST 3
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_mgr.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_mgr.cmake
new file mode 100644
index 000000000..fd6e69098
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/app_mgr.cmake
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+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/${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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/ble_msg.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/ble_msg.c
new file mode 100644
index 000000000..1d19dddaf
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/ble_msg.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if 0
+
+#define BLUETOOTH_INTERFACE_ADVERTISMENT_DATA_LENGTH 31
+/* ble_device_info */
+typedef struct ble_device_info {
+
+ /* address type */
+ uint8_t address_type;
+ /* MAC of Device */
+ uint8_t mac[6];
+ /* security level */
+ uint8_t security_level;
+ /* signal strength */
+ int8_t rssi;
+ /* uuid_16_type */
+ int8_t uuid_16_type;
+ /* uuid_32_type */
+ int8_t uuid_32_type;
+ /* uuid_128_type */
+ int8_t uuid_128_type;
+ /* error code */
+ uint8_t error_code;
+ /* scan response length*/
+ uint16_t adv_data_len;
+ /* advertisement data */
+ uint8_t *adv_data;
+ /* scan response length*/
+ uint16_t scan_response_len;
+ /* scan response */
+ uint8_t *scan_response;
+ /* next device */
+ struct ble_device_info *next;
+ /* private data length */
+ int private_data_length;
+ /* private data */
+ uint8_t *private_data;
+ /* value handle*/
+ uint16_t value_handle;
+ /* ccc handle*/
+ uint16_t ccc_handle;
+
+}ble_device_info;
+
+/* BLE message sub type */
+typedef enum BLE_SUB_EVENT_TYPE {
+ BLE_SUB_EVENT_DISCOVERY,
+ BLE_SUB_EVENT_CONNECTED,
+ BLE_SUB_EVENT_DISCONNECTED,
+ BLE_SUB_EVENT_NOTIFICATION,
+ BLE_SUB_EVENT_INDICATION,
+ BLE_SUB_EVENT_PASSKEYENTRY,
+ BLE_SUB_EVENT_SECURITY_LEVEL_CHANGE
+}BLE_SUB_EVENT_TYPE;
+
+/* Queue message, for BLE Event */
+typedef struct bh_queue_ble_sub_msg_t {
+ /* message type, should be one of QUEUE_MSG_TYPE */
+ BLE_SUB_EVENT_TYPE type;
+ /* payload size */
+ /*uint32_t payload_size;*/
+ char payload[1];
+}bh_queue_ble_sub_msg_t;
+
+static void
+app_instance_free_ble_msg(char *msg)
+{
+ bh_queue_ble_sub_msg_t *ble_msg = (bh_queue_ble_sub_msg_t *)msg;
+ ble_device_info *dev_info;
+
+ dev_info = (ble_device_info *) ble_msg->payload;
+
+ if (dev_info->scan_response != NULL)
+ APP_MGR_FREE(dev_info->scan_response);
+
+ if (dev_info->private_data != NULL)
+ APP_MGR_FREE(dev_info->private_data);
+
+ if (dev_info->adv_data != NULL)
+ APP_MGR_FREE(dev_info->adv_data);
+
+ if (dev_info != NULL)
+ APP_MGR_FREE(dev_info);
+}
+
+static void
+app_instance_queue_free_callback(bh_message_t queue_msg)
+{
+
+ char * payload = (char *)bh_message_payload(queue_msg);
+ if(payload == NULL)
+ return;
+
+ switch (bh_message_type(queue_msg))
+ {
+ /*
+ case SENSOR_EVENT: {
+ bh_sensor_event_t *sensor_event = (bh_sensor_event_t *) payload;
+ attr_container_t *event = sensor_event->event;
+ attr_container_destroy(event);
+ }
+ break;
+ */
+ case BLE_EVENT: {
+ app_instance_free_ble_msg(payload);
+ break;
+ }
+ }
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/coding_rule.txt b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/coding_rule.txt
new file mode 100644
index 000000000..4598872a3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/coding_rule.txt
@@ -0,0 +1,15 @@
+Coding rules:
+
+1. module implementation can include the export head files of associated runtime
+
+2. app manager only call access the module implementation through the interface API
+
+3. module implementation can call the app manager API from following files:
+ - util.c
+ - message.c
+
+4. platform API: To define it
+
+5. Any platform dependent implementation of app manager should be implemented in the
+ platform specific source file, such as app_mgr_zephyr.c
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.c
new file mode 100644
index 000000000..a21065fab
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <string.h>
+
+#include "event.h"
+
+#include "app_manager.h"
+#include "coap_ext.h"
+
+typedef struct _subscribe {
+ struct _subscribe *next;
+ uint32 subscriber_id;
+} subscribe_t;
+
+typedef struct _event {
+ struct _event *next;
+ int subscriber_size;
+ subscribe_t *subscribers;
+ char url[1]; /* event url */
+} event_reg_t;
+
+event_reg_t *g_events = NULL;
+
+static bool
+find_subscriber(event_reg_t *reg, uint32 id, bool remove_found)
+{
+ subscribe_t *c = reg->subscribers;
+ subscribe_t *prev = NULL;
+ while (c) {
+ subscribe_t *next = c->next;
+ if (c->subscriber_id == id) {
+ if (remove_found) {
+ if (prev)
+ prev->next = next;
+ else
+ reg->subscribers = next;
+
+ APP_MGR_FREE(c);
+ }
+
+ return true;
+ }
+ else {
+ prev = c;
+ c = next;
+ }
+ }
+
+ return false;
+}
+
+static bool
+check_url(const char *url)
+{
+ if (*url == 0)
+ return false;
+
+ return true;
+}
+
+bool
+am_register_event(const char *url, uint32_t reg_client)
+{
+ event_reg_t *current = g_events;
+
+ app_manager_printf("am_register_event adding url:(%s)\n", url);
+
+ if (!check_url(url)) {
+ app_manager_printf("am_register_event: invaild url:(%s)\n", url);
+ return false;
+ }
+ while (current) {
+ if (strcmp(url, current->url) == 0)
+ break;
+ current = current->next;
+ }
+
+ if (current == NULL) {
+ if (NULL
+ == (current = (event_reg_t *)APP_MGR_MALLOC(
+ offsetof(event_reg_t, url) + strlen(url) + 1))) {
+ app_manager_printf("am_register_event: malloc fail\n");
+ return false;
+ }
+
+ memset(current, 0, sizeof(event_reg_t));
+ bh_strcpy_s(current->url, strlen(url) + 1, url);
+ current->next = g_events;
+ g_events = current;
+ }
+
+ if (find_subscriber(current, reg_client, false)) {
+ return true;
+ }
+ else {
+ subscribe_t *s = (subscribe_t *)APP_MGR_MALLOC(sizeof(subscribe_t));
+ if (s == NULL)
+ return false;
+
+ memset(s, 0, sizeof(subscribe_t));
+ s->subscriber_id = reg_client;
+ s->next = current->subscribers;
+ current->subscribers = s;
+ app_manager_printf("client: %d registered event (%s)\n", reg_client,
+ url);
+ }
+
+ return true;
+}
+
+// @url: NULL means the client wants to unregister all its subscribed items
+bool
+am_unregister_event(const char *url, uint32_t reg_client)
+{
+ event_reg_t *current = g_events, *pre = NULL;
+
+ while (current != NULL) {
+ if (url == NULL || strcmp(current->url, url) == 0) {
+ event_reg_t *next = current->next;
+ if (find_subscriber(current, reg_client, true)) {
+ app_manager_printf("client: %d deregistered event (%s)\n",
+ reg_client, current->url);
+ }
+
+ // remove the registration if no client subscribe it
+ if (current->subscribers == NULL) {
+ app_manager_printf("unregister for event deleted url:(%s)\n",
+ current->url);
+ if (pre)
+ pre->next = next;
+ else
+ g_events = next;
+ APP_MGR_FREE(current);
+ current = next;
+ continue;
+ }
+ }
+ pre = current;
+ current = current->next;
+ }
+
+ return true;
+}
+
+bool
+event_handle_event_request(uint8_t code, const char *event_url,
+ uint32_t reg_client)
+{
+ if (code == COAP_PUT) { /* register */
+ return am_register_event(event_url, reg_client);
+ }
+ else if (code == COAP_DELETE) { /* unregister */
+ return am_unregister_event(event_url, reg_client);
+ }
+ else {
+ /* invalid request */
+ return false;
+ }
+}
+
+void
+am_publish_event(request_t *event)
+{
+ bh_assert(event->action == COAP_EVENT);
+
+ event_reg_t *current = g_events;
+ while (current) {
+ if (0 == strcmp(event->url, current->url)) {
+ subscribe_t *c = current->subscribers;
+ while (c) {
+ if (c->subscriber_id == ID_HOST) {
+ send_request_to_host(event);
+ }
+ else {
+ module_request_handler(event,
+ (void *)(uintptr_t)c->subscriber_id);
+ }
+ c = c->next;
+ }
+
+ return;
+ }
+
+ current = current->next;
+ }
+}
+
+bool
+event_is_registered(const char *event_url)
+{
+ event_reg_t *current = g_events;
+
+ while (current != NULL) {
+ if (strcmp(current->url, event_url) == 0) {
+ return true;
+ }
+ current = current->next;
+ }
+
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.h
new file mode 100644
index 000000000..36ced521d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/event.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _EVENT_H_
+#define _EVENT_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Handle event request from host agent
+ *
+ * @param code the coap packet code
+ * @param event_url the event url
+ *
+ * @return true if success, false otherwise
+ */
+bool
+event_handle_event_request(uint8_t code, const char *event_url,
+ uint32_t register);
+
+/**
+ * Test whether the event is registered
+ *
+ * @param event_url the event url
+ *
+ * @return true for registered, false for not registered
+ */
+bool
+event_is_registered(const char *event_url);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _EVENT_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/message.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/message.c
new file mode 100644
index 000000000..aac7a2364
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/message.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "app_manager.h"
+#include "app_manager_host.h"
+#include "event.h"
+#include "bi-inc/attr_container.h"
+#include "coap_ext.h"
+
+#if 0
+bool send_coap_packet_to_host(coap_packet_t * packet)
+{
+ int size;
+ uint8_t *buf;
+
+ size = coap_serialize_message_tcp(&packet, &buf);
+ if (!buf || size == 0)
+ return false;
+
+ app_manager_host_send_msg(buf, size);
+ APP_MGR_FREE(buf);
+
+ return true;
+}
+#endif
+
+bool
+send_request_to_host(request_t *msg)
+{
+ if (COAP_EVENT == msg->action && !event_is_registered(msg->url)) {
+ app_manager_printf("Event is not registered\n");
+ return false;
+ }
+
+ int size;
+ char *packet = pack_request(msg, &size);
+ if (packet == NULL)
+ return false;
+
+ app_manager_host_send_msg(REQUEST_PACKET, packet, size);
+
+ free_req_resp_packet(packet);
+
+ return true;
+}
+
+bool
+send_response_to_host(response_t *response)
+{
+ int size;
+ char *packet = pack_response(response, &size);
+ if (packet == NULL)
+ return false;
+
+ app_manager_host_send_msg(RESPONSE_PACKET, packet, size);
+
+ free_req_resp_packet(packet);
+
+ return true;
+}
+
+bool
+send_error_response_to_host(int mid, int status, const char *msg)
+{
+ int payload_len = 0;
+ attr_container_t *payload = NULL;
+ response_t response[1] = { 0 };
+
+ if (msg) {
+ payload = attr_container_create("");
+ if (payload) {
+ attr_container_set_string(&payload, "error message", msg);
+ payload_len = attr_container_get_serialize_length(payload);
+ }
+ }
+
+ set_response(response, status, FMT_ATTR_CONTAINER, (const char *)payload,
+ payload_len);
+ response->mid = mid;
+
+ send_response_to_host(response);
+
+ if (payload)
+ attr_container_destroy(payload);
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_config.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_config.h
new file mode 100644
index 000000000..b742fed3a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_config.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _MODULE_CONFIG_H_
+#define _MODULE_CONFIG_H_
+
+#define ENABLE_MODULE_JEFF 0
+#define ENABLE_MODULE_WASM_APP 1
+#define ENABLE_MODULE_WASM_LIB 1
+
+#ifdef ENABLE_MODULE_JEFF
+#include "module_jeff.h"
+#endif
+#ifdef ENABLE_MODULE_WASM_APP
+#include "module_wasm_app.h"
+#endif
+#ifdef ENABLE_MODULE_WASM_LIB
+#include "module_wasm_lib.h"
+#endif
+
+#endif /* _MODULE_CONFIG_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.c
new file mode 100644
index 000000000..7c7f9510d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.c
@@ -0,0 +1,1883 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifdef ENABLE_JEFF
+
+#include "module_jeff.h"
+#include "jeff_export.h"
+#include "../vmcore_jeff/jeff-runtime.h"
+#include "../vmcore_jeff/jeff-thread.h"
+#include "../vmcore_jeff/jeff-buffer.h"
+#include "../vmcore_jeff/jeff-tool.h"
+#include "../vmcore_jeff/jeff-tool-priv.h"
+#include "app_manager-host.h"
+#include "bh_queue.h"
+#include "attr-container.h"
+#include "attr-container-util.h"
+#include "bh_thread.h"
+#include "ems_gc.h"
+#include "coap_ext.h"
+#include "libcore.h"
+#include "event.h"
+#include "watchdog.h"
+
+#define DEFAULT_APPLET_TIMEOUT (3 * 60 * 1000)
+#define DEFAULT_APPLET_HEAP_SIZE (48 * 1024)
+#define MIN_APPLET_HEAP_SIZE (2 * 1024)
+#define MAX_APPLET_HEAP_SIZE (1024 * 1024)
+
+typedef struct jeff_applet_data {
+ /* Java Applet Object */
+ JeffObjectRef applet_obj;
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ /* Whether the applet is in debug mode */
+ bool debug_mode;
+ /* Queue of the tool agent */
+ bh_queue *tool_agent_queue;
+#endif
+
+ /* VM instance */
+ JeffInstanceLocalRoot *vm_instance;
+ /* Applet Main file */
+ JeffFileHeaderLinked *main_file;
+ /* Permissions of the Java Applet */
+ char *perms;
+} jeff_applet_data;
+
+/* Jeff class com.intel.aee.AEEApplet */
+static JeffClassHeaderLinked *class_AEEApplet;
+/* Jeff class com.intel.aee.Request */
+static JeffClassHeaderLinked *class_AEERequest;
+/* Jeff class com.intel.aee.Timer */
+static JeffClassHeaderLinked *class_Timer;
+/* Jeff class com.intel.aee.Sensor */
+static JeffClassHeaderLinked *class_Sensor;
+/* Jeff class com.intel.aee.ble.BLEManager */
+static JeffClassHeaderLinked *class_BLEManager;
+/* Jeff class com.intel.aee.ble.BLEDevice */
+static JeffClassHeaderLinked *class_BLEDevice;
+/* Jeff class com.intel.aee.ble.BLEGattService */
+JeffClassHeaderLinked *class_BLEGattService;
+/* Jeff class com.intel.aee.ble.BLEGattCharacteristic */
+JeffClassHeaderLinked *class_BLEGattCharacteristic;
+/* Jeff class com.intel.aee.ble.BLEGattDescriptor */
+JeffClassHeaderLinked *class_BLEGattDescriptor;
+/* Jeff class com.intel.aee.gpio.GPIOChannel */
+static JeffClassHeaderLinked *class_GPIOChannel;
+/* Jeff method void com.intel.aee.AEEApplet.onInit() */
+static JeffMethodLinked *method_AEEApplet_onInit;
+/* Jeff method void com.intel.aee.AEEApplet.onDestroy() */
+static JeffMethodLinked *method_AEEApplet_onDestroy;
+/* Jeff method void com.intel.aee.AEEApplet.callOnRequest(Request request) */
+static JeffMethodLinked *method_AEEApplet_callOnRequest;
+/* Jeff method void com.intel.aee.Timer.callOnTimer() */
+static JeffMethodLinked *method_callOnTimer;
+/* Jeff method void com.intel.aee.Sensor.callOnSensorEvent() */
+static JeffMethodLinked *method_callOnSensorEvent;
+/* Jeff method void com.intel.aee.ble.BLEManager.callOnBLEStartDiscovery() */
+static JeffMethodLinked *method_callOnBLEStartDiscovery;
+/* Jeff method void com.intel.aee.ble.BLEManager.callOnBLEConnected() */
+static JeffMethodLinked *method_callOnBLEConnected;
+/* Jeff method void com.intel.aee.ble.BLEManager.callOnBLEDisonnected() */
+static JeffMethodLinked *method_callOnBLEDisconnected;
+/* Jeff method void com.intel.aee.ble.BLEManager.callOnBLENotification() */
+static JeffMethodLinked *method_callOnBLENotification;
+/* Jeff method void com.intel.aee.ble.BLEManager.callOnBLEIndication() */
+static JeffMethodLinked *method_callOnBLEIndication;
+/* Jeff method void com.intel.aee.ble.BLEManager.callOnBLEPasskeyEntry() */
+static JeffMethodLinked *method_callOnBLEPasskeyEntry;
+/* Jeff method void com.intel.aee.gpio.GPIOChannel.callOnGPIOInterrupt() */
+static JeffMethodLinked *method_callOnGPIOInterrupt;
+/* Jeff method void com.intel.aee.ble.BLEManager.getBLEDevice() */
+static JeffMethodLinked *method_callOnBLEManagerGetBLEDevice;
+
+static jeff_applet_data *
+app_manager_get_jeff_applet_data()
+{
+ module_data *m_data = app_manager_get_module_data(Module_Jeff);
+ return (jeff_applet_data *)m_data->internal_data;
+}
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+void *
+app_manager_get_tool_agent_queue()
+{
+ return app_manager_get_jeff_applet_data()->tool_agent_queue;
+}
+#endif
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+static bool
+is_tool_agent_running(module_data *m_data)
+{
+ jeff_applet_data *applet_data = (jeff_applet_data *)m_data->internal_data;
+ return (applet_data->debug_mode && applet_data->tool_agent_queue
+ && applet_data->vm_instance->tool_agent);
+}
+#endif
+
+static char *
+get_class_qname(const JeffString *pname, const JeffString *cname)
+{
+ unsigned int length =
+ pname->length ? pname->length + 2 + cname->length : cname->length + 1;
+ char *buf = APP_MGR_MALLOC(length), *p;
+
+ if (!buf)
+ return NULL;
+
+ p = buf;
+ if (pname->length) {
+ bh_memcpy_s(p, pname->length, pname->value, pname->length);
+ p += pname->length;
+ *p++ = '.';
+ }
+
+ bh_memcpy_s(p, cname->length, cname->value, cname->length);
+ p += cname->length;
+ *p = '\0';
+
+ return buf;
+}
+
+static void
+send_exception_event_to_host(const char *applet_name, const char *exc_name)
+{
+ attr_container_t *payload;
+ bh_request_msg_t msg;
+ char *url;
+ int url_len;
+
+ payload = attr_container_create("exception detail");
+ if (!payload) {
+ app_manager_printf("Send exception to host fail: allocate memory");
+ return;
+ }
+
+ if (!attr_container_set_string(&payload, "exception name", exc_name)
+ || !attr_container_set_string(&payload, "stack trace", "TODO")
+ || !attr_container_set_string(&payload, "applet name", applet_name)) {
+ app_manager_printf("Send exception to host fail: set attr");
+ goto fail;
+ }
+
+ url_len = strlen("/exception/") + strlen(applet_name);
+ url = APP_MGR_MALLOC(url_len + 1);
+ if (!url) {
+ app_manager_printf("Send exception to host fail: allocate memory");
+ goto fail;
+ }
+ memset(url, 0, url_len + 1);
+ bh_strcpy_s(url, url_len + 1, "/exception/");
+ bh_strcat_s(url, url_len + 1, applet_name);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.url = url;
+ msg.action = COAP_PUT;
+ msg.payload = (char *)payload;
+
+ app_send_request_msg_to_host(&msg);
+
+ APP_MGR_FREE(url);
+
+fail:
+ attr_container_destroy(payload);
+}
+
+static bool
+check_exception()
+{
+ if (jeff_runtime_get_exception()) {
+ jeff_printf("V1.Exception thrown when running applet '%s':\n",
+ app_manager_get_module_name(Module_Jeff));
+ jeff_runtime_print_exception();
+ jeff_printf("\n");
+ jeff_printf(NULL);
+ }
+
+ if (!app_manager_is_interrupting_module(Module_Jeff)) {
+ attr_container_t *payload;
+ int payload_len;
+ JeffClassHeaderLinked *exc_class =
+ jeff_object_class_pointer(jeff_runtime_get_exception());
+ char *qname_buf = get_class_qname(jeff_get_class_pname(exc_class),
+ jeff_get_class_cname(exc_class));
+
+ /* Send exception event to host */
+ if (qname_buf) {
+ send_exception_event_to_host(
+ app_manager_get_module_name(Module_Jeff), qname_buf);
+ APP_MGR_FREE(qname_buf);
+ }
+
+ /* Uninstall the applet */
+ if ((payload = attr_container_create("uninstall myself"))) {
+ if (attr_container_set_string(
+ &payload, "name", app_manager_get_module_name(Module_Jeff))
+ /* Set special flag to prevent app manager making response
+ since this is an internal message */
+ && attr_container_set_bool(&payload, "do not reply me", true)) {
+ request_t request = { 0 };
+ payload_len = attr_container_get_serialize_length(payload);
+
+ init_request(request, "/applet", COAP_DELETE, (char *)payload, payload_len));
+ app_mgr_lookup_resource(&request);
+
+ // TODO: confirm this is right
+ attr_container_destroy(payload);
+ }
+ }
+
+ jeff_runtime_set_exception(NULL);
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+app_manager_initialize_class(JeffClassHeaderLinked *c)
+{
+ jeff_runtime_initialize_class(c);
+ return !check_exception();
+}
+
+static bool
+app_manager_initialize_object(JeffObjectRef obj)
+{
+ jeff_runtime_initialize_object(obj);
+ return !check_exception();
+}
+
+static bool
+app_manager_call_java(JeffMethodLinked *method, unsigned int argc,
+ uint32 argv[], uint8 argt[])
+{
+ module_data *m_data = app_manager_get_module_data(Module_Jeff);
+ watchdog_timer *wd_timer = &m_data->wd_timer;
+ bool is_wd_started = false;
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ /* Only start watchdog when debugger is not running */
+ if (!is_tool_agent_running(m_data)) {
+#endif
+ watchdog_timer_start(wd_timer);
+ is_wd_started = true;
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ }
+#endif
+
+ jeff_runtime_call_java(method, argc, argv, argt);
+
+ if (is_wd_started) {
+ os_mutex_lock(&wd_timer->lock);
+ if (!wd_timer->is_interrupting) {
+ wd_timer->is_stopped = true;
+ watchdog_timer_stop(wd_timer);
+ }
+ os_mutex_unlock(&wd_timer->lock);
+ }
+
+ return !check_exception();
+}
+
+static AEEBLEDevice
+create_object_BLEDevice(ble_device_info *dev_info)
+{
+ JeffLocalObjectRef ref;
+ AEEBLEDevice dev_struct;
+
+ jeff_runtime_push_local_object_ref(&ref);
+
+ ref.val = jeff_runtime_new_object(class_BLEDevice);
+
+ if (!ref.val) {
+ jeff_runtime_pop_local_object_ref(1);
+ return NULL;
+ }
+
+ dev_struct = (AEEBLEDevice)(ref.val);
+ dev_struct->rssi = dev_info->rssi;
+ dev_struct->mac =
+ (jbyteArray)jeff_runtime_create_byte_array((int8 *)dev_info->mac, 6);
+
+ app_manager_printf("adv_data_len:%d,scan_response_len:%d\n",
+ dev_info->adv_data_len, dev_info->scan_response_len);
+
+ dev_struct->advData = (jbyteArray)jeff_runtime_create_byte_array(
+ (int8 *)dev_info->adv_data, dev_info->adv_data_len);
+ dev_struct->scanResponse = (jbyteArray)jeff_runtime_create_byte_array(
+ (int8 *)dev_info->scan_response, dev_info->scan_response_len);
+ dev_struct->addressType = dev_info->address_type;
+ jeff_runtime_initialize_object(ref.val);
+ jeff_runtime_pop_local_object_ref(1);
+ if ((dev_struct->mac == NULL) || (dev_struct->advData == NULL)
+ || (dev_struct->scanResponse == NULL)) {
+ return NULL;
+ }
+ return (AEEBLEDevice)ref.val;
+}
+
+static void
+app_instance_process_ble_msg(char *msg)
+{
+ bh_queue_ble_sub_msg_t *ble_msg = (bh_queue_ble_sub_msg_t *)msg;
+ unsigned int argv[5];
+ uint8 argt[5];
+
+ ble_device_info *dev_info;
+
+ dev_info = (ble_device_info *)ble_msg->payload;
+ AEEBLEDevice ble_dev;
+
+ argv[0] = (unsigned int)(jbyteArray)jeff_runtime_create_byte_array(
+ (int8 *)dev_info->mac, 6);
+ argt[0] = 1;
+ if (!app_manager_call_java(method_callOnBLEManagerGetBLEDevice, 1, argv,
+ argt)) {
+ app_manager_printf(
+ "app_manager_call_java BLEManagerGetBLEDevice fail error\n");
+ goto fail;
+ }
+ ble_dev = (AEEBLEDevice)argv[0];
+ if (ble_dev == NULL) {
+ ble_dev = create_object_BLEDevice(dev_info);
+ if (ble_dev == NULL) {
+ goto fail;
+ }
+ }
+
+ switch (ble_msg->type) {
+ case BLE_SUB_EVENT_DISCOVERY:
+ {
+ argv[0] = (unsigned int)ble_dev;
+ argt[0] = 1;
+ ble_dev->rssi = dev_info->rssi;
+ if (!app_manager_call_java(method_callOnBLEStartDiscovery, 1, argv,
+ argt)) {
+ app_manager_printf(
+ "app_manager_call_java method_callOnBLEStartDiscovery "
+ "fail error\n");
+ goto fail;
+ }
+ break;
+ }
+
+ case BLE_SUB_EVENT_CONNECTED:
+ {
+ if (ble_dev) {
+ argv[0] = (unsigned int)ble_dev;
+ argv[1] = 0;
+ argt[0] = 1;
+ argt[1] = 1;
+ if (!app_manager_call_java(method_callOnBLEConnected, 2, argv,
+ argt)) {
+ app_manager_printf(
+ "app_manager_call_java method_callOnBLEConnected "
+ "fail error\n");
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case BLE_SUB_EVENT_DISCONNECTED:
+ {
+ app_manager_printf("app instance received disconnected\n");
+
+ if (ble_dev) {
+ argv[0] = (unsigned int)ble_dev;
+ argv[1] = 0;
+ argt[0] = 1;
+ argt[1] = 1;
+ ble_dev->rssi = dev_info->rssi;
+ if (!app_manager_call_java(method_callOnBLEDisconnected, 2,
+ argv, argt)) {
+ app_manager_printf(
+ "app_manager_call_java "
+ "method_callOnBLEDisconnected fail error\n");
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case BLE_SUB_EVENT_NOTIFICATION:
+ {
+ if (ble_dev) {
+ argv[0] = (unsigned int)ble_dev;
+ argv[1] =
+ (unsigned int)(jbyteArray)jeff_runtime_create_byte_array(
+ (int8 *)dev_info->private_data,
+ dev_info->private_data_length);
+ argv[2] = dev_info->value_handle;
+ argv[3] = dev_info->ccc_handle;
+ argt[1] = 1;
+ argt[2] = 0;
+ argt[3] = 0;
+ ble_dev->rssi = dev_info->rssi;
+ if (!app_manager_call_java(method_callOnBLENotification, 4,
+ argv, argt)) {
+ app_manager_printf(
+ "app_manager_call_java "
+ "method_callOnBLENotification fail error\n");
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case BLE_SUB_EVENT_INDICATION:
+ {
+ if (ble_dev) {
+ argv[0] = (unsigned int)ble_dev;
+ argv[1] =
+ (unsigned int)(jbyteArray)jeff_runtime_create_byte_array(
+ (int8 *)dev_info->private_data,
+ dev_info->private_data_length);
+ argv[2] = dev_info->value_handle;
+ argv[3] = dev_info->ccc_handle;
+ argt[0] = 1;
+ argt[1] = 1;
+ argt[2] = 0;
+ argt[3] = 0;
+ ble_dev->rssi = dev_info->rssi;
+ if (!app_manager_call_java(method_callOnBLEIndication, 4, argv,
+ argt)) {
+ app_manager_printf(
+ "app_manager_call_java method_callOnBLEIndication "
+ "fail error\n");
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case BLE_SUB_EVENT_PASSKEYENTRY:
+ {
+
+ if (ble_dev) {
+ argv[0] = (unsigned int)ble_dev;
+ argt[0] = 1;
+ argt[1] = 1;
+ ble_dev->rssi = dev_info->rssi;
+ if (!app_manager_call_java(method_callOnBLEPasskeyEntry, 1,
+ argv, argt)) {
+ app_manager_printf(
+ "app_manager_call_java "
+ "method_callOnBLEPasskeyEntry fail error\n");
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case BLE_SUB_EVENT_SECURITY_LEVEL_CHANGE:
+ {
+ if (ble_dev) {
+ ble_dev->securityLevel = dev_info->security_level;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+fail:
+ if (dev_info->scan_response != NULL) {
+ APP_MGR_FREE(dev_info->scan_response);
+ }
+ if (dev_info->private_data != NULL) {
+ APP_MGR_FREE(dev_info->private_data);
+ }
+
+ if (dev_info->adv_data != NULL) {
+ APP_MGR_FREE(dev_info->adv_data);
+ }
+ if (dev_info != NULL) {
+ APP_MGR_FREE(dev_info);
+ }
+}
+
+static void
+app_instance_free_ble_msg(char *msg)
+{
+ bh_queue_ble_sub_msg_t *ble_msg = (bh_queue_ble_sub_msg_t *)msg;
+ ble_device_info *dev_info;
+
+ dev_info = (ble_device_info *)ble_msg->payload;
+
+ if (dev_info->scan_response != NULL)
+ APP_MGR_FREE(dev_info->scan_response);
+
+ if (dev_info->private_data != NULL)
+ APP_MGR_FREE(dev_info->private_data);
+
+ if (dev_info->adv_data != NULL)
+ APP_MGR_FREE(dev_info->adv_data);
+
+ if (dev_info != NULL)
+ APP_MGR_FREE(dev_info);
+}
+
+static void
+app_instance_queue_free_callback(void *queue_msg)
+{
+ bh_queue_msg_t *msg = (bh_queue_msg_t *)queue_msg;
+
+ switch (msg->message_type) {
+ case APPLET_REQUEST:
+ {
+ bh_request_msg_t *req_msg = (bh_request_msg_t *)msg->payload;
+ APP_MGR_FREE(req_msg);
+ break;
+ }
+
+ case TIMER_EVENT:
+ {
+ break;
+ }
+
+ case SENSOR_EVENT:
+ {
+ if (msg->payload) {
+ bh_sensor_event_t *sensor_event =
+ (bh_sensor_event_t *)msg->payload;
+ attr_container_t *event = sensor_event->event;
+
+ attr_container_destroy(event);
+ APP_MGR_FREE(sensor_event);
+ }
+ break;
+ }
+
+ case BLE_EVENT:
+ {
+ if (msg->payload) {
+ app_instance_free_ble_msg(msg->payload);
+ APP_MGR_FREE(msg->payload);
+ }
+ break;
+ }
+
+ case GPIO_INTERRUPT_EVENT:
+ {
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ APP_MGR_FREE(msg);
+}
+
+static void
+app_instance_queue_callback(void *queue_msg)
+{
+ bh_queue_msg_t *msg = (bh_queue_msg_t *)queue_msg;
+ unsigned int argv[5];
+ uint8 argt[5];
+
+ if (app_manager_is_interrupting_module(Module_Jeff)) {
+ app_instance_queue_free_callback(queue_msg);
+ return;
+ }
+
+ switch (msg->message_type) {
+ case APPLET_REQUEST:
+ {
+ JeffLocalObjectRef ref;
+ AEERequest req_obj;
+ bh_request_msg_t *req_msg = (bh_request_msg_t *)msg->payload;
+ attr_container_t *attr_cont = (attr_container_t *)req_msg->payload;
+ module_data *m_data = app_manager_get_module_data(Module_Jeff);
+ jeff_applet_data *applet_data =
+ (jeff_applet_data *)m_data->internal_data;
+
+ app_manager_printf("Applet %s got request, url %s, action %d\n",
+ m_data->module_name, req_msg->url,
+ req_msg->action);
+
+ /* Create Request object */
+ req_obj =
+ (AEERequest)jeff_object_new(m_data->heap, class_AEERequest);
+ if (!req_obj) {
+ app_manager_printf("Applet process request failed: create "
+ "request obj failed.\n");
+ goto fail1;
+ }
+
+ jeff_runtime_push_local_object_ref(&ref);
+ ref.val = (JeffObjectRef)req_obj;
+
+ req_obj->mid = req_msg->mid;
+ req_obj->action = req_msg->action;
+ req_obj->fmt = req_msg->fmt;
+
+ /* Create Java url string */
+ if (req_msg->url) {
+ req_obj->url =
+ (jstring)jeff_runtime_create_java_string(req_msg->url);
+ if (!req_obj->url) {
+ app_manager_printf("Applet process request failed: "
+ "create url string failed.\n");
+ goto fail2;
+ }
+ }
+
+ /* Create Java AttributeObject payload */
+ if (attr_cont
+ && !attr_container_to_attr_obj(attr_cont, &req_obj->payload)) {
+ app_manager_printf("Applet process request failed: convert "
+ "payload failed.\n");
+ goto fail2;
+ }
+
+ /* Call AEEApplet.callOnRequest(Request request) method */
+ argv[0] = (unsigned int)applet_data->applet_obj;
+ argv[1] = (unsigned int)req_obj;
+ argt[0] = argt[1] = 1;
+ app_manager_call_java(method_AEEApplet_callOnRequest, 2, argv,
+ argt);
+ app_manager_printf("Applet process request success.\n");
+
+ fail2:
+ jeff_runtime_pop_local_object_ref(1);
+ fail1:
+ APP_MGR_FREE(req_msg);
+ break;
+ }
+
+ case TIMER_EVENT:
+ {
+ if (msg->payload) {
+ /* Call Timer.callOnTimer() method */
+ argv[0] = (unsigned int)msg->payload;
+ argt[0] = 1;
+ app_manager_call_java(method_callOnTimer, 1, argv, argt);
+ }
+ break;
+ }
+
+ case SENSOR_EVENT:
+ {
+ if (msg->payload) {
+ bh_sensor_event_t *sensor_event =
+ (bh_sensor_event_t *)msg->payload;
+ AEESensor sensor = sensor_event->sensor;
+ attr_container_t *event = sensor_event->event;
+ bool ret = attr_container_to_attr_obj(event, &sensor->event);
+
+ attr_container_destroy(event);
+ APP_MGR_FREE(sensor_event);
+
+ if (ret) {
+ /* Call Sensor.callOnSensorEvent() method */
+ argv[0] = (unsigned int)sensor;
+ argt[0] = 1;
+ app_manager_call_java(method_callOnSensorEvent, 1, argv,
+ argt);
+ }
+ }
+ break;
+ }
+
+ case BLE_EVENT:
+ {
+ if (msg->payload) {
+ app_instance_process_ble_msg(msg->payload);
+ APP_MGR_FREE(msg->payload);
+ }
+ break;
+ }
+
+ case GPIO_INTERRUPT_EVENT:
+ {
+ AEEGPIOChannel gpio_ch = (AEEGPIOChannel)msg->payload;
+
+ if ((gpio_ch == NULL) || (gpio_ch->callback == 0)
+ || (gpio_ch->listener == NULL)) {
+ break;
+ }
+ argv[0] = (unsigned int)gpio_ch;
+ argt[0] = 1;
+ bool ret_value = app_manager_call_java(method_callOnGPIOInterrupt,
+ 1, argv, argt);
+
+ if (!ret_value) {
+ app_manager_printf(
+ "app_manager_call_java "
+ "method_method_callOnGPIOInterrupt return false\n");
+ }
+ break;
+ }
+
+ default:
+ {
+ app_manager_printf(
+ "Invalid message type of applet queue message.\n");
+ break;
+ }
+ }
+
+ APP_MGR_FREE(msg);
+}
+
+static JeffClassHeaderLinked *
+find_main_class(JeffFileHeaderLinked *main_file)
+{
+ JeffClassHeaderLinked *c = NULL, *ci;
+ unsigned int i;
+
+ for (i = 0; i < main_file->internal_class_count; i++) {
+ ci = main_file->class_header[i];
+
+ if (jeff_is_super_class(class_AEEApplet, ci)
+ && (ci->access_flag & JEFF_ACC_PUBLIC)) {
+ if (c) {
+ jeff_printe_more_than_one_main_class();
+ return NULL;
+ }
+
+ c = ci;
+ }
+ }
+
+ if (!c)
+ jeff_printe_no_main_class();
+
+ return c;
+}
+
+/* Java applet thread main routine */
+static void *
+app_instance_main(void *arg)
+{
+ module_data *m_data = (module_data *)arg;
+ jeff_applet_data *applet_data = (jeff_applet_data *)m_data->internal_data;
+ JeffClassHeaderLinked *object_class;
+ JeffMethodLinked *m;
+ unsigned int argv[1];
+ uint8 argt[1];
+
+ app_manager_printf("Java Applet '%s' started\n", m_data->module_name);
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ if (applet_data->debug_mode)
+ jeff_tool_suspend_self();
+#endif
+
+ applet_data->vm_instance->applet_object = applet_data->applet_obj;
+ object_class = jeff_object_class_pointer(applet_data->applet_obj);
+ m = jeff_select_method_virtual(object_class, method_AEEApplet_onInit);
+ bh_assert(m != NULL);
+ /* Initialize applet class which call <clinit> */
+ if (!app_manager_initialize_class(object_class)) {
+ app_manager_printf("Call <clinit> fail\n");
+ goto fail;
+ }
+
+ /* Initialize applet object which call <init> */
+ if (!app_manager_initialize_object(applet_data->applet_obj)) {
+ app_manager_printf("Call <init> fail\n");
+ goto fail;
+ }
+
+ /* Call applet's onInit() method */
+ argv[0] = (unsigned int)applet_data->applet_obj;
+ argt[0] = 1;
+ if (app_manager_call_java(m, 1, argv, argt))
+ /* Enter queue loop run to receive and process applet queue message
+ */
+ bh_queue_enter_loop_run(m_data->queue, app_instance_queue_callback);
+
+fail:
+ applet_data->vm_instance->applet_object = applet_data->applet_obj;
+ object_class = jeff_object_class_pointer(applet_data->applet_obj);
+ m = jeff_select_method_virtual(object_class, method_AEEApplet_onDestroy);
+ bh_assert(m != NULL);
+ /* Call User Applet or AEEApplet onDestroy() method */
+ app_manager_call_java(m, 1, argv, argt);
+ if (m != method_AEEApplet_onDestroy) {
+ /*If 'm' is user onDestroy, then Call AEEApplet.onDestroy() method*/
+ app_manager_call_java(method_AEEApplet_onDestroy, 1, argv, argt);
+ }
+ app_manager_printf("Applet instance main thread exit.\n");
+ return NULL;
+}
+
+static bool
+verify_signature(JeffFileHeader *file, unsigned size)
+{
+ uint8 *sig;
+ unsigned sig_size;
+
+#if BEIHAI_ENABLE_NO_SIGNATURE != 0
+ /* no signature */
+ if (file->file_signature == 0)
+ return true;
+#endif
+
+ if (file->file_length != size
+#if BEIHAI_ENABLE_NO_SIGNATURE == 0
+ || file->file_signature == 0
+#endif
+ || file->file_signature >= file->file_length)
+ return false;
+
+ sig = (uint8 *)file + file->file_signature;
+ sig_size = file->file_length - file->file_signature;
+
+ if (0
+ == app_manager_signature_verify((uint8_t *)file, file->file_signature,
+ sig, sig_size))
+ return false;
+
+ return true;
+}
+
+/* Install Java Applet */
+static bool
+jeff_module_install(bh_request_msg_t *msg)
+{
+ unsigned int size, bpk_file_len, main_file_len, heap_size, timeout;
+ uint8 *bpk_file;
+ JeffFileHeaderLinked *main_file;
+ JeffClassHeaderLinked *main_class;
+ module_data *m_data;
+ jeff_applet_data *applet_data;
+ char *applet_name, *applet_perm;
+ attr_container_t *attr_cont;
+ bool debug = false;
+
+ /* Check url */
+ if (!msg->url || strcmp(msg->url, "/applet") != 0) {
+ SEND_ERR_RESPONSE(msg->mid, "Install Applet failed: invalid url.");
+ return false;
+ }
+
+ /* Check payload */
+ attr_cont = (attr_container_t *)msg->payload;
+ if (!attr_cont
+ || !(bpk_file = (uint8 *)attr_container_get_as_bytearray(
+ attr_cont, "bpk", &bpk_file_len))) {
+ SEND_ERR_RESPONSE(msg->mid, "Install Applet failed: invalid bpk file.");
+ return false;
+ }
+
+ /* Check applet name */
+ applet_name = attr_container_get_as_string(attr_cont, "name");
+
+ if (!applet_name || strlen(applet_name) == 0) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: invalid applet name.");
+ return false;
+ }
+
+ if (app_manager_lookup_module_data(applet_name)) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: applet already installed.");
+ return false;
+ }
+
+ /* TODO: convert bpk file to Jeff file */
+ main_file_len = bpk_file_len;
+ main_file = APP_MGR_MALLOC(main_file_len);
+ if (!main_file) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: allocate memory failed.");
+ return false;
+ }
+ bh_memcpy_s(main_file, main_file_len, bpk_file, main_file_len);
+
+ /* Verify signature */
+ if (!verify_signature((JeffFileHeader *)main_file, main_file_len)) {
+ SEND_ERR_RESPONSE(
+ msg->mid,
+ "Install Applet failed: verify Jeff file signature failed.");
+ goto fail1;
+ }
+
+ /* Load Jeff main file */
+ if (!jeff_runtime_load(main_file, main_file_len, false, NULL, NULL)) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: load Jeff file failed.");
+ goto fail1;
+ }
+
+ /* Find main class */
+ main_class = find_main_class(main_file);
+ if (!main_class) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: find applet class failed.");
+ goto fail2;
+ }
+
+ /* Create module data */
+ size = offsetof(module_data, module_name) + strlen(applet_name) + 1;
+ size = align_uint(size, 4);
+ m_data = APP_MGR_MALLOC(size + sizeof(jeff_applet_data));
+ if (!m_data) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: allocate memory failed.");
+ goto fail2;
+ }
+
+ memset(m_data, 0, size + sizeof(jeff_applet_data));
+ m_data->module_type = Module_Jeff;
+ m_data->internal_data = (uint8 *)m_data + size;
+ applet_data = (jeff_applet_data *)m_data->internal_data;
+ bh_strcpy_s(m_data->module_name, strlen(applet_name) + 1, applet_name);
+ applet_data->main_file = main_file;
+
+ /* Set applet execution timeout */
+ timeout = DEFAULT_APPLET_TIMEOUT;
+ if (attr_container_contain_key(attr_cont, "execution timeout"))
+ timeout = attr_container_get_as_int(attr_cont, "execution timeout");
+ m_data->timeout = timeout;
+
+ /* Create applet permissions */
+ applet_perm = attr_container_get_as_string(attr_cont, "perm");
+ if (applet_perm != NULL) {
+ applet_data->perms = APP_MGR_MALLOC(strlen(applet_perm) + 1);
+ if (!applet_data->perms) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: allocate memory for "
+ "applet permissions failed.");
+ goto fail3;
+ }
+
+ bh_strcpy_s(applet_data->perms, strlen(applet_perm) + 1, applet_perm);
+ }
+
+ /* Create applet queue */
+ m_data->queue = bh_queue_create();
+ if (!m_data->queue) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: create applet queue failed.");
+ goto fail3_1;
+ }
+
+ /* Set heap size */
+ heap_size = DEFAULT_APPLET_HEAP_SIZE;
+ if (attr_container_contain_key(attr_cont, "heap size")) {
+ heap_size = attr_container_get_as_int(attr_cont, "heap size");
+ if (heap_size < MIN_APPLET_HEAP_SIZE)
+ heap_size = MIN_APPLET_HEAP_SIZE;
+ else if (heap_size > MAX_APPLET_HEAP_SIZE)
+ heap_size = MAX_APPLET_HEAP_SIZE;
+ }
+
+ m_data->heap_size = heap_size;
+
+ /* Create applet heap */
+ m_data->heap = gc_init_for_instance(heap_size);
+ if (!m_data->heap) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: create heap failed.");
+ goto fail4;
+ }
+
+ /* Create applet object */
+ applet_data->applet_obj = jeff_object_new(m_data->heap, main_class);
+ if (!applet_data->applet_obj) {
+ SEND_ERR_RESPONSE(
+ msg->mid, "Install Applet failed: create applet object failed.");
+ goto fail5;
+ }
+
+ /* Initialize watchdog timer */
+ if (!watchdog_timer_init(m_data)) {
+ SEND_ERR_RESPONSE(
+ msg->mid,
+ "Install Applet failed: create applet watchdog timer failed.");
+ goto fail5;
+ }
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ /* Check whether applet is debuggable */
+ if (attr_container_contain_key(attr_cont, "debug"))
+ debug = attr_container_get_as_bool(attr_cont, "debug");
+
+ applet_data->debug_mode = debug;
+
+ /* Create tool agent queue */
+ if (debug && !(applet_data->tool_agent_queue = bh_queue_create())) {
+ SEND_ERR_RESPONSE(
+ msg->mid, "Install Applet failed: create tool agent queue failed.");
+ goto fail5_1;
+ }
+#endif
+
+ /* Create applet instance */
+ applet_data->vm_instance = jeff_runtime_create_instance(
+ main_file, m_data->heap, 16, app_instance_main, m_data, NULL);
+ if (!applet_data->vm_instance) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: create Java VM failed");
+ goto fail6;
+ }
+
+ /* Add applet data to applet data list */
+ applet_data->vm_instance->applet_object = applet_data->applet_obj;
+ app_manager_add_module_data(m_data);
+ app_manager_post_applets_update_event();
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ /* Start tool agent thread */
+ if (debug
+ && !jeff_tool_start_agent(applet_data->vm_instance,
+ applet_data->tool_agent_queue)) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install Applet failed: start tool agent failed");
+ goto fail6;
+ }
+#endif
+
+ app_manager_printf("Install Applet success!\n");
+ app_send_response_to_host(msg->mid, CREATED_2_01, NULL); /* CREATED */
+ return true;
+
+fail6:
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ if (debug)
+ bh_queue_destroy(applet_data->tool_agent_queue);
+#endif
+
+fail5_1:
+ watchdog_timer_destroy(&m_data->wd_timer);
+
+fail5:
+ gc_destroy_for_instance(m_data->heap);
+
+fail4:
+ bh_queue_destroy(m_data->queue, NULL);
+
+fail3_1:
+ APP_MGR_FREE(applet_data->perms);
+
+fail3:
+ APP_MGR_FREE(applet_data);
+
+fail2:
+ jeff_runtime_unload(main_file);
+
+fail1:
+ APP_MGR_FREE(main_file);
+
+ return false;
+}
+
+static void
+cleanup_applet_resource(module_data *m_data)
+{
+ jeff_applet_data *applet_data = (jeff_applet_data *)m_data->internal_data;
+
+ /* Unload Jeff main file and free it */
+ jeff_runtime_unload(applet_data->main_file);
+ APP_MGR_FREE(applet_data->main_file);
+
+ /* Destroy queue */
+ bh_queue_destroy(m_data->queue, app_instance_queue_free_callback);
+
+ /* Destroy heap */
+ gc_destroy_for_instance(m_data->heap);
+
+ /* 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);
+ APP_MGR_FREE(applet_data->perms);
+ APP_MGR_FREE(m_data);
+}
+
+/* Uninstall Java Applet */
+static bool
+jeff_module_uninstall(bh_request_msg_t *msg)
+{
+ module_data *m_data;
+ jeff_applet_data *applet_data;
+ attr_container_t *attr_cont;
+ char *applet_name;
+ bool do_not_reply = false;
+
+ /* Check payload and applet name*/
+ attr_cont = (attr_container_t *)msg->payload;
+
+ /* Check whether need to reply this request */
+ if (attr_container_contain_key(attr_cont, "do not reply me"))
+ do_not_reply = attr_container_get_as_bool(attr_cont, "do not reply me");
+
+ /* Check url */
+ if (!msg->url || strcmp(msg->url, "/applet") != 0) {
+ if (!do_not_reply)
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall Applet failed: invalid url.");
+ else
+ app_manager_printf("Uninstall Applet failed: invalid url.");
+ return false;
+ }
+
+ if (!attr_cont
+ || !(applet_name = attr_container_get_as_string(attr_cont, "name"))
+ || strlen(applet_name) == 0) {
+ if (!do_not_reply)
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall Applet failed: invalid applet name.");
+ else
+ app_manager_printf("Uninstall Applet failed: invalid applet name.");
+ return false;
+ }
+
+ m_data = app_manager_lookup_module_data(applet_name);
+ if (!m_data) {
+ if (!do_not_reply)
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall Applet failed: no applet found.");
+ else
+ app_manager_printf("Uninstall Applet failed: no applet found.");
+ return false;
+ }
+
+ if (m_data->module_type != Module_Jeff) {
+ if (!do_not_reply)
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall Applet failed: invlaid module type.");
+ else
+ app_manager_printf("Uninstall Applet failed: invalid module type.");
+ return false;
+ }
+
+ if (m_data->wd_timer.is_interrupting) {
+ if (!do_not_reply)
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall Applet failed: applet is being "
+ "interrupted by watchdog.");
+ else
+ app_manager_printf("Uninstall Applet failed: applet is being "
+ "interrupted by watchdog.");
+ return false;
+ }
+
+ /* Exit applet queue loop run */
+ bh_queue_exit_loop_run(m_data->queue);
+
+ applet_data = (jeff_applet_data *)m_data->internal_data;
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ /* Exit tool agent queue loop run */
+ if (is_tool_agent_running(m_data)) {
+ bh_queue_exit_loop_run(applet_data->tool_agent_queue);
+ }
+#endif
+
+ /* Wait the end of the applet instance and then destroy it */
+ if (applet_data->vm_instance->main_file)
+ jeff_runtime_wait_for_instance(applet_data->vm_instance, -1);
+ jeff_runtime_destroy_instance(applet_data->vm_instance);
+
+ cleanup_applet_resource(m_data);
+ app_manager_post_applets_update_event();
+
+ app_manager_printf("Uninstall Applet success!\n");
+
+ if (!do_not_reply)
+ app_send_response_to_host(msg->mid, DELETED_2_02, NULL); /* DELETED */
+ return true;
+}
+
+#define PERM_PREFIX "AEE.permission."
+
+static bool
+check_permission_format(const char *perm)
+{
+ const char *prefix = PERM_PREFIX;
+ const char *p;
+
+ if (perm == NULL || strncmp(perm, prefix, strlen(prefix)) != 0
+ || *(p = perm + strlen(prefix)) == '\0')
+ return false;
+
+ do {
+ if (!(*p == '.' || ('A' <= *p && *p <= 'Z')
+ || ('a' <= *p && *p <= 'z')))
+ return false;
+ } while (*++p != '\0');
+
+ return true;
+}
+
+static bool
+match(const char *haystack, const char *needle, char delim)
+{
+ const char *p = needle;
+
+ if (haystack == NULL || *haystack == '\0' || needle == NULL
+ || *needle == '\0')
+ return false;
+
+ while (true) {
+ while (true) {
+ if ((*haystack == '\0' || *haystack == delim) && *p == '\0') {
+ return true;
+ }
+ else if (*p == *haystack) {
+ ++p;
+ ++haystack;
+ }
+ else {
+ break;
+ }
+ }
+ while (*haystack != '\0' && *haystack != delim) {
+ ++haystack;
+ }
+ if (*haystack == '\0') {
+ return false;
+ }
+ else {
+ ++haystack;
+ p = needle;
+ }
+ }
+}
+
+bool
+bh_applet_check_permission(const char *perm)
+{
+ return check_permission_format(perm)
+ && match(app_manager_get_jeff_applet_data()->perms,
+ perm + strlen(PERM_PREFIX), ' ');
+}
+
+static bool
+jeff_module_init()
+{
+ JeffDescriptorFull d[] = { { JEFF_TYPE_VOID, 0, NULL } };
+ JeffDescriptorFull d1[] = { { JEFF_TYPE_OBJECT | JEFF_TYPE_REF, 0, NULL },
+ { JEFF_TYPE_VOID, 0, NULL } };
+
+ /* Resolve class com.intel.aee.AEEApplet */
+ class_AEEApplet =
+ jeff_runtime_resolve_class_full_name("com.intel.aee.AEEApplet");
+ if (!class_AEEApplet) {
+ app_manager_printf(
+ "App Manager start failed: resolve class AEEApplet failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.Request */
+ class_AEERequest =
+ jeff_runtime_resolve_class_full_name("com.intel.aee.Request");
+ if (!class_AEERequest) {
+ app_manager_printf(
+ "App Manager start failed: resolve class Request failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.Timer */
+ class_Timer = jeff_runtime_resolve_class_full_name("com.intel.aee.Timer");
+ if (!class_Timer) {
+ app_manager_printf(
+ "App Manager start failed: resolve class Timer failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.Sensor */
+ class_Sensor = jeff_runtime_resolve_class_full_name("com.intel.aee.Sensor");
+ if (!class_Sensor) {
+ app_manager_printf(
+ "App Manager start failed: resolve class Sensor failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.ble.BLEManager */
+ class_BLEManager =
+ jeff_runtime_resolve_class_full_name("com.intel.aee.ble.BLEManager");
+ if (!class_BLEManager) {
+ app_manager_printf(
+ "App Manager start failed: resolve class BLEManager failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.ble.BLEDevice */
+ class_BLEDevice =
+ jeff_runtime_resolve_class_full_name("com.intel.aee.ble.BLEDevice");
+ if (!class_BLEDevice) {
+ app_manager_printf(
+ "App Manager start failed: resolve class BLEDevice failed.\n");
+ return false;
+ }
+ /* Resolve class com.intel.aee.ble.BLEDevice */
+ class_BLEGattService = jeff_runtime_resolve_class_full_name(
+ "com.intel.aee.ble.BLEGattService");
+ if (!class_BLEGattService) {
+ app_manager_printf("App Manager start failed: resolve class "
+ "BLEGattService failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.ble.BLEDevice */
+ class_BLEGattCharacteristic = jeff_runtime_resolve_class_full_name(
+ "com.intel.aee.ble.BLEGattCharacteristic");
+ if (!class_BLEGattCharacteristic) {
+ app_manager_printf("App Manager start failed: resolve class "
+ "BLEGattCharacteristic failed.\n");
+ return false;
+ }
+
+ /* Resolve class com.intel.aee.ble.BLEDevice */
+ class_BLEGattDescriptor = jeff_runtime_resolve_class_full_name(
+ "com.intel.aee.ble.BLEGattDescriptor");
+ if (!class_BLEGattDescriptor) {
+ app_manager_printf("App Manager start failed: resolve class "
+ "BLEGattDescriptor failed.\n");
+ return false;
+ }
+ /* Resolve class com.intel.aee.gpio.GPIOChannel */
+ class_GPIOChannel =
+ jeff_runtime_resolve_class_full_name("com.intel.aee.gpio.GPIOChannel");
+ if (!class_GPIOChannel) {
+ app_manager_printf("App Manager start failed: resolve class "
+ "GPIOChannel failed.\n");
+ return false;
+ }
+
+ /* Resolve method com.intel.aee.AEEApplet.onInit() */
+ method_AEEApplet_onInit =
+ jeff_lookup_method(class_AEEApplet, "onInit", 0, d);
+ if (!method_AEEApplet_onInit) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "Applet.onInit() failed.\n");
+ return false;
+ }
+
+ /* Resolve method com.intel.aee.AEEApplet.onDestroy() */
+ method_AEEApplet_onDestroy =
+ jeff_lookup_method(class_AEEApplet, "onDestroy", 0, d);
+ if (!method_AEEApplet_onDestroy) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "AEEApplet.onDestroy() failed.\n");
+ return false;
+ }
+
+ /* Resolve method com.intel.aee.AEEApplet.callOnRequest(Request) */
+ d1[0].class_header = class_AEERequest;
+ method_AEEApplet_callOnRequest =
+ jeff_lookup_method(class_AEEApplet, "callOnRequest", 1, d1);
+ if (!method_AEEApplet_callOnRequest) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "AEEApplet.callOnRequest() failed.\n");
+ return false;
+ }
+
+ /* Resolve method com.intel.aee.Timer.callOnTimer() */
+ method_callOnTimer = jeff_lookup_method(class_Timer, "callOnTimer", 0, d);
+ if (!method_callOnTimer) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "Timer.callOnTimer() failed.\n");
+ return false;
+ }
+
+ /* Resolve method com.intel.aee.Sensor.callOnSensorEvent() */
+ method_callOnSensorEvent =
+ jeff_lookup_method(class_Sensor, "callOnSensorEvent", 0, d);
+ if (!method_callOnSensorEvent) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "Sensor.callOnSensorEvent() failed.\n");
+ return false;
+ }
+
+ /* Resovle method
+ * com.intel.aee.ble.BLEManager.callOnBLEStartDiscovery(BLEDevice) */
+ d1[0].class_header = class_BLEDevice;
+ method_callOnBLEStartDiscovery =
+ jeff_lookup_method(class_BLEManager, "callOnBLEStartDiscovery", 1, d1);
+ if (!method_callOnBLEStartDiscovery) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.callOnBLEStartDiscovery() failed.\n");
+ return false;
+ }
+
+ /* Resovle method
+ * com.intel.aee.ble.BLEManager.callOnBLEConnected(BLEDevice) */
+ JeffDescriptorFull d2_1[] = { { JEFF_TYPE_OBJECT | JEFF_TYPE_REF, 0,
+ class_BLEDevice },
+ { JEFF_TYPE_INT, 0, NULL },
+ { JEFF_TYPE_VOID, 0, NULL } };
+ method_callOnBLEConnected =
+ jeff_lookup_method(class_BLEManager, "callOnBLEConnected", 2, d2_1);
+ if (!method_callOnBLEConnected) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.callOnBLEConnected() failed.\n");
+ return false;
+ }
+
+ /* Resovle method
+ * com.intel.aee.ble.BLEManager.method_callOnBLENotification(BLEDevice,byte[])
+ */
+ JeffDescriptorFull d2_2[] = {
+ { JEFF_TYPE_OBJECT | JEFF_TYPE_REF, 0, class_BLEDevice },
+ { JEFF_TYPE_BYTE | JEFF_TYPE_REF | JEFF_TYPE_MONO, 1, NULL },
+ { JEFF_TYPE_INT, 0, NULL },
+ { JEFF_TYPE_INT, 0, NULL },
+ { JEFF_TYPE_VOID, 0, NULL }
+ };
+ method_callOnBLENotification =
+ jeff_lookup_method(class_BLEManager, "callOnBLENotification", 4, d2_2);
+ if (!method_callOnBLENotification) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.callOnBLENotification() failed.\n");
+ return false;
+ }
+
+ /* Resovle method
+ * com.intel.aee.ble.BLEManager.callOnBLEConnected(BLEDevice,byte[]) */
+ method_callOnBLEIndication =
+ jeff_lookup_method(class_BLEManager, "callOnBLEIndication", 4, d2_2);
+ if (!method_callOnBLEIndication) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.callOnBLEIndication() failed.\n");
+ return false;
+ }
+
+ /* Resovle method
+ * com.intel.aee.ble.BLEManager.callOnBLEConnected(BLEDevice) */
+ d1[0].class_header = class_BLEDevice;
+ method_callOnBLEDisconnected =
+ jeff_lookup_method(class_BLEManager, "callOnBLEDisconnected", 1, d1);
+ if (!method_callOnBLEDisconnected) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.callOnBLEDisconnected() failed.\n");
+ return false;
+ }
+
+ /* Resovle method
+ * com.intel.aee.ble.BLEManager.callOnBLEConnected(BLEDevice) */
+ method_callOnBLEPasskeyEntry =
+ jeff_lookup_method(class_BLEManager, "callOnBLEPasskeyEntry", 1, d1);
+ if (!method_callOnBLEPasskeyEntry) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.callOnBLEPasskeyEntry() failed.\n");
+ return false;
+ }
+ /* Resovle method void
+ * com.intel.aee.gpio.GPIOChannel.callOnGPIOInterrupt() */
+ method_callOnGPIOInterrupt =
+ jeff_lookup_method(class_GPIOChannel, "callOnGPIOInterrupt", 0, d);
+ if (!method_callOnGPIOInterrupt) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "GPIOChannel.callOnGPIOInterrupt() failed.\n");
+ return false;
+ }
+
+ JeffDescriptorFull d2[] = {
+ { JEFF_TYPE_BYTE | JEFF_TYPE_REF | JEFF_TYPE_MONO, 1, NULL },
+ { JEFF_TYPE_OBJECT | JEFF_TYPE_REF, 0, class_BLEDevice }
+ };
+ /* Resovle method com.intel.aee.ble.BLEManager.getBLEDevice(byte []) */
+ method_callOnBLEManagerGetBLEDevice =
+ jeff_lookup_method(class_BLEManager, "getBLEDevice", 1, d2);
+ if (!method_callOnBLEManagerGetBLEDevice) {
+ app_manager_printf("App Manager start failed: resolve method "
+ "BLEManager.getBLEDevice() failed.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void
+jeff_module_watchdog_kill(module_data *m_data)
+{
+ jeff_applet_data *applet_data = (jeff_applet_data *)m_data->internal_data;
+
+ app_manager_printf("Watchdog interrupt the applet %s\n",
+ m_data->module_name);
+
+ jeff_runtime_interrupt_instance(applet_data->vm_instance, true);
+
+ /* Exit applet queue loop run */
+ bh_queue_exit_loop_run(m_data->queue);
+
+ /* Wait the end of the applet instance. If timeout, it means applet
+ * is busy executing native code, then try to cancle the main thread. */
+ if (applet_data->vm_instance->main_file)
+ jeff_runtime_wait_for_instance(applet_data->vm_instance, 3000);
+
+ if (applet_data->vm_instance->main_file) {
+ app_manager_printf("Watchdog cancel applet main thread.\n");
+ os_thread_cancel(applet_data->vm_instance->main_tlr.handle);
+ /* k_thread_abort(applet_data->vm_instance->main_tlr.handle); */
+ }
+
+ send_exception_event_to_host(m_data->module_name,
+ "java.lang.InterruptedException");
+ cleanup_applet_resource(m_data);
+ app_manager_printf("Watchdog interrupt Jeff applet done.\n");
+}
+
+static bool
+jeff_module_handle_host_url(void *queue_msg)
+{
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+ bh_queue_msg_t *msg = (bh_queue_msg_t *)queue_msg;
+
+ if (msg->message_type == COAP_PARSED) {
+ coap_packet_t *packet = (coap_packet_t *)msg->payload;
+ attr_container_t *attr_cont = (attr_container_t *)packet->payload;
+ const char *url = NULL;
+ int url_len = 0, mid;
+
+ bh_memcpy_s(&mid, sizeof(uint32), packet->token, sizeof(uint32));
+ url_len = coap_get_header_uri_path(packet, &url);
+
+ /* Send request to tool agent */
+ if (url_len >= 12 && memcmp(url, "/tool_agent/", 12) == 0) {
+ module_data *m_data;
+ jeff_applet_data *applet_data;
+ unsigned attr_cont_len = 0, req_msg_len;
+ bh_queue_msg_t *tool_agent_msg;
+ bh_request_msg_t *req_msg;
+ char url_buf[256] = { 0 }, *p = url_buf;
+ char applet_name[128] = { 0 };
+
+ /* Resolve applet name */
+ bh_memcpy_s(url_buf, sizeof(url_buf), url + 12, url_len - 12);
+ while (*p != '/' && *p != '\0')
+ p++;
+
+ bh_memcpy_s(applet_name, sizeof(applet_name), url_buf, p - url_buf);
+ app_manager_printf("Send request to tool agent of applet: %s\n",
+ applet_name);
+
+ /* Check applet name */
+ if (!(m_data = app_manager_lookup_module_data(applet_name))) {
+ SEND_ERR_RESPONSE(mid, "Send request to tool agent failed: "
+ "invalid applet name");
+ return false;
+ }
+
+ applet_data = (jeff_applet_data *)m_data->internal_data;
+ /* Attach debug: start the tool agent firstly */
+ if (packet->code == COAP_PUT) {
+ if (is_tool_agent_running(m_data)) {
+ SEND_ERR_RESPONSE(mid, "Attach debug failed: tool "
+ "agent is already exist.");
+ return false;
+ }
+
+ applet_data->debug_mode = true;
+
+ /* Create tool agent queue */
+ if (!(applet_data->tool_agent_queue = bh_queue_create())) {
+ SEND_ERR_RESPONSE(mid, "Attach debug failed: create "
+ "tool agent queue failed.");
+ return false;
+ }
+
+ /* Start tool agent thread */
+ if (!jeff_tool_start_agent(applet_data->vm_instance,
+ applet_data->tool_agent_queue)) {
+ bh_queue_destroy(applet_data->tool_agent_queue, NULL);
+ SEND_ERR_RESPONSE(
+ mid, "Attach debug failed: start tool agent failed");
+ return false;
+ }
+
+ app_manager_printf("Attach debug: start tool agent of "
+ "applet %s success.\n",
+ applet_name);
+ app_send_response_to_host(mid, CREATED_2_01, NULL); /* OK */
+ }
+ else {
+ /* Check tool agent running */
+ if (!is_tool_agent_running(m_data)) {
+ SEND_ERR_RESPONSE(mid, "Send request to tool agent failed: "
+ "tool agent is not running");
+ return false;
+ }
+
+ /* Create queue message for tool agent */
+ if (!(tool_agent_msg =
+ APP_MGR_MALLOC(sizeof(bh_queue_msg_t)))) {
+ SEND_ERR_RESPONSE(mid, "Send request to tool agent failed: "
+ "allocate memory failed");
+ return false;
+ }
+
+ if (attr_cont)
+ attr_cont_len =
+ attr_container_get_serialize_length(attr_cont);
+
+ req_msg_len =
+ sizeof(bh_request_msg_t) + strlen(p) + 1 + attr_cont_len;
+
+ /* Create request message */
+ if (!(req_msg = APP_MGR_MALLOC(req_msg_len))) {
+ SEND_ERR_RESPONSE(mid, "Send request to applet failed: "
+ "allocate memory failed");
+ APP_MGR_FREE(tool_agent_msg);
+ return false;
+ }
+
+ /* Set request message */
+ memset(req_msg, 0, req_msg_len);
+ req_msg->mid = mid;
+ req_msg->url = (char *)req_msg + sizeof(bh_request_msg_t);
+ bh_strcpy_s(req_msg->url, strlen(p) + 1,
+ p); /* Actual url sent to tool agent */
+ req_msg->action = packet->code;
+ req_msg->fmt = 0;
+ if (attr_cont) {
+ req_msg->payload = (char *)req_msg
+ + sizeof(bh_request_msg_t) + strlen(p)
+ + 1;
+ attr_container_serialize(req_msg->payload, attr_cont);
+ }
+
+ /* Set queue message and send to tool agent's queue */
+ tool_agent_msg->message_type = JDWP_REQUEST;
+ tool_agent_msg->payload_size = req_msg_len;
+ tool_agent_msg->payload = (char *)req_msg;
+ if (!bh_queue_send_message(applet_data->tool_agent_queue,
+ tool_agent_msg)) {
+ APP_MGR_FREE(req_msg);
+ APP_MGR_FREE(tool_agent_msg);
+ SEND_ERR_RESPONSE(mid, "Send request to tool agent failed: "
+ "send queue msg failed.");
+ return false;
+ }
+
+ /* app_manager_printf("Send request to tool agent of applet
+ * %s success.\n", applet_name); */
+ }
+
+ return true;
+ }
+ }
+#endif /* BEIHAI_ENABLE_TOOL_AGENT != 0 */
+ return false;
+}
+
+static module_data *
+jeff_module_get_module_data(void)
+{
+ JeffThreadLocalRoot *self = jeff_runtime_get_tlr();
+ return (module_data *)self->il_root->start_routine_arg;
+}
+
+#if BEIHAI_ENABLE_TOOL_AGENT != 0
+
+#define JDWP_HANDSHAKE_MAGIC "JDWP-Handshake"
+#define JDWP_HANDSHAKE_LEN (sizeof(JDWP_HANDSHAKE_MAGIC) - 1)
+
+#define JDWP_PAYLOAD_KEY "jdwp"
+
+static bool debug = true;
+
+static bool
+send_msg_to_host(int mid, const char *url, int code, const uint8 *msg,
+ unsigned size)
+{
+ bool ret;
+ int payload_len = 0;
+ attr_container_t *payload = NULL;
+
+ if (msg) {
+ if ((payload = attr_container_create(""))) {
+ attr_container_set_bytearray(&payload, JDWP_PAYLOAD_KEY,
+ (const int8_t *)msg, size);
+ payload_len = attr_container_get_serialize_length(payload);
+ }
+ }
+ ret = app_send_msg_to_host(mid, url, code, (char *)payload, payload_len);
+
+ if (payload)
+ attr_container_destroy(payload);
+
+ return ret;
+}
+
+static bool
+send_response(int mid, int code, const uint8 *msg, unsigned size)
+{
+ return send_msg_to_host(mid, NULL, code, msg, size);
+}
+
+static bool
+send_packet_response(int mid, int code, JeffBuffer *packet)
+{
+ int size;
+
+ if ((size = jeff_buffer_size(packet)) == 0)
+ /* No data need to be written, succeed. */
+ return true;
+
+ return send_msg_to_host(mid, NULL, code, jeff_buffer_at(packet, 0), size);
+}
+
+void
+jeff_tool_event_publish(uint8 *evtbuf, unsigned size)
+{
+ char *prefix = "/jdwp/", *url = NULL;
+ int url_len;
+
+ url_len = strlen(prefix) + strlen(app_manager_get_module_name(Module_Jeff));
+ if (NULL == (url = jeff_runtime_malloc(url_len + 1)))
+ return;
+
+ bh_strcpy_s(url, url_len + 1, prefix);
+ bh_strcat_s(url, url_len + 1, app_manager_get_module_name(Module_Jeff));
+
+ /* Event is sent as request so we set code as COAP_PUT */
+ if (event_is_registered(url))
+ send_msg_to_host(0, url, COAP_PUT, evtbuf, size);
+
+ jeff_runtime_free(url);
+}
+
+#define SEND_ERROR_RESPONSE(err_msg) \
+ do { \
+ app_manager_printf("%s\n", err_msg); \
+ send_response(req_msg->mid, INTERNAL_SERVER_ERROR_5_00, \
+ (uint8 *)err_msg, strlen(err_msg) + 1); \
+ } while (0)
+
+/* Queue callback of tool agent */
+void
+tool_agent_queue_callback(void *arg)
+{
+ bh_queue_msg_t *msg = (bh_queue_msg_t *)arg;
+
+ if (msg->message_type == JDWP_REQUEST) {
+ bh_request_msg_t *req_msg = (bh_request_msg_t *)msg->payload;
+ attr_container_t *attr_cont = (attr_container_t *)req_msg->payload;
+ JeffThreadLocalRoot *self = jeff_runtime_get_tlr();
+ JeffInstanceLocalRoot *cur_instance = self->il_root;
+ JeffToolAgent *agent = cur_instance->tool_agent;
+ bh_queue *queue = (bh_queue *)self->start_routine_arg;
+
+ if (debug)
+ app_manager_printf(
+ "Tool Agent of applet %s got request, url %s, action %d\n",
+ app_manager_get_module_name(Module_Jeff), req_msg->url,
+ req_msg->action);
+
+ /* Handshake or Process Request */
+ if (req_msg->action == COAP_GET) {
+ uint8 *buf;
+ unsigned buf_len;
+
+ if (!attr_cont
+ || !(buf = (uint8 *)attr_container_get_as_bytearray(
+ attr_cont, JDWP_PAYLOAD_KEY, &buf_len))) {
+ SEND_ERROR_RESPONSE("Tool Agent fail: invalid JDWP payload.");
+ goto fail;
+ }
+
+ if (!agent->connected) {
+ if (buf_len != JDWP_HANDSHAKE_LEN
+ || memcmp(buf, JDWP_HANDSHAKE_MAGIC, JDWP_HANDSHAKE_LEN)) {
+ SEND_ERROR_RESPONSE("Tool Agent fail: handshake fail.");
+ goto fail;
+ }
+
+ /* Handshake success and response */
+ agent->connected = true;
+ send_response(req_msg->mid, CONTENT_2_05, buf, buf_len);
+ }
+ else {
+ /* TODO: tool-agent thread should reuse the request/reply
+ * buffer to avoid allocating memory repeatedly */
+ JeffBuffer request, reply;
+
+ /* Initialize the package buffers. */
+ jeff_buffer_init(&request);
+ jeff_buffer_init(&reply);
+
+ if (!jeff_buffer_resize(&request, buf_len)) {
+ SEND_ERROR_RESPONSE("Tool Agent fail: resize buffer fail.");
+ jeff_buffer_destroy(&request);
+ jeff_buffer_destroy(&reply);
+ goto fail;
+ }
+
+ /* Copy data from request to jeff buffer */
+ bh_memcpy_s(jeff_buffer_at(&request, 0),
+ jeff_buffer_size(&request), buf, buf_len);
+
+ /* Handle JDWP request */
+ if (!jeff_tool_handle_packet(agent, &request, &reply)) {
+ SEND_ERROR_RESPONSE(
+ "Tool agent fail: handle request fail.");
+ jeff_buffer_destroy(&request);
+ jeff_buffer_destroy(&reply);
+ goto fail;
+ }
+
+ /* Response JDWP reply */
+ send_packet_response(req_msg->mid, CONTENT_2_05, &reply);
+
+ /* Destroy the package buffers. */
+ jeff_buffer_destroy(&request);
+ jeff_buffer_destroy(&reply);
+ }
+ }
+ /* Debugger disconnect */
+ else if (req_msg->action == COAP_DELETE) {
+ send_response(req_msg->mid, DELETED_2_02, NULL, 0);
+ bh_queue_exit_loop_run(queue);
+ }
+ else {
+ SEND_ERROR_RESPONSE("Tool agent fail: invalid request.");
+ goto fail;
+ }
+
+ APP_MGR_FREE(req_msg);
+ APP_MGR_FREE(msg);
+ return;
+
+ fail:
+ bh_queue_exit_loop_run(queue);
+ APP_MGR_FREE(req_msg);
+ }
+
+ APP_MGR_FREE(msg);
+}
+
+void
+tool_agent_queue_free_callback(void *message)
+{
+ bh_queue_msg_t *msg = (bh_queue_msg_t *)message;
+
+ if (msg->message_type == JDWP_REQUEST) {
+ bh_request_msg_t *req_msg = (bh_request_msg_t *)msg->payload;
+ APP_MGR_FREE(req_msg);
+ }
+
+ APP_MGR_FREE(msg);
+}
+
+#endif /* BEIHAI_ENABLE_TOOL_AGENT != 0 */
+
+/* clang-format off */
+module_interface jeff_module_interface = {
+ jeff_module_init,
+ jeff_module_install,
+ jeff_module_uninstall,
+ jeff_module_watchdog_kill,
+ jeff_module_handle_host_url,
+ jeff_module_get_module_data,
+ NULL
+};
+/* clang-format on */
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.h
new file mode 100644
index 000000000..bb39f27e4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_jeff.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _MODULE_JEFF_H_
+#define _MODULE_JEFF_H_
+
+#include "app_manager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern module_interface jeff_module_interface;
+
+/* sensor event */
+typedef struct bh_sensor_event_t {
+ /* Java sensor object */
+ void *sensor;
+ /* event of attribute container from context core */
+ void *event;
+} bh_sensor_event_t;
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _MODULE_JEFF_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_utils.c
new file mode 100644
index 000000000..b4b25e4a9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_utils.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "app_manager.h"
+#include "app_manager_host.h"
+#include "bh_platform.h"
+#include "bi-inc/attr_container.h"
+#include "event.h"
+#include "watchdog.h"
+#include "coap_ext.h"
+
+/* Lock of the module data list */
+korp_mutex module_data_list_lock;
+
+/* Module data list */
+module_data *module_data_list;
+
+bool
+module_data_list_init()
+{
+ module_data_list = NULL;
+ return !os_mutex_init(&module_data_list_lock) ? true : false;
+}
+
+void
+module_data_list_destroy()
+{
+
+ os_mutex_lock(&module_data_list_lock);
+ if (module_data_list) {
+ while (module_data_list) {
+ module_data *p = module_data_list->next;
+ APP_MGR_FREE(module_data_list);
+ module_data_list = p;
+ }
+ }
+ os_mutex_unlock(&module_data_list_lock);
+ os_mutex_destroy(&module_data_list_lock);
+}
+
+static void
+module_data_list_add(module_data *m_data)
+{
+ static uint32 module_id_max = 1;
+ os_mutex_lock(&module_data_list_lock);
+ // reserve some special ID
+ // TODO: check the new id is not already occupied!
+ if (module_id_max == 0xFFFFFFF0)
+ module_id_max = 1;
+ m_data->id = module_id_max++;
+ if (!module_data_list) {
+ module_data_list = m_data;
+ }
+ else {
+ /* Set as head */
+ m_data->next = module_data_list;
+ module_data_list = m_data;
+ }
+ os_mutex_unlock(&module_data_list_lock);
+}
+
+void
+module_data_list_remove(module_data *m_data)
+{
+ os_mutex_lock(&module_data_list_lock);
+ if (module_data_list) {
+ if (module_data_list == m_data)
+ module_data_list = module_data_list->next;
+ else {
+ /* Search and remove it */
+ module_data *p = module_data_list;
+
+ while (p && p->next != m_data)
+ p = p->next;
+ if (p && p->next == m_data)
+ p->next = p->next->next;
+ }
+ }
+ os_mutex_unlock(&module_data_list_lock);
+}
+
+module_data *
+module_data_list_lookup(const char *module_name)
+{
+ os_mutex_lock(&module_data_list_lock);
+ if (module_data_list) {
+ module_data *p = module_data_list;
+
+ while (p) {
+ /* Search by module name */
+ if (!strcmp(module_name, p->module_name)) {
+ os_mutex_unlock(&module_data_list_lock);
+ return p;
+ }
+ p = p->next;
+ }
+ }
+ os_mutex_unlock(&module_data_list_lock);
+ return NULL;
+}
+
+module_data *
+module_data_list_lookup_id(unsigned int module_id)
+{
+ os_mutex_lock(&module_data_list_lock);
+ if (module_data_list) {
+ module_data *p = module_data_list;
+
+ while (p) {
+ /* Search by module name */
+ if (module_id == p->id) {
+ os_mutex_unlock(&module_data_list_lock);
+ return p;
+ }
+ p = p->next;
+ }
+ }
+ os_mutex_unlock(&module_data_list_lock);
+ return NULL;
+}
+
+module_data *
+app_manager_get_module_data(uint32 module_type, void *module_inst)
+{
+ if (module_type < Module_Max && g_module_interfaces[module_type]
+ && g_module_interfaces[module_type]->module_get_module_data)
+ return g_module_interfaces[module_type]->module_get_module_data(
+ module_inst);
+ return NULL;
+}
+
+void *
+app_manager_get_module_queue(uint32 module_type, void *module_inst)
+{
+ module_data *m_data = app_manager_get_module_data(module_type, module_inst);
+ return m_data ? m_data->queue : NULL;
+}
+
+const char *
+app_manager_get_module_name(uint32 module_type, void *module_inst)
+{
+ module_data *m_data = app_manager_get_module_data(module_type, module_inst);
+ return m_data ? m_data->module_name : NULL;
+}
+
+unsigned int
+app_manager_get_module_id(uint32 module_type, void *module_inst)
+{
+ module_data *m_data = app_manager_get_module_data(module_type, module_inst);
+ return m_data ? m_data->id : ID_NONE;
+}
+
+void *
+app_manager_get_module_heap(uint32 module_type, void *module_inst)
+{
+ module_data *m_data = app_manager_get_module_data(module_type, module_inst);
+ return m_data ? m_data->heap : NULL;
+}
+
+module_data *
+app_manager_lookup_module_data(const char *name)
+{
+ return module_data_list_lookup(name);
+}
+
+void
+app_manager_add_module_data(module_data *m_data)
+{
+ module_data_list_add(m_data);
+}
+
+void
+app_manager_del_module_data(module_data *m_data)
+{
+ module_data_list_remove(m_data);
+
+ release_module(m_data);
+}
+
+bool
+app_manager_is_interrupting_module(uint32 module_type, void *module_inst)
+{
+ module_data *m_data = app_manager_get_module_data(module_type, module_inst);
+ return m_data ? m_data->wd_timer.is_interrupting : false;
+}
+
+extern void
+destroy_module_timer_ctx(unsigned int module_id);
+
+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);
+#endif
+
+ if (m_data->queue)
+ bh_queue_destroy(m_data->queue);
+
+ m_data->timer_ctx = NULL;
+
+ destroy_module_timer_ctx(m_data->id);
+
+ APP_MGR_FREE(m_data);
+}
+
+uint32
+check_modules_timer_expiry()
+{
+ os_mutex_lock(&module_data_list_lock);
+ module_data *p = module_data_list;
+ uint32 ms_to_expiry = (uint32)-1;
+
+ while (p) {
+ uint32 next = get_expiry_ms(p->timer_ctx);
+ if (next != (uint32)-1) {
+ if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
+ ms_to_expiry = next;
+ }
+
+ p = p->next;
+ }
+ os_mutex_unlock(&module_data_list_lock);
+ return ms_to_expiry;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.c
new file mode 100644
index 000000000..2005ad8e8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.c
@@ -0,0 +1,1743 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "module_wasm_app.h"
+
+#include "native_interface.h" /* for request_t type */
+#include "app_manager_host.h"
+#include "bh_platform.h"
+#include "bi-inc/attr_container.h"
+#include "coap_ext.h"
+#include "event.h"
+#include "watchdog.h"
+#include "runtime_lib.h"
+#if WASM_ENABLE_INTERP != 0
+#include "wasm.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "aot_export.h"
+#endif
+
+/* clang-format off */
+#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
+/* Wasm bytecode file 4 version bytes */
+static uint8 wasm_bytecode_version[4] = {
+ (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[4] = {
+ (uint8)0x02,
+ (uint8)0x00,
+ (uint8)0x00,
+ (uint8)0x00
+};
+#endif
+/* clang-format on */
+
+static union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+/* Wasm App Install Request Receiving Phase */
+typedef enum wasm_app_install_req_recv_phase_t {
+ Phase_Req_Ver,
+ Phase_Req_Action,
+ Phase_Req_Fmt,
+ Phase_Req_Mid,
+ Phase_Req_Sender,
+ Phase_Req_Url_Len,
+ Phase_Req_Payload_Len, /* payload is wasm app binary */
+ Phase_Req_Url,
+
+ /* 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,
+#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 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 app_file;
+ int app_file_magic;
+} install_wasm_app_msg_t;
+
+/* Wasm App Install Request Receive Context */
+typedef struct wasm_app_install_req_recv_ctx_t {
+ wasm_app_install_req_recv_phase_t phase;
+ int size_in_phase;
+ install_wasm_app_msg_t message;
+ int total_received_size;
+} wasm_app_install_req_recv_ctx_t;
+
+/* 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_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);
+
+#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 };
+message_type_handler_t g_msg_callbacks[Max_Msg_Callback] = { 0 };
+
+#define Max_Cleanup_Callback 10
+static resource_cleanup_handler_t g_cleanup_callbacks[Max_Cleanup_Callback] = {
+ 0
+};
+
+module_interface wasm_app_module_interface = {
+ wasm_app_module_init,
+ wasm_app_module_install,
+ wasm_app_module_uninstall,
+ wasm_app_module_watchdog_kill,
+ wasm_app_module_handle_host_url,
+ wasm_app_module_get_module_data,
+ wasm_app_module_on_install_request_byte_arrive
+};
+
+#if WASM_ENABLE_INTERP == 0
+static unsigned
+align_uint(unsigned v, unsigned b)
+{
+ unsigned m = b - 1;
+ return (v + m) & ~m;
+}
+#endif
+
+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 wasm_function_inst_t
+app_manager_lookup_function(const wasm_module_inst_t module_inst,
+ const char *name, const char *signature)
+{
+ wasm_function_inst_t func;
+
+ func = wasm_runtime_lookup_function(module_inst, name, signature);
+ if (!func && name[0] == '_')
+ func = wasm_runtime_lookup_function(module_inst, name + 1, signature);
+ return func;
+}
+
+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;
+ int message_type;
+
+ bh_assert(m_data);
+ wasm_app_data = (wasm_data *)m_data->internal_data;
+ message_type = bh_message_type(queue_msg);
+
+ if (message_type < BASE_EVENT_MAX) {
+ switch (message_type) {
+ case RESTFUL_REQUEST:
+ {
+ request_t *request = (request_t *)bh_message_payload(queue_msg);
+ int size;
+ char *buffer;
+ int32 buffer_offset;
+
+ app_manager_printf("App %s got request, url %s, action %d\n",
+ m_data->module_name, request->url,
+ request->action);
+
+ func_onRequest = app_manager_lookup_function(
+ inst, "_on_request", "(i32i32)");
+ if (!func_onRequest) {
+ app_manager_printf("Cannot find function onRequest\n");
+ break;
+ }
+
+ buffer = pack_request(request, &size);
+ if (buffer == NULL)
+ break;
+
+ buffer_offset =
+ wasm_runtime_module_dup_data(inst, buffer, size);
+ if (buffer_offset == 0) {
+ const char *exception = wasm_runtime_get_exception(inst);
+ if (exception) {
+ app_manager_printf(
+ "Got exception running wasm code: %s\n", exception);
+ wasm_runtime_clear_exception(inst);
+ }
+ free_req_resp_packet(buffer);
+ break;
+ }
+
+ free_req_resp_packet(buffer);
+
+ argv[0] = (uint32)buffer_offset;
+ argv[1] = (uint32)size;
+
+ 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",
+ exception);
+ wasm_runtime_clear_exception(inst);
+ wasm_runtime_module_free(inst, buffer_offset);
+ break;
+ }
+
+ wasm_runtime_module_free(inst, buffer_offset);
+ app_manager_printf("Wasm app process request success.\n");
+ break;
+ }
+ case RESTFUL_RESPONSE:
+ {
+ wasm_function_inst_t func_onResponse;
+ response_t *response =
+ (response_t *)bh_message_payload(queue_msg);
+ int size;
+ char *buffer;
+ int32 buffer_offset;
+
+ app_manager_printf("App %s got response_t,status %d\n",
+ m_data->module_name, response->status);
+
+ func_onResponse = app_manager_lookup_function(
+ inst, "_on_response", "(i32i32)");
+ if (!func_onResponse) {
+ app_manager_printf("Cannot find function on_response\n");
+ break;
+ }
+
+ buffer = pack_response(response, &size);
+ if (buffer == NULL)
+ break;
+
+ buffer_offset =
+ wasm_runtime_module_dup_data(inst, buffer, size);
+ if (buffer_offset == 0) {
+ const char *exception = wasm_runtime_get_exception(inst);
+ if (exception) {
+ app_manager_printf(
+ "Got exception running wasm code: %s\n", exception);
+ wasm_runtime_clear_exception(inst);
+ }
+ free_req_resp_packet(buffer);
+ break;
+ }
+
+ free_req_resp_packet(buffer);
+
+ argv[0] = (uint32)buffer_offset;
+ argv[1] = (uint32)size;
+
+ 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",
+ exception);
+ wasm_runtime_clear_exception(inst);
+ wasm_runtime_module_free(inst, buffer_offset);
+ break;
+ }
+
+ wasm_runtime_module_free(inst, buffer_offset);
+ app_manager_printf("Wasm app process response success.\n");
+ break;
+ }
+ default:
+ {
+ for (int i = 0; i < Max_Msg_Callback; i++) {
+ if (g_msg_type[i] == message_type) {
+ g_msg_callbacks[i](m_data, queue_msg);
+ return;
+ }
+ }
+ app_manager_printf(
+ "Invalid message type of WASM app queue message.\n");
+ break;
+ }
+ }
+ }
+ else {
+ switch (message_type) {
+ case TIMER_EVENT_WASM:
+ {
+ unsigned int timer_id;
+ if (bh_message_payload(queue_msg)) {
+ /* Call Timer.callOnTimer() method */
+ func_onTimer = app_manager_lookup_function(
+ inst, "_on_timer_callback", "(i32)");
+
+ if (!func_onTimer) {
+ app_manager_printf(
+ "Cannot find function _on_timer_callback\n");
+ break;
+ }
+ timer_id =
+ (unsigned int)(uintptr_t)bh_message_payload(queue_msg);
+ argv[0] = timer_id;
+ 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", exception);
+ wasm_runtime_clear_exception(inst);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ for (int i = 0; i < Max_Msg_Callback; i++) {
+ if (g_msg_type[i] == message_type) {
+ g_msg_callbacks[i](m_data, queue_msg);
+ return;
+ }
+ }
+ app_manager_printf(
+ "Invalid message type of WASM app queue message.\n");
+ break;
+ }
+ }
+ }
+}
+
+#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';
+
+ if (mkdir(wasi_dir_buf, 0777) != 0) {
+ if (errno == EEXIST) {
+ /* Failed due to dir already exist */
+ if ((stat(wasi_dir_buf, &st) == 0) && (st.st_mode & S_IFDIR)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+/* WASM app thread main routine */
+static void *
+wasm_app_routine(void *arg)
+{
+ wasm_function_inst_t func_onInit;
+ wasm_function_inst_t func_onDestroy;
+
+ module_data *m_data = (module_data *)arg;
+ wasm_data *wasm_app_data = (wasm_data *)m_data->internal_data;
+ wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
+
+ /* Set m_data to the VM managed instance's custom data */
+ wasm_runtime_set_custom_data(inst, m_data);
+
+ 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);
+ app_manager_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) {
+ app_manager_printf("Cannot find function on_init().\n");
+ goto fail1;
+ }
+
+ 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);
+ app_manager_printf("Got exception running WASM code: %s\n", exception);
+ wasm_runtime_clear_exception(inst);
+ /* call on_destroy() in case some resources are opened in on_init()
+ * and then exception thrown */
+ goto fail2;
+ }
+
+ /* Enter queue loop run to receive and process applet queue message */
+ bh_queue_enter_loop_run(m_data->queue, app_instance_queue_callback, inst);
+
+ app_manager_printf("App instance main thread exit.\n");
+
+fail2:
+ /* Call WASM app onDestroy() method if there is */
+ func_onDestroy = app_manager_lookup_function(inst, "_on_destroy", "()");
+ if (func_onDestroy) {
+ if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onDestroy, 0,
+ NULL)) {
+ const char *exception = wasm_runtime_get_exception(inst);
+ bh_assert(exception);
+ app_manager_printf("Got exception running WASM code: %s\n",
+ exception);
+ wasm_runtime_clear_exception(inst);
+ }
+ }
+
+fail1:
+
+ return NULL;
+}
+
+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);
+
+ am_unregister_event(NULL, m_data->id);
+
+ for (i = 0; i < Max_Cleanup_Callback; i++) {
+ if (g_cleanup_callbacks[i] != NULL)
+ g_cleanup_callbacks[i](m_data->id);
+ else
+ break;
+ }
+
+ wasm_runtime_deinstantiate(wasm_app_data->wasm_module_inst);
+
+ /* 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)
+{
+ uint32 version;
+
+#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
+ version = WASM_CURRENT_VERSION;
+ if (!is_little_endian())
+ exchange_uint32((uint8 *)&version);
+ bh_memcpy_s(wasm_bytecode_version, 4, &version, 4);
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ version = AOT_CURRENT_VERSION;
+ if (!is_little_endian())
+ exchange_uint32((uint8 *)&version);
+ bh_memcpy_s(wasm_aot_version, 4, &version, 4);
+#endif
+ return true;
+}
+
+#define APP_NAME_MAX_LEN 128
+#define MAX_INT_STR_LEN 11
+
+static bool
+wasm_app_module_install(request_t *msg)
+{
+ unsigned int m_data_size, heap_size, stack_size;
+ unsigned int timeout, timers, err_size;
+ char *properties;
+ int properties_offset;
+ wasm_app_file_t *wasm_app_file;
+ wasm_data *wasm_app_data;
+ package_type_t package_type;
+ module_data *m_data = NULL;
+ 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[128], err_resp[256];
+#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);
+
+ /* Check payload */
+ if (!msg->payload || msg->payload_len == 0) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: invalid wasm file.");
+ return false;
+ }
+
+ /* Judge the app type is AOTed or not */
+ package_type = get_package_type((uint8 *)msg->payload, msg->payload_len);
+ wasm_app_file = (wasm_app_file_t *)msg->payload;
+
+ /* Check app name */
+ properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
+ bh_assert(properties_offset > 0);
+ if (properties_offset <= 0) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: invalid app name.");
+ goto fail;
+ }
+
+ properties = msg->url + properties_offset;
+ find_key_value(properties, strlen(properties), "name", m_name,
+ sizeof(m_name) - 1, '&');
+
+ if (strlen(m_name) == 0) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: invalid app name.");
+ goto fail;
+ }
+
+ if (app_manager_lookup_module_data(m_name)) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: app already installed.");
+ goto fail;
+ }
+
+ /* Parse heap size */
+ heap_size = APP_HEAP_SIZE_DEFAULT;
+ find_key_value(properties, strlen(properties), "heap", heap_size_str,
+ sizeof(heap_size_str) - 1, '&');
+ if (strlen(heap_size_str) > 0) {
+ heap_size = atoi(heap_size_str);
+ if (heap_size < APP_HEAP_SIZE_MIN)
+ heap_size = APP_HEAP_SIZE_MIN;
+ else if (heap_size > APP_HEAP_SIZE_MAX)
+ heap_size = APP_HEAP_SIZE_MAX;
+ }
+
+ /* Load WASM file and instantiate*/
+ switch (package_type) {
+#if WASM_ENABLE_AOT != 0
+ case Wasm_Module_AoT:
+ {
+ wasm_aot_file_t *aot_file;
+ /* clang-format off */
+ /* 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,
+ AOT_SECTION_TYPE_CUSTOM,
+ };
+ /* clang-format on */
+
+ 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) {
+ snprintf(err_resp, sizeof(err_resp),
+ "Install WASM app failed: %s", err);
+ SEND_ERR_RESPONSE(msg->mid, err_resp);
+ goto fail;
+ }
+ /* 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.");
+ goto fail;
+ }
+ 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) {
+ snprintf(err_resp, sizeof(err_resp),
+ "Install WASM app failed: %s", err);
+ SEND_ERR_RESPONSE(msg->mid, err);
+ goto fail;
+ }
+ break;
+ }
+#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,
+#if WASM_ENABLE_BULK_MEMORY != 0
+ SECTION_TYPE_DATACOUNT
+#endif
+
+ };
+ /* Sections to be released after instantiating */
+ uint8 sections2[] = { SECTION_TYPE_DATA };
+
+ 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) {
+ snprintf(err_resp, sizeof(err_resp),
+ "Install WASM app failed: %s", err);
+ SEND_ERR_RESPONSE(msg->mid, err_resp);
+ goto fail;
+ }
+
+ /* 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.");
+ goto fail;
+ }
+ 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) {
+ snprintf(err_resp, sizeof(err_resp),
+ "Install WASM app failed: %s", err);
+ SEND_ERR_RESPONSE(msg->mid, err_resp);
+ goto fail;
+ }
+
+ /* Destroy useless sections from list after instantiate */
+ destroy_part_wasm_sections(&bytecode_file->sections, sections2,
+ sizeof(sections2) / sizeof(uint8));
+ break;
+ }
+#endif /* endof WASM_ENALBE_INTERP != 0 || WASM_ENABLE_JIT != 0 */
+ default:
+ SEND_ERR_RESPONSE(
+ msg->mid,
+ "Install WASM app failed: invalid wasm package type.");
+ goto fail;
+ }
+
+ /* Create module data including the wasm_app_data as its internal_data*/
+ m_data_size = offsetof(module_data, module_name) + strlen(m_name) + 1;
+ m_data_size = align_uint(m_data_size, 4);
+ m_data = APP_MGR_MALLOC(m_data_size + sizeof(wasm_data));
+ if (!m_data) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: allocate memory failed.");
+ goto fail;
+ }
+ memset(m_data, 0, m_data_size + sizeof(wasm_data));
+
+ m_data->module_type = Module_WASM_App;
+ m_data->internal_data = (uint8 *)m_data + m_data_size;
+ wasm_app_data = (wasm_data *)m_data->internal_data;
+ wasm_app_data->wasm_module_inst = inst;
+ wasm_app_data->wasm_module = module;
+ wasm_app_data->m_data = m_data;
+ 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);
+
+ /* Set module data - execution timeout */
+ timeout = DEFAULT_WATCHDOG_INTERVAL;
+ find_key_value(properties, strlen(properties), "wd", timeout_str,
+ sizeof(timeout_str) - 1, '&');
+ if (strlen(timeout_str) > 0)
+ timeout = atoi(timeout_str);
+ m_data->timeout = timeout;
+
+ /* Set module data - create queue */
+ m_data->queue = bh_queue_create();
+ if (!m_data->queue) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: create app queue failed.");
+ goto fail;
+ }
+
+ /* Set heap size */
+ m_data->heap_size = heap_size;
+
+ /* Set module data - timers number */
+ timers = DEFAULT_TIMERS_PER_APP;
+ find_key_value(properties, strlen(properties), "timers", timers_str,
+ sizeof(timers_str) - 1, '&');
+ if (strlen(timers_str) > 0) {
+ timers = atoi(timers_str);
+ if (timers > MAX_TIMERS_PER_APP)
+ timers = MAX_TIMERS_PER_APP;
+ }
+
+ /* Attention: must add the module before start the thread! */
+ app_manager_add_module_data(m_data);
+
+ m_data->timer_ctx = create_wasm_timer_ctx(m_data->id, timers);
+ if (!m_data->timer_ctx) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: create app timers failed.");
+ goto fail;
+ }
+
+ /* Initialize watchdog timer */
+ if (!watchdog_timer_init(m_data)) {
+ SEND_ERR_RESPONSE(
+ msg->mid,
+ "Install WASM app failed: create app watchdog timer failed.");
+ goto fail;
+ }
+
+ stack_size = APP_THREAD_STACK_SIZE_DEFAULT;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ stack_size += 4 * BH_KB;
+#endif
+ /* Create WASM app thread. */
+ if (os_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
+ (void *)m_data, stack_size)
+ != 0) {
+ module_data_list_remove(m_data);
+ SEND_ERR_RESPONSE(msg->mid,
+ "Install WASM app failed: create app thread failed.");
+ goto fail;
+ }
+
+ /* only when thread is created it is the flag of installation success */
+ app_manager_post_applets_update_event();
+
+ app_manager_printf("Install WASM app success!\n");
+ send_error_response_to_host(msg->mid, CREATED_2_01, NULL); /* CREATED */
+
+ return true;
+
+fail:
+ if (m_data)
+ release_module(m_data);
+
+ if (inst)
+ wasm_runtime_deinstantiate(inst);
+
+ if (module)
+ wasm_runtime_unload(module);
+
+ if (exec_env)
+ wasm_runtime_destroy_exec_env(exec_env);
+
+ 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)
+{
+ module_data *m_data;
+ wasm_data *wasm_app_data;
+ char m_name[APP_NAME_MAX_LEN] = { 0 };
+ char *properties;
+ int properties_offset;
+
+ properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
+ /* TODO: assert(properties_offset > 0) */
+ if (properties_offset <= 0)
+ return false;
+ properties = msg->url + properties_offset;
+ find_key_value(properties, strlen(properties), "name", m_name,
+ sizeof(m_name) - 1, '&');
+
+ if (strlen(m_name) == 0) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall WASM app failed: invalid app name.");
+ return false;
+ }
+
+ m_data = app_manager_lookup_module_data(m_name);
+ if (!m_data) {
+ SEND_ERR_RESPONSE(msg->mid, "Uninstall WASM app failed: no app found.");
+ return false;
+ }
+
+ if (m_data->module_type != Module_WASM_App) {
+ SEND_ERR_RESPONSE(msg->mid,
+ "Uninstall WASM app failed: invalid module type.");
+ return false;
+ }
+
+ if (m_data->wd_timer.is_interrupting) {
+ SEND_ERR_RESPONSE(
+ msg->mid,
+ "Uninstall WASM app failed: app is being interrupted by watchdog.");
+ return false;
+ }
+
+ /* Exit app queue loop run */
+ bh_queue_exit_loop_run(m_data->queue);
+
+ /* Wait for wasm app thread to exit */
+ wasm_app_data = (wasm_data *)m_data->internal_data;
+ os_thread_join(wasm_app_data->thread_id, NULL);
+
+ cleanup_app_resource(m_data);
+
+ app_manager_post_applets_update_event();
+
+ app_manager_printf("Uninstall WASM app successful!\n");
+
+#ifdef COLLECT_CODE_COVERAGE
+ /* Exit app manager so as to collect code coverage data */
+ if (!strcmp(m_name, "__exit_app_manager__")) {
+ app_manager_printf("Exit app manager\n");
+ bh_queue_exit_loop_run(get_app_manager_queue());
+ }
+#endif
+
+#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)
+{
+ /* TODO: implement in future */
+ app_manager_printf("App handles host url address %d\n",
+ (int)(uintptr_t)queue_msg);
+ return false;
+}
+
+static module_data *
+wasm_app_module_get_module_data(void *inst)
+{
+ wasm_module_inst_t module_inst = (wasm_module_inst_t)inst;
+ return (module_data *)wasm_runtime_get_custom_data(module_inst);
+}
+
+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,
+ message_type_handler_t message_handler)
+{
+ int i;
+ int freeslot = -1;
+ for (i = 0; i < Max_Msg_Callback; i++) {
+ /* replace handler for the same event registered */
+ if (g_msg_type[i] == message_type)
+ break;
+
+ if (g_msg_callbacks[i] == NULL && freeslot == -1)
+ freeslot = i;
+ }
+
+ if (i != Max_Msg_Callback)
+ g_msg_callbacks[i] = message_handler;
+ else if (freeslot != -1) {
+ g_msg_callbacks[freeslot] = message_handler;
+ g_msg_type[freeslot] = message_type;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+bool
+wasm_register_cleanup_callback(resource_cleanup_handler_t handler)
+{
+ int i;
+
+ for (i = 0; i < Max_Cleanup_Callback; i++) {
+ if (g_cleanup_callbacks[i] == NULL) {
+ g_cleanup_callbacks[i] = handler;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#define RECV_INTEGER(value, next_phase) \
+ do { \
+ 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; \
+ } \
+ } while (0)
+
+/* return:
+ * 1: whole wasm app arrived
+ * 0: one valid byte arrived
+ * -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,
+ int *received_size)
+{
+ uint8 *p;
+ int magic;
+ 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;
+ recv_ctx.total_received_size = 0;
+ }
+
+ recv_ctx.total_received_size++;
+ *received_size = recv_ctx.total_received_size;
+
+ if (recv_ctx.phase == Phase_Req_Ver) {
+ if (ch != 1 /* REQUES_PACKET_VER from restful_utils.c */)
+ return false;
+ recv_ctx.phase = Phase_Req_Action;
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Req_Action) {
+ recv_ctx.message.request_action = ch;
+ recv_ctx.phase = Phase_Req_Fmt;
+ recv_ctx.size_in_phase = 0;
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Req_Fmt) {
+ RECV_INTEGER(recv_ctx.message.request_fmt, Phase_Req_Mid);
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Req_Mid) {
+ RECV_INTEGER(recv_ctx.message.request_mid, Phase_Req_Sender);
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Req_Sender) {
+ RECV_INTEGER(recv_ctx.message.request_sender, Phase_Req_Url_Len);
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Req_Url_Len) {
+ p = (uint8 *)&recv_ctx.message.request_url_len;
+
+ p[recv_ctx.size_in_phase++] = ch;
+ if (recv_ctx.size_in_phase
+ == sizeof(recv_ctx.message.request_url_len)) {
+ recv_ctx.message.request_url_len =
+ ntohs(recv_ctx.message.request_url_len);
+ recv_ctx.message.request_url =
+ APP_MGR_MALLOC(recv_ctx.message.request_url_len + 1);
+ if (NULL == recv_ctx.message.request_url) {
+ app_manager_printf("Allocate memory failed!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "allocate memory failed.");
+ goto fail;
+ }
+ memset(recv_ctx.message.request_url, 0,
+ recv_ctx.message.request_url_len + 1);
+ recv_ctx.phase = Phase_Req_Payload_Len;
+ recv_ctx.size_in_phase = 0;
+ }
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Req_Payload_Len) {
+ RECV_INTEGER(recv_ctx.message.wasm_app_size, Phase_Req_Url);
+ return true;
+ }
+ 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_App_Magic;
+ recv_ctx.size_in_phase = 0;
+ }
+ return true;
+ }
+ 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;
+
+ p[recv_ctx.size_in_phase++] = ch;
+
+ if (recv_ctx.size_in_phase == sizeof(recv_ctx.message.app_file_magic)) {
+ 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) {
+ p = (uint8 *)&recv_ctx.message.app_file.u.bytecode.version;
+
+ if (ch == wasm_bytecode_version[recv_ctx.size_in_phase])
+ p[recv_ctx.size_in_phase++] = ch;
+ else {
+ app_manager_printf("Invalid WASM version!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: invalid WASM version.");
+ goto fail;
+ }
+
+ if (recv_ctx.size_in_phase
+ == 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) {
+ uint8 section_type = ch;
+#if WASM_ENABLE_BULK_MEMORY == 0
+ uint8 section_type_max = SECTION_TYPE_DATA;
+#else
+ uint8 section_type_max = SECTION_TYPE_DATACOUNT;
+#endif
+ if (section_type <= section_type_max) {
+ wasm_section_t *new_section;
+ if (!(new_section = (wasm_section_t *)APP_MGR_MALLOC(
+ sizeof(wasm_section_t)))) {
+ app_manager_printf("Allocate memory failed!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "allocate memory failed.");
+ goto fail;
+ }
+ memset(new_section, 0, sizeof(wasm_section_t));
+ new_section->section_type = section_type;
+ new_section->next = NULL;
+
+ /* 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;
+ }
+
+ recv_ctx.phase = Phase_Wasm_Section_Size;
+ recv_ctx.size_in_phase = 0;
+
+ return true;
+ }
+ else {
+ char error_buf[128];
+
+ app_manager_printf("Invalid wasm section type: %d\n", section_type);
+ snprintf(error_buf, sizeof(error_buf),
+ "Install WASM app failed: invalid wasm section type %d",
+ section_type);
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
+ goto fail;
+ }
+ }
+ else if (recv_ctx.phase == Phase_Wasm_Section_Size) {
+ /* the last section is the current receiving one */
+ 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);
+ recv_ctx.size_in_phase++;
+ /* check leab128 overflow for uint32 value */
+ if (recv_ctx.size_in_phase
+ > (sizeof(section->section_body_size) * 8 + 7 - 1) / 7) {
+ app_manager_printf("LEB overflow when parsing section size\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "LEB overflow when parsing section size");
+ goto fail;
+ }
+
+ if ((byte & 0x80) == 0) {
+ /* leb128 encoded section size parsed done */
+ if (!(section->section_body =
+ APP_MGR_MALLOC(section->section_body_size))) {
+ app_manager_printf("Allocate memory failed!\n");
+ SEND_ERR_RESPONSE(
+ recv_ctx.message.request_mid,
+ "Install WASM app failed: allocate memory failed");
+ goto fail;
+ }
+ recv_ctx.phase = Phase_Wasm_Section_Content;
+ recv_ctx.size_in_phase = 0;
+ }
+
+ return true;
+ }
+ else if (recv_ctx.phase == Phase_Wasm_Section_Content) {
+ /* the last section is the current receiving one */
+ wasm_section_t *section =
+ recv_ctx.message.app_file.u.bytecode.section_end;
+
+ bh_assert(section);
+
+ section->section_body[recv_ctx.size_in_phase++] = ch;
+
+ if (recv_ctx.size_in_phase == section->section_body_size) {
+ if (recv_ctx.total_received_size == request_total_size) {
+ /* whole wasm app received */
+ if (module_wasm_app_handle_install_msg(&recv_ctx.message)) {
+ APP_MGR_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");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "handle install message failed");
+ /**
+ * The sections were destroyed inside
+ * module_wasm_app_handle_install_msg(),
+ * no need to destroy again.
+ */
+ return false;
+ }
+ }
+ else {
+ recv_ctx.phase = Phase_Wasm_Section_Type;
+ recv_ctx.size_in_phase = 0;
+ return true;
+ }
+ }
+
+ 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 AOT version!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: invalid AOT version");
+ 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 *)APP_MGR_MALLOC(sizeof(aot_section_t)))) {
+ app_manager_printf("Allocate memory failed!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "allocate memory failed");
+ 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
+ || cur_section->section_type == AOT_SECTION_TYPE_CUSTOM) {
+ recv_ctx.phase = Phase_AOT_Section_Size;
+ recv_ctx.size_in_phase = 0;
+ }
+ else {
+ char error_buf[128];
+
+ app_manager_printf("Invalid AOT section id: %d\n",
+ cur_section->section_type);
+ snprintf(error_buf, sizeof(error_buf),
+ "Install WASM app failed: invalid AOT section id %d",
+ cur_section->section_type);
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
+ 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 *)&section->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) \
+ || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+ /* 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 =
+ os_mmap(NULL, (uint32)total_size, map_prot,
+ map_flags))) {
+ app_manager_printf(
+ "Allocate executable memory failed!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "allocate 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)section->section_body < INT32_MAX);
+#endif
+ }
+ else {
+ if (!(section->section_body =
+ APP_MGR_MALLOC(section->section_body_size))) {
+ app_manager_printf("Allocate memory failed!\n");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "allocate memory failed");
+ 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)) {
+ APP_MGR_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");
+ SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+ "Install WASM app failed: "
+ "handle install message failed");
+ /**
+ * The sections were destroyed inside
+ * module_wasm_app_handle_install_msg(),
+ * no need to destroy again.
+ */
+ return false;
+ }
+ }
+ 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:
+ /* Restore the package type */
+ 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:
+ 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) {
+ APP_MGR_FREE(recv_ctx.message.request_url);
+ recv_ctx.message.request_url = NULL;
+ }
+
+ memset(&recv_ctx, 0, sizeof(recv_ctx));
+ return false;
+}
+
+static bool
+module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message)
+{
+ request_t *request = NULL;
+ bh_message_t msg;
+
+ request = (request_t *)APP_MGR_MALLOC(sizeof(request_t));
+ if (request == NULL)
+ return false;
+
+ memset(request, 0, sizeof(*request));
+ request->action = message->request_action;
+ request->fmt = message->request_fmt;
+ request->url = bh_strdup(message->request_url);
+ request->sender = ID_HOST;
+ request->mid = message->request_mid;
+ request->payload_len = sizeof(message->app_file);
+ request->payload = APP_MGR_MALLOC(request->payload_len);
+
+ if (request->url == NULL || request->payload == NULL) {
+ request_cleaner(request);
+ return false;
+ }
+
+ /* Request payload is set to wasm_app_file_t struct,
+ * but not whole app buffer */
+ bh_memcpy_s(request->payload, 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
+ * failed to post to app-mgr's queue. The defect is missing url check. */
+ if (!(msg = bh_new_msg(RESTFUL_REQUEST, request, sizeof(*request),
+ request_cleaner))) {
+ request_cleaner(request);
+ return false;
+ }
+
+ if (!bh_post_msg2(get_app_manager_queue(), msg))
+ return false;
+
+ return true;
+}
+
+#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;
+ while (cur) {
+ wasm_section_t *next = cur->next;
+ if (cur->section_body != NULL)
+ APP_MGR_FREE(cur->section_body);
+ APP_MGR_FREE(cur);
+ cur = next;
+ }
+}
+
+static void
+destroy_part_wasm_sections(wasm_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];
+ wasm_section_t *cur = *p_sections, *prev = NULL;
+
+ while (cur) {
+ wasm_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)
+ APP_MGR_FREE(cur->section_body);
+ APP_MGR_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) {
+ aot_section_t *next = cur->next;
+ if (cur->section_body != NULL) {
+ if (cur->section_type == AOT_SECTION_TYPE_TEXT)
+ os_munmap(cur->section_body, cur->section_body_size);
+ else
+ APP_MGR_FREE(cur->section_body);
+ }
+ APP_MGR_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)
+ os_munmap(cur->section_body, cur->section_body_size);
+ else
+ APP_MGR_FREE(cur->section_body);
+ }
+ APP_MGR_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;
+
+ snprintf(wasi_root_dir, sizeof(wasi_root_dir), "%s", path);
+ return true;
+}
+
+const char *
+wasm_get_wasi_root_dir()
+{
+ return wasi_root_dir;
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.h
new file mode 100644
index 000000000..8a7ae4e54
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_app.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _MODULE_WASM_APP_H_
+#define _MODULE_WASM_APP_H_
+
+#include "bh_queue.h"
+#include "app_manager_export.h"
+#include "wasm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SECTION_TYPE_USER 0
+#define SECTION_TYPE_TYPE 1
+#define SECTION_TYPE_IMPORT 2
+#define SECTION_TYPE_FUNC 3
+#define SECTION_TYPE_TABLE 4
+#define SECTION_TYPE_MEMORY 5
+#define SECTION_TYPE_GLOBAL 6
+#define SECTION_TYPE_EXPORT 7
+#define SECTION_TYPE_START 8
+#define SECTION_TYPE_ELEM 9
+#define SECTION_TYPE_CODE 10
+#define SECTION_TYPE_DATA 11
+
+typedef enum AOTSectionType {
+ AOT_SECTION_TYPE_TARGET_INFO = 0,
+ AOT_SECTION_TYPE_INIT_DATA = 1,
+ AOT_SECTION_TYPE_TEXT = 2,
+ AOT_SECTION_TYPE_FUNCTION = 3,
+ AOT_SECTION_TYPE_EXPORT = 4,
+ AOT_SECTION_TYPE_RELOCATION = 5,
+ AOT_SECTION_TYPE_SIGANATURE = 6,
+ AOT_SECTION_TYPE_CUSTOM = 100,
+} AOTSectionType;
+
+enum {
+ WASM_Msg_Start = BASE_EVENT_MAX,
+ TIMER_EVENT_WASM,
+ SENSOR_EVENT_WASM,
+ CONNECTION_EVENT_WASM,
+ WIDGET_EVENT_WASM,
+ WASM_Msg_End = WASM_Msg_Start + 100
+};
+
+typedef struct wasm_data {
+ /* for easily access the containing wasm module */
+ wasm_module_t wasm_module;
+ wasm_module_inst_t wasm_module_inst;
+ /* Permissions of the WASM app */
+ char *perms;
+ /* thread list mapped with this WASM module */
+ korp_tid thread_id;
+ /* for easily access the containing module data */
+ module_data *m_data;
+ /* 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 */
+typedef struct _sensor_event_data {
+ uint32 sensor_id;
+
+ int data_fmt;
+ /* event of attribute container from context core */
+ void *data;
+} sensor_event_data_t;
+
+/* WASM Bytecode File */
+typedef struct wasm_bytecode_file {
+ /* magics */
+ int magic;
+ /* current version */
+ int version;
+ /* WASM section list */
+ 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;
+
+typedef void (*message_type_handler_t)(module_data *m_data, bh_message_t msg);
+extern bool
+wasm_register_msg_callback(int msg_type,
+ message_type_handler_t message_handler);
+
+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
+
+#endif /* _MODULE_WASM_APP_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.c
new file mode 100644
index 000000000..0b5c07ea7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "module_wasm_lib.h"
+
+static bool
+wasm_lib_module_init(void)
+{
+ return false;
+}
+
+static bool
+wasm_lib_module_install(request_t *msg)
+{
+ (void)msg;
+ return false;
+}
+
+static bool
+wasm_lib_module_uninstall(request_t *msg)
+{
+ (void)msg;
+ return false;
+}
+
+static void
+wasm_lib_module_watchdog_kill(module_data *m_data)
+{
+ (void)m_data;
+}
+
+static bool
+wasm_lib_module_handle_host_url(void *queue_msg)
+{
+ (void)queue_msg;
+ return false;
+}
+
+static module_data *
+wasm_lib_module_get_module_data(void *inst)
+{
+ (void)inst;
+ return NULL;
+}
+
+/* clang-format off */
+module_interface wasm_lib_module_interface = {
+ wasm_lib_module_init,
+ wasm_lib_module_install,
+ wasm_lib_module_uninstall,
+ wasm_lib_module_watchdog_kill,
+ wasm_lib_module_handle_host_url,
+ wasm_lib_module_get_module_data,
+ NULL
+};
+/* clang-format on */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.h
new file mode 100644
index 000000000..63ffd92b5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/module_wasm_lib.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _MODULE_WASM_LIB_H_
+#define _MODULE_WASM_LIB_H_
+
+#include "app_manager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern module_interface wasm_lib_module_interface;
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _MODULE_WASM_LIB_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/darwin/app_mgr_darwin.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/darwin/app_mgr_darwin.c
new file mode 100644
index 000000000..1c7409f55
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/darwin/app_mgr_darwin.c
@@ -0,0 +1 @@
+#include "../linux/app_mgr_linux.c"
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/linux/app_mgr_linux.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/linux/app_mgr_linux.c
new file mode 100644
index 000000000..5e51788bc
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/linux/app_mgr_linux.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "app_manager.h"
+
+void *
+app_manager_timer_create(void (*timer_callback)(void *),
+ watchdog_timer *wd_timer)
+{
+ /* TODO */
+ return NULL;
+}
+
+void
+app_manager_timer_destroy(void *timer)
+{
+ /* TODO */
+}
+
+void
+app_manager_timer_start(void *timer, int timeout)
+{
+ /* TODO */
+}
+
+void
+app_manager_timer_stop(void *timer)
+{
+ /* TODO */
+}
+
+watchdog_timer *
+app_manager_get_wd_timer_from_timer_handle(void *timer)
+{
+ /* TODO */
+ return NULL;
+}
+
+int
+app_manager_signature_verify(const uint8_t *file, unsigned int file_len,
+ const uint8_t *signature, unsigned int sig_size)
+{
+ return 1;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c
new file mode 100644
index 000000000..650e536f1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "app_manager.h"
+#include "bh_platform.h"
+#include <autoconf.h>
+#include <zephyr.h>
+#include <kernel.h>
+#if 0
+#include <sigverify.h>
+#endif
+typedef struct k_timer_watchdog {
+ struct k_timer timer;
+ watchdog_timer *wd_timer;
+} k_timer_watchdog;
+
+void *
+app_manager_timer_create(void (*timer_callback)(void *),
+ watchdog_timer *wd_timer)
+{
+ struct k_timer_watchdog *timer =
+ APP_MGR_MALLOC(sizeof(struct k_timer_watchdog));
+
+ if (timer) {
+ k_timer_init(&timer->timer, (void (*)(struct k_timer *))timer_callback,
+ NULL);
+ timer->wd_timer = wd_timer;
+ }
+
+ return timer;
+}
+
+void
+app_manager_timer_destroy(void *timer)
+{
+ APP_MGR_FREE(timer);
+}
+
+void
+app_manager_timer_start(void *timer, int timeout)
+{
+ k_timer_start(timer, Z_TIMEOUT_MS(timeout), Z_TIMEOUT_MS(0));
+}
+
+void
+app_manager_timer_stop(void *timer)
+{
+ k_timer_stop(timer);
+}
+
+watchdog_timer *
+app_manager_get_wd_timer_from_timer_handle(void *timer)
+{
+ return ((k_timer_watchdog *)timer)->wd_timer;
+}
+#if 0
+int app_manager_signature_verify(const uint8_t *file, unsigned int file_len,
+ const uint8_t *signature, unsigned int sig_size)
+{
+ return signature_verify(file, file_len, signature, sig_size);
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/resource_reg.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/resource_reg.c
new file mode 100644
index 000000000..4e930890e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/resource_reg.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "native_interface.h"
+#include "app_manager.h"
+#include "app_manager_export.h"
+#include "bi-inc/shared_utils.h"
+#include "bi-inc/attr_container.h"
+#include "coap_ext.h"
+
+typedef struct _app_res_register {
+ struct _app_res_register *next;
+ char *url;
+ void (*request_handler)(request_t *, void *);
+ uint32 register_id;
+} app_res_register_t;
+
+static app_res_register_t *g_resources = NULL;
+
+void
+module_request_handler(request_t *request, void *user_data)
+{
+ unsigned int mod_id = (unsigned int)(uintptr_t)user_data;
+ bh_message_t msg;
+ module_data *m_data;
+ request_t *req;
+
+ /* Check module name */
+ m_data = module_data_list_lookup_id(mod_id);
+ if (!m_data) {
+ return;
+ }
+
+ if (m_data->wd_timer.is_interrupting) {
+ return;
+ }
+
+ req = clone_request(request);
+ if (!req) {
+ return;
+ }
+
+ /* Set queue message and send to applet's queue */
+ msg = bh_new_msg(RESTFUL_REQUEST, req, sizeof(*req), request_cleaner);
+ if (!msg) {
+ request_cleaner(req);
+ return;
+ }
+
+ if (!bh_post_msg2(m_data->queue, msg)) {
+ return;
+ }
+
+ app_manager_printf("Send request to app %s success.\n",
+ m_data->module_name);
+}
+
+void
+targeted_app_request_handler(request_t *request, void *unused)
+{
+ char applet_name[128] = { 0 };
+ int offset;
+ char *url = request->url;
+ module_data *m_data;
+
+ offset = check_url_start(request->url, strlen(request->url), "/app/");
+
+ if (offset <= 0) {
+ return;
+ }
+
+ strncpy(applet_name, request->url + offset, sizeof(applet_name) - 1);
+ char *p = strchr(applet_name, '/');
+ if (p) {
+ *p = 0;
+ }
+ else
+ return;
+ app_manager_printf("Send request to applet: %s\n", applet_name);
+
+ request->url = p + 1;
+
+ /* Check module name */
+ m_data = module_data_list_lookup(applet_name);
+ if (!m_data) {
+ SEND_ERR_RESPONSE(request->mid,
+ "Send request to applet failed: invalid applet name");
+ goto end;
+ }
+
+ module_request_handler(request, (void *)(uintptr_t)m_data->id);
+end:
+ request->url = url;
+}
+
+void
+am_send_response(response_t *response)
+{
+ module_data *m_data;
+
+ // if the receiver is not any of modules, just forward it to the host
+ m_data = module_data_list_lookup_id(response->reciever);
+ if (!m_data) {
+ send_response_to_host(response);
+ }
+ else {
+ response_t *resp_for_send = clone_response(response);
+ if (!resp_for_send) {
+ return;
+ }
+
+ bh_message_t msg = bh_new_msg(RESTFUL_RESPONSE, resp_for_send,
+ sizeof(*resp_for_send), response_cleaner);
+ if (!msg) {
+ response_cleaner(resp_for_send);
+ return;
+ }
+
+ if (!bh_post_msg2(m_data->queue, msg)) {
+ return;
+ }
+ }
+}
+
+void *
+am_dispatch_request(request_t *request)
+{
+ app_res_register_t *r = g_resources;
+
+ while (r) {
+ if (check_url_start(request->url, strlen(request->url), r->url) > 0) {
+ r->request_handler(request, (void *)(uintptr_t)r->register_id);
+ return r;
+ }
+ r = r->next;
+ }
+ return NULL;
+}
+
+bool
+am_register_resource(const char *url,
+ void (*request_handler)(request_t *, void *),
+ uint32 register_id)
+{
+ app_res_register_t *r = g_resources;
+ int register_num = 0;
+
+ while (r) {
+ if (strcmp(r->url, url) == 0) {
+ return false;
+ }
+
+ if (r->register_id == register_id)
+ register_num++;
+
+ r = r->next;
+ }
+
+ if (strlen(url) > RESOUCE_EVENT_URL_LEN_MAX)
+ return false;
+
+ if (register_num >= RESOURCE_REGISTRATION_NUM_MAX)
+ return false;
+
+ r = (app_res_register_t *)APP_MGR_MALLOC(sizeof(app_res_register_t));
+ if (r == NULL)
+ return false;
+
+ memset(r, 0, sizeof(*r));
+ r->url = bh_strdup(url);
+ if (r->url == NULL) {
+ APP_MGR_FREE(r);
+ return false;
+ }
+
+ r->request_handler = request_handler;
+ r->next = g_resources;
+ r->register_id = register_id;
+ g_resources = r;
+
+ return true;
+}
+
+void
+am_cleanup_registeration(uint32 register_id)
+{
+ app_res_register_t *r = g_resources;
+ app_res_register_t *prev = NULL;
+
+ while (r) {
+ app_res_register_t *next = r->next;
+
+ if (register_id == r->register_id) {
+ if (prev)
+ prev->next = next;
+ else
+ g_resources = next;
+
+ APP_MGR_FREE(r->url);
+ APP_MGR_FREE(r);
+ }
+ else
+ /* if r is freed, should not change prev. Only set prev to r
+ when r isn't freed. */
+ prev = r;
+
+ r = next;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.c
new file mode 100644
index 000000000..ba5bb05f5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "watchdog.h"
+#include "bh_platform.h"
+
+#define WATCHDOG_THREAD_PRIORITY 5
+
+/* Queue of watchdog */
+static bh_queue *watchdog_queue;
+
+#ifdef WATCHDOG_ENABLED /* TODO */
+static void
+watchdog_timer_callback(void *timer)
+{
+ watchdog_timer *wd_timer =
+ app_manager_get_wd_timer_from_timer_handle(timer);
+
+ watchdog_timer_stop(wd_timer);
+
+ os_mutex_lock(&wd_timer->lock);
+
+ if (!wd_timer->is_stopped) {
+
+ wd_timer->is_interrupting = true;
+
+ bh_post_msg(watchdog_queue, WD_TIMEOUT, wd_timer->module_data,
+ sizeof(module_data));
+ }
+
+ os_mutex_unlock(&wd_timer->lock);
+}
+#endif
+
+bool
+watchdog_timer_init(module_data *m_data)
+{
+#ifdef WATCHDOG_ENABLED /* TODO */
+ watchdog_timer *wd_timer = &m_data->wd_timer;
+
+ if (0 != os_mutex_init(&wd_timer->lock))
+ return false;
+
+ if (!(wd_timer->timer_handle =
+ app_manager_timer_create(watchdog_timer_callback, wd_timer))) {
+ os_mutex_destroy(&wd_timer->lock);
+ return false;
+ }
+
+ wd_timer->module_data = m_data;
+ wd_timer->is_interrupting = false;
+ wd_timer->is_stopped = false;
+#endif
+ return true;
+}
+
+void
+watchdog_timer_destroy(watchdog_timer *wd_timer)
+{
+#ifdef WATCHDOG_ENABLED /* TODO */
+ app_manager_timer_destroy(wd_timer->timer_handle);
+ os_mutex_destroy(&wd_timer->lock);
+#endif
+}
+
+void
+watchdog_timer_start(watchdog_timer *wd_timer)
+{
+ os_mutex_lock(&wd_timer->lock);
+
+ wd_timer->is_interrupting = false;
+ wd_timer->is_stopped = false;
+ app_manager_timer_start(wd_timer->timer_handle,
+ wd_timer->module_data->timeout);
+
+ os_mutex_unlock(&wd_timer->lock);
+}
+
+void
+watchdog_timer_stop(watchdog_timer *wd_timer)
+{
+ app_manager_timer_stop(wd_timer->timer_handle);
+}
+
+#ifdef WATCHDOG_ENABLED /* TODO */
+static void
+watchdog_queue_callback(void *queue_msg)
+{
+ if (bh_message_type(queue_msg) == WD_TIMEOUT) {
+ module_data *m_data = (module_data *)bh_message_payload(queue_msg);
+ if (g_module_interfaces[m_data->module_type]
+ && g_module_interfaces[m_data->module_type]->module_watchdog_kill) {
+ g_module_interfaces[m_data->module_type]->module_watchdog_kill(
+ m_data);
+ app_manager_post_applets_update_event();
+ }
+ }
+}
+#endif
+
+#ifdef WATCHDOG_ENABLED /* TODO */
+static void *
+watchdog_thread_routine(void *arg)
+{
+ /* Enter loop run */
+ bh_queue_enter_loop_run(watchdog_queue, watchdog_queue_callback);
+
+ (void)arg;
+ return NULL;
+}
+#endif
+
+bool
+watchdog_startup()
+{
+ if (!(watchdog_queue = bh_queue_create())) {
+ app_manager_printf(
+ "App Manager start failed: create watchdog queue failed.\n");
+ return false;
+ }
+#if 0
+//todo: enable watchdog
+ /* Start watchdog thread */
+ if (!jeff_runtime_create_supervisor_thread_with_prio(watchdog_thread_routine, NULL,
+ WATCHDOG_THREAD_PRIORITY)) {
+ bh_queue_destroy(watchdog_queue);
+ return false;
+ }
+#endif
+ return true;
+}
+
+void
+watchdog_destroy()
+{
+ bh_queue_exit_loop_run(watchdog_queue);
+ bh_queue_destroy(watchdog_queue);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.h
new file mode 100644
index 000000000..d960df03b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-manager/watchdog.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WATCHDOG_H_
+#define _WATCHDOG_H_
+
+#include "app_manager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+watchdog_timer_init(module_data *module_data);
+
+void
+watchdog_timer_destroy(watchdog_timer *wd_timer);
+
+void
+watchdog_timer_start(watchdog_timer *wd_timer);
+
+void
+watchdog_timer_stop(watchdog_timer *wd_timer);
+
+watchdog_timer *
+app_manager_get_watchdog_timer(void *timer);
+
+bool
+watchdog_startup();
+
+void
+watchdog_destroy();
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _WATCHDOG_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_manager_export.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_manager_export.h
new file mode 100644
index 000000000..54b59b944
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_manager_export.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _APP_MANAGER_EXPORT_H_
+#define _APP_MANAGER_EXPORT_H_
+
+#include "native_interface.h"
+#include "bi-inc/shared_utils.h"
+#include "bh_queue.h"
+#include "host_link.h"
+#include "runtime_timer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Special module IDs */
+#define ID_HOST -3
+#define ID_APP_MGR -2
+/* Invalid module ID */
+#define ID_NONE ((uint32)-1)
+
+struct attr_container;
+
+/* Queue message type */
+typedef enum QUEUE_MSG_TYPE {
+ COAP_PARSED = LINK_MSG_TYPE_MAX + 1,
+ RESTFUL_REQUEST,
+ RESTFUL_RESPONSE,
+ TIMER_EVENT = 5,
+ SENSOR_EVENT = 6,
+ GPIO_INTERRUPT_EVENT = 7,
+ BLE_EVENT = 8,
+ JDWP_REQUEST = 9,
+ WD_TIMEOUT = 10,
+ BASE_EVENT_MAX = 100
+
+} QUEUE_MSG_TYPE;
+
+typedef enum {
+ Module_Jeff,
+ Module_WASM_App,
+ Module_WASM_Lib,
+ Module_Max
+} Module_Type;
+
+struct module_data;
+
+/* Watchdog timer of module */
+typedef struct watchdog_timer {
+ /* Timer handle of the platform */
+ void *timer_handle;
+ /* Module of the watchdog timer */
+ struct module_data *module_data;
+ /* Lock of the watchdog timer */
+ korp_mutex lock;
+ /* Flag indicates module is being interrupted by watchdog */
+ bool is_interrupting;
+ /* Flag indicates watchdog timer is stopped */
+ bool is_stopped;
+} watchdog_timer;
+
+typedef struct module_data {
+ struct module_data *next;
+
+ /* ID of the module */
+ uint32 id;
+
+ /* Type of the module */
+ Module_Type module_type;
+
+ /* Heap of the module */
+ void *heap;
+
+ /* Heap size of the module */
+ int heap_size;
+
+ /* Module execution timeout in millisecond */
+ int timeout;
+
+ /* Queue of the module */
+ bh_queue *queue;
+
+ /* Watchdog timer of the module*/
+ struct watchdog_timer wd_timer;
+
+ timer_ctx_t timer_ctx;
+
+ /* max timers number app can create */
+ int timers;
+
+ /* Internal data of the module */
+ void *internal_data;
+
+ /* Module name */
+ char module_name[1];
+} module_data;
+
+/* Module function types */
+typedef bool (*module_init_func)(void);
+typedef bool (*module_install_func)(request_t *msg);
+typedef bool (*module_uninstall_func)(request_t *msg);
+typedef void (*module_watchdog_kill_func)(module_data *module_data);
+typedef bool (*module_handle_host_url_func)(void *queue_msg);
+typedef module_data *(*module_get_module_data_func)(void *inst);
+
+/**
+ * @typedef module_on_install_request_byte_arrive_func
+ *
+ * @brief Define the signature of function to handle one byte of
+ * module app install request for struct module_interface.
+ *
+ * @param ch the byte to be received and handled
+ * @param total_size total size of the request
+ * @param received_total_size currently received total size when
+ * the function return
+ *
+ * @return true if success, false otherwise
+ */
+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 {
+ module_init_func module_init;
+ module_install_func module_install;
+ module_uninstall_func module_uninstall;
+ module_watchdog_kill_func module_watchdog_kill;
+ module_handle_host_url_func module_handle_host_url;
+ module_get_module_data_func module_get_module_data;
+ module_on_install_request_byte_arrive_func module_on_install;
+} module_interface;
+
+/**
+ * @typedef host_init_func
+ * @brief Define the host initialize callback function signature for
+ * struct host_interface.
+ *
+ * @return true if success, false if fail
+ */
+typedef bool (*host_init_func)(void);
+
+/**
+ * @typedef host_send_fun
+ * @brief Define the host send callback function signature for
+ * struct host_interface.
+ *
+ * @param buf data buffer to send.
+ * @param size size of the data to send.
+ *
+ * @return size of the data sent in bytes
+ */
+typedef int (*host_send_fun)(void *ctx, const char *buf, int size);
+
+/**
+ * @typedef host_destroy_fun
+ * @brief Define the host receive callback function signature for
+ * struct host_interface.
+ *
+ */
+typedef void (*host_destroy_fun)();
+
+/* Interfaces of host communication */
+typedef struct host_interface {
+ host_init_func init;
+ host_send_fun send;
+ host_destroy_fun destroy;
+} host_interface;
+
+/**
+ * Initialize communication with Host
+ *
+ * @param interface host communication interface
+ *
+ * @return true if success, false otherwise
+ */
+bool
+app_manager_host_init(host_interface *intf);
+
+/* Startup app manager */
+void
+app_manager_startup(host_interface *intf);
+
+/* Return whether app manager is started */
+bool
+app_manager_is_started(void);
+
+/* Get queue of current applet */
+void *
+app_manager_get_module_queue(uint32 module_type, void *module_inst);
+
+/* Get applet name of current applet */
+const char *
+app_manager_get_module_name(uint32 module_type, void *module_inst);
+
+/* Get heap of current applet */
+void *
+app_manager_get_module_heap(uint32 module_type, void *module_inst);
+
+void *
+get_app_manager_queue();
+
+module_data *
+app_manager_get_module_data(uint32 module_type, void *module_inst);
+
+unsigned int
+app_manager_get_module_id(uint32 module_type, void *module_inst);
+
+module_data *
+app_manager_lookup_module_data(const char *name);
+
+module_data *
+module_data_list_lookup(const char *module_name);
+
+module_data *
+module_data_list_lookup_id(unsigned int module_id);
+
+void
+app_manager_post_applets_update_event();
+
+bool
+am_register_resource(const char *url,
+ void (*request_handler)(request_t *, void *),
+ uint32 register_id);
+
+void
+am_cleanup_registeration(uint32 register_id);
+
+bool
+am_register_event(const char *url, uint32_t reg_client);
+
+bool
+am_unregister_event(const char *url, uint32_t reg_client);
+
+void
+am_publish_event(request_t *event);
+
+void *
+am_dispatch_request(request_t *request);
+
+void
+am_send_response(response_t *response);
+
+void
+module_request_handler(request_t *request, void *user_data);
+
+/**
+ * Send request message to host
+ *
+ * @param msg the request or event message.
+ * It is event when msg->action==COAP_EVENT
+ *
+ * @return true if success, false otherwise
+ */
+bool
+send_request_to_host(request_t *msg);
+
+/**
+ * Send response message to host
+ *
+ * @param msg the response message
+ *
+ * @return true if success, false otherwise
+ */
+bool
+send_response_to_host(response_t *msg);
+
+/**
+ * Send response with mid and code to host
+ *
+ * @param mid the message id of response
+ * @param code the code/status of response
+ * @param msg the detailed message
+ *
+ * @return true if success, false otherwise
+ */
+bool
+send_error_response_to_host(int mid, int code, const char *msg);
+
+/**
+ * Check whether the applet has the permission
+ *
+ * @param perm the permission needed to check
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_applet_check_permission(const char *perm);
+
+/**
+ * Send message to Host
+ *
+ * @param buf buffer to send
+ * @param size size of buffer
+ *
+ * @return size of buffer sent
+ */
+int
+app_manager_host_send_msg(int msg_type, const char *buf, int size);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake
new file mode 100644
index 000000000..f370e8b29
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake
@@ -0,0 +1,16 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (APP_MGR_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${APP_MGR_SHARED_DIR})
+
+
+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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/host_link.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/host_link.h
new file mode 100644
index 000000000..e3a37fb40
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/app-mgr-shared/host_link.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef DEPS_APP_MGR_APP_MGR_SHARED_HOST_LINK_H_
+#define DEPS_APP_MGR_APP_MGR_SHARED_HOST_LINK_H_
+
+typedef enum LINK_MSG_TYPE {
+ COAP_TCP_RAW = 0,
+ COAP_UDP_RAW = 1,
+ REQUEST_PACKET,
+ RESPONSE_PACKET,
+ INSTALL_WASM_APP,
+ CBOR_GENERIC = 30,
+
+ LINK_MSG_TYPE_MAX = 50
+} LINK_MSG_TYPE;
+
+/* Link message, or message between host and app manager */
+typedef struct bh_link_msg_t {
+ /* 2 bytes leading */
+ uint16_t leading_bytes;
+ /* message type, must be COAP_TCP or COAP_UDP */
+ uint16_t message_type;
+ /* size of payload */
+ uint32_t payload_size;
+ char *payload;
+} bh_link_msg_t;
+
+#endif /* DEPS_APP_MGR_APP_MGR_SHARED_HOST_LINK_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/module.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/module.json
new file mode 100644
index 000000000..b2faeca5f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-mgr/module.json
@@ -0,0 +1,52 @@
+{
+ "name": "aee",
+ "version": "0.0.1",
+ "description": "aee",
+ "type": "source",
+ "category": "middleware",
+ "arch": "x86, arc, posix",
+ "includes": [
+ "Beihai/classlib/include",
+ "Beihai/runtime/include",
+ "Beihai/runtime/platform/include",
+ "Beihai/runtime/platform/zephyr",
+ "Beihai/runtime/utils/coap/er-coap",
+ "Beihai/runtime/utils/coap/extension",
+ "iwasm/runtime/include",
+ "iwasm/runtime/platform/include",
+ "iwasm/runtime/platform/zephyr",
+ "iwasm/runtime/vmcore_wasm"
+ ],
+ "sources": [
+ "Beihai/classlib/native/internal/*.c",
+ "Beihai/classlib/native/*.c",
+ "Beihai/runtime/gc/*.c",
+ "Beihai/runtime/platform/zephyr/*.c",
+ "Beihai/runtime/utils/*.c",
+ "Beihai/runtime/utils/coap/er-coap/*.c",
+ "Beihai/runtime/utils/coap/extension/*.c",
+ "Beihai/runtime/vmcore_jeff/*.c",
+ "app-manager/app-manager.c",
+ "app-manager/app-manager-host.c",
+ "app-manager/app_mgr_zephyr.c",
+ "app-manager/event.c",
+ "app-manager/message.c",
+ "app-manager/module_jeff.c",
+ "app-manager/module_wasm_lib.c",
+ "app-manager/module_wasm_app.c",
+ "app-manager/watchdog.c",
+ "Beihai/products/iMRT/*.c",
+ "iwasm/runtime/utils/*.c",
+ "iwasm/runtime/platform/zephyr/*.c",
+ "iwasm/runtime/vmcore_wasm/*.c",
+ "iwasm/lib/lib-export\.c",
+ "iwasm/lib/aee/*.c",
+ "iwasm/products/zephyr/sample/src/*.c"
+ ],
+ "compile_definitions": [
+ "__JLF__",
+ "__ZEPHYR__"
+ ],
+ "target": "aee",
+ "dependencies": []
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/config.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/config.h
new file mode 100644
index 000000000..feedb13fa
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/config.h
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+/* clang-format off */
+#if !defined(BUILD_TARGET_X86_64) \
+ && !defined(BUILD_TARGET_AMD_64) \
+ && !defined(BUILD_TARGET_AARCH64) \
+ && !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) \
+ && !defined(BUILD_TARGET_RISCV64_LP64D) \
+ && !defined(BUILD_TARGET_RISCV64_LP64) \
+ && !defined(BUILD_TARGET_RISCV32_ILP32D) \
+ && !defined(BUILD_TARGET_RISCV32_ILP32) \
+ && !defined(BUILD_TARGET_ARC)
+/* clang-format on */
+#if defined(__x86_64__) || defined(__x86_64)
+#define BUILD_TARGET_X86_64
+#elif defined(__amd64__) || defined(__amd64)
+#define BUILD_TARGET_AMD_64
+#elif defined(__aarch64__)
+#define BUILD_TARGET_AARCH64
+#elif defined(__i386__) || defined(__i386) || defined(i386)
+#define BUILD_TARGET_X86_32
+#elif defined(__thumb__)
+#define BUILD_TARGET_THUMB
+#define BUILD_TARGET "THUMBV4T"
+#elif defined(__arm__)
+#define BUILD_TARGET_ARM
+#define BUILD_TARGET "ARMV4T"
+#elif defined(__mips__) || defined(__mips) || defined(mips)
+#define BUILD_TARGET_MIPS
+#elif defined(__XTENSA__)
+#define BUILD_TARGET_XTENSA
+#elif defined(__riscv) && (__riscv_xlen == 64)
+#define BUILD_TARGET_RISCV64_LP64D
+#elif defined(__riscv) && (__riscv_xlen == 32)
+#define BUILD_TARGET_RISCV32_ILP32D
+#elif defined(__arc__)
+#define BUILD_TARGET_ARC
+#else
+#error "Build target isn't set"
+#endif
+#endif
+
+#ifndef BH_DEBUG
+#define BH_DEBUG 0
+#endif
+
+#define MEM_ALLOCATOR_EMS 0
+#define MEM_ALLOCATOR_TLSF 1
+
+/* Default memory allocator */
+#define DEFAULT_MEM_ALLOCATOR MEM_ALLOCATOR_EMS
+
+#ifndef WASM_ENABLE_INTERP
+#define WASM_ENABLE_INTERP 0
+#endif
+
+#ifndef WASM_ENABLE_AOT
+#define WASM_ENABLE_AOT 0
+#endif
+
+#ifndef WASM_ENABLE_WORD_ALIGN_READ
+#define WASM_ENABLE_WORD_ALIGN_READ 0
+#endif
+
+#define AOT_MAGIC_NUMBER 0x746f6100
+#define AOT_CURRENT_VERSION 3
+
+#ifndef WASM_ENABLE_JIT
+#define WASM_ENABLE_JIT 0
+#endif
+
+#ifndef WASM_ENABLE_LAZY_JIT
+#define WASM_ENABLE_LAZY_JIT 0
+#endif
+
+#ifndef WASM_ORC_JIT_BACKEND_THREAD_NUM
+/* The number of backend threads created by runtime */
+#define WASM_ORC_JIT_BACKEND_THREAD_NUM 4
+#endif
+
+#if WASM_ORC_JIT_BACKEND_THREAD_NUM < 1
+#error "WASM_ORC_JIT_BACKEND_THREAD_NUM must be greater than 0"
+#endif
+
+#ifndef WASM_ORC_JIT_COMPILE_THREAD_NUM
+/* The number of compilation threads created by LLVM JIT */
+#define WASM_ORC_JIT_COMPILE_THREAD_NUM 4
+#endif
+
+#if WASM_ORC_JIT_COMPILE_THREAD_NUM < 1
+#error "WASM_ORC_JIT_COMPILE_THREAD_NUM must be greater than 0"
+#endif
+
+#if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0)
+/* LLVM JIT can only be enabled when AOT is enabled */
+#undef WASM_ENABLE_JIT
+#define WASM_ENABLE_JIT 0
+
+#undef WASM_ENABLE_LAZY_JIT
+#define WASM_ENABLE_LAZY_JIT 0
+#endif
+
+#ifndef WASM_ENABLE_FAST_JIT
+#define WASM_ENABLE_FAST_JIT 0
+#endif
+
+#ifndef WASM_ENABLE_FAST_JIT_DUMP
+#define WASM_ENABLE_FAST_JIT_DUMP 0
+#endif
+
+#ifndef FAST_JIT_DEFAULT_CODE_CACHE_SIZE
+#define FAST_JIT_DEFAULT_CODE_CACHE_SIZE 10 * 1024 * 1024
+#endif
+
+#ifndef WASM_ENABLE_WAMR_COMPILER
+#define WASM_ENABLE_WAMR_COMPILER 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_UVWASI
+#define WASM_ENABLE_UVWASI 0
+#endif
+
+#ifndef WASM_ENABLE_WASI_NN
+#define WASM_ENABLE_WASI_NN 0
+#endif
+
+/* Default disable libc emcc */
+#ifndef WASM_ENABLE_LIBC_EMCC
+#define WASM_ENABLE_LIBC_EMCC 0
+#endif
+
+#ifndef WASM_ENABLE_LIB_RATS
+#define WASM_ENABLE_LIB_RATS 0
+#endif
+
+#ifndef WASM_ENABLE_LIB_PTHREAD
+#define WASM_ENABLE_LIB_PTHREAD 0
+#endif
+
+#ifndef WASM_ENABLE_LIB_PTHREAD_SEMAPHORE
+#define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0
+#endif
+
+#ifndef WASM_ENABLE_LIB_WASI_THREADS
+#define WASM_ENABLE_LIB_WASI_THREADS 0
+#endif
+
+#ifndef WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION
+#define WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION WASM_ENABLE_LIB_WASI_THREADS
+#elif WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0 \
+ && WASM_ENABLE_LIB_WASI_THREADS == 1
+#error "Heap aux stack allocation must be enabled for WASI threads"
+#endif
+
+#ifndef WASM_ENABLE_BASE_LIB
+#define WASM_ENABLE_BASE_LIB 0
+#endif
+
+#ifndef WASM_ENABLE_APP_FRAMEWORK
+#define WASM_ENABLE_APP_FRAMEWORK 0
+#endif
+
+/* Bulk memory operation */
+#ifndef WASM_ENABLE_BULK_MEMORY
+#define WASM_ENABLE_BULK_MEMORY 0
+#endif
+
+/* Shared memory */
+#ifndef WASM_ENABLE_SHARED_MEMORY
+#define WASM_ENABLE_SHARED_MEMORY 0
+#endif
+
+/* Thread manager */
+#ifndef WASM_ENABLE_THREAD_MGR
+#define WASM_ENABLE_THREAD_MGR 0
+#endif
+
+/* Source debugging */
+#ifndef WASM_ENABLE_DEBUG_INTERP
+#define WASM_ENABLE_DEBUG_INTERP 0
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#ifndef DEBUG_EXECUTION_MEMORY_SIZE
+/* 0x85000 is the size required by lldb, if this is changed to a smaller value,
+ * then the debugger will not be able to evaluate user expressions, other
+ * functionality such as breakpoint and stepping are not influenced by this */
+#define DEBUG_EXECUTION_MEMORY_SIZE 0x85000
+#endif
+#endif /* end of WASM_ENABLE_DEBUG_INTERP != 0 */
+
+#ifndef WASM_ENABLE_DEBUG_AOT
+#define WASM_ENABLE_DEBUG_AOT 0
+#endif
+
+/* Custom sections */
+#ifndef WASM_ENABLE_LOAD_CUSTOM_SECTION
+#define WASM_ENABLE_LOAD_CUSTOM_SECTION 0
+#endif
+
+/* WASM log system */
+#ifndef WASM_ENABLE_LOG
+#define WASM_ENABLE_LOG 1
+#endif
+
+#ifndef WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS
+#if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_X86_64) \
+ || defined(BUILD_TARGET_AARCH64)
+#define WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS 1
+#else
+#define WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS 0
+#endif
+#endif
+
+/* WASM Interpreter labels-as-values feature */
+#ifndef WASM_ENABLE_LABELS_AS_VALUES
+#ifdef __GNUC__
+#define WASM_ENABLE_LABELS_AS_VALUES 1
+#else
+#define WASM_ENABLE_LABELS_AS_VALUES 0
+#endif
+#endif
+
+/* Enable fast interpreter or not */
+#ifndef WASM_ENABLE_FAST_INTERP
+#define WASM_ENABLE_FAST_INTERP 0
+#endif
+
+#if WASM_ENABLE_FAST_INTERP != 0
+#define WASM_DEBUG_PREPROCESSOR 0
+#endif
+
+/* Enable opcode counter or not */
+#ifndef WASM_ENABLE_OPCODE_COUNTER
+#define WASM_ENABLE_OPCODE_COUNTER 0
+#endif
+
+/* Support a module with dependency, other modules */
+#ifndef WASM_ENABLE_MULTI_MODULE
+#define WASM_ENABLE_MULTI_MODULE 0
+#endif
+
+/* Enable wasm mini loader or not */
+#ifndef WASM_ENABLE_MINI_LOADER
+#define WASM_ENABLE_MINI_LOADER 0
+#endif
+
+/* Disable boundary check with hardware trap or not,
+ * enable it by default if it is supported */
+#ifndef WASM_DISABLE_HW_BOUND_CHECK
+#define WASM_DISABLE_HW_BOUND_CHECK 0
+#endif
+
+/* Disable native stack access boundary check with hardware
+ * trap or not, enable it by default if it is supported */
+#ifndef WASM_DISABLE_STACK_HW_BOUND_CHECK
+#define WASM_DISABLE_STACK_HW_BOUND_CHECK 0
+#endif
+
+/* Disable SIMD unless it is manualy enabled somewhere */
+#ifndef WASM_ENABLE_SIMD
+#define WASM_ENABLE_SIMD 0
+#endif
+
+/* Memory profiling */
+#ifndef WASM_ENABLE_MEMORY_PROFILING
+#define WASM_ENABLE_MEMORY_PROFILING 0
+#endif
+
+/* Memory tracing */
+#ifndef WASM_ENABLE_MEMORY_TRACING
+#define WASM_ENABLE_MEMORY_TRACING 0
+#endif
+
+/* Performance profiling */
+#ifndef WASM_ENABLE_PERF_PROFILING
+#define WASM_ENABLE_PERF_PROFILING 0
+#endif
+
+/* Dump call stack */
+#ifndef WASM_ENABLE_DUMP_CALL_STACK
+#define WASM_ENABLE_DUMP_CALL_STACK 0
+#endif
+
+/* Heap verification */
+#ifndef BH_ENABLE_GC_VERIFY
+#define BH_ENABLE_GC_VERIFY 0
+#endif
+
+/* Enable global heap pool if heap verification is enabled */
+#if BH_ENABLE_GC_VERIFY != 0
+#define WASM_ENABLE_GLOBAL_HEAP_POOL 1
+#endif
+
+/* Global heap pool */
+#ifndef WASM_ENABLE_GLOBAL_HEAP_POOL
+#define WASM_ENABLE_GLOBAL_HEAP_POOL 0
+#endif
+
+#ifndef WASM_ENABLE_SPEC_TEST
+#define WASM_ENABLE_SPEC_TEST 0
+#endif
+
+/* Global heap pool size in bytes */
+#ifndef WASM_GLOBAL_HEAP_SIZE
+#define WASM_GLOBAL_HEAP_SIZE (10 * 1024 * 1024)
+#endif
+
+/* Max app number of all modules */
+#define MAX_APP_INSTALLATIONS 3
+
+/* Default timer number in one app */
+#define DEFAULT_TIMERS_PER_APP 20
+
+/* Max timer number in one app */
+#define MAX_TIMERS_PER_APP 30
+
+/* Max connection number in one app */
+#define MAX_CONNECTION_PER_APP 20
+
+/* Max resource registration number in one app */
+#define RESOURCE_REGISTRATION_NUM_MAX 16
+
+/* Max length of resource/event url */
+#define RESOUCE_EVENT_URL_LEN_MAX 256
+
+/* Default length of queue */
+#define DEFAULT_QUEUE_LENGTH 50
+
+/* Default watchdog interval in ms */
+#define DEFAULT_WATCHDOG_INTERVAL (3 * 60 * 1000)
+
+/* The max percentage of global heap that app memory space can grow */
+#define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3
+
+/* Default min/max heap size of each app */
+#ifndef APP_HEAP_SIZE_DEFAULT
+#define APP_HEAP_SIZE_DEFAULT (8 * 1024)
+#endif
+#define APP_HEAP_SIZE_MIN (256)
+#define APP_HEAP_SIZE_MAX (512 * 1024 * 1024)
+
+/* Default wasm stack size of each app */
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+#define DEFAULT_WASM_STACK_SIZE (16 * 1024)
+#else
+#define DEFAULT_WASM_STACK_SIZE (12 * 1024)
+#endif
+/* Min auxilliary stack size of each wasm thread */
+#define WASM_THREAD_AUX_STACK_SIZE_MIN (256)
+
+/* Default/min native stack size of each app thread */
+#if !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \
+ && defined(APP_THREAD_STACK_SIZE_MIN))
+#if defined(BH_PLATFORM_ZEPHYR) || defined(BH_PLATFORM_ALIOS_THINGS) \
+ || defined(BH_PLATFORM_ESP_IDF) || defined(BH_PLATFORM_OPENRTOS)
+#define APP_THREAD_STACK_SIZE_DEFAULT (6 * 1024)
+#define APP_THREAD_STACK_SIZE_MIN (4 * 1024)
+#elif defined(PTHREAD_STACK_DEFAULT) && defined(PTHREAD_STACK_MIN)
+#define APP_THREAD_STACK_SIZE_DEFAULT PTHREAD_STACK_DEFAULT
+#define APP_THREAD_STACK_SIZE_MIN PTHREAD_STACK_MIN
+#elif WASM_ENABLE_UVWASI != 0
+/* UVWASI requires larger native stack */
+#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024)
+#define APP_THREAD_STACK_SIZE_MIN (48 * 1024)
+#else
+#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024)
+#define APP_THREAD_STACK_SIZE_MIN (24 * 1024)
+#endif
+#endif /* end of !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \
+ && defined(APP_THREAD_STACK_SIZE_MIN)) */
+
+/* Max native stack size of each app thread */
+#if !defined(APP_THREAD_STACK_SIZE_MAX)
+#define APP_THREAD_STACK_SIZE_MAX (8 * 1024 * 1024)
+#endif
+
+/* Reserved bytes to the native thread stack boundary, throw native
+ stack overflow exception if the guard boudary is reached */
+#ifndef WASM_STACK_GUARD_SIZE
+#if WASM_ENABLE_UVWASI != 0
+/* UVWASI requires larger native stack */
+#define WASM_STACK_GUARD_SIZE (4096 * 6)
+#else
+#define WASM_STACK_GUARD_SIZE (1024)
+#endif
+#endif
+
+/* Guard page count for stack overflow check with hardware trap */
+#ifndef STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT
+#define STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT 3
+#endif
+
+/* Default wasm block address cache size and conflict list size */
+#ifndef BLOCK_ADDR_CACHE_SIZE
+#define BLOCK_ADDR_CACHE_SIZE 64
+#endif
+#define BLOCK_ADDR_CONFLICT_SIZE 2
+
+/* Default max thread num per cluster. Can be overwrite by
+ wasm_runtime_set_max_thread_num */
+#define CLUSTER_MAX_THREAD_NUM 4
+
+#ifndef WASM_ENABLE_TAIL_CALL
+#define WASM_ENABLE_TAIL_CALL 0
+#endif
+
+#ifndef WASM_ENABLE_CUSTOM_NAME_SECTION
+#define WASM_ENABLE_CUSTOM_NAME_SECTION 0
+#endif
+
+#ifndef WASM_ENABLE_REF_TYPES
+#define WASM_ENABLE_REF_TYPES 0
+#endif
+
+#ifndef WASM_ENABLE_SGX_IPFS
+#define WASM_ENABLE_SGX_IPFS 0
+#endif
+
+#ifndef WASM_MEM_ALLOC_WITH_USER_DATA
+#define WASM_MEM_ALLOC_WITH_USER_DATA 0
+#endif
+
+#ifndef WASM_ENABLE_WASM_CACHE
+#define WASM_ENABLE_WASM_CACHE 0
+#endif
+
+#endif /* end of _CONFIG_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/README.md
new file mode 100644
index 000000000..65ab78a49
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/README.md
@@ -0,0 +1,14 @@
+# vmcore architecture
+- [WAMR memory model overview](https://bytecodealliance.github.io/wamr.dev/blog/the-wamr-memory-model/)
+
+## Wasm function
+- [Wasm function architecture](./doc/wasm_function.MD)
+
+## Exports
+- [Wasm export architecture](./doc/wasm_exports.MD)
+
+## globals
+- [Wasm globals architecture](./doc/wasm_globals.MD)
+
+## classic interpreter
+- [classic interpreter](./doc/classic_interpreter.MD) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/SConscript
new file mode 100644
index 000000000..790f28404
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/SConscript
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import re
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+
+src = Split('''
+aot_loader.c
+aot_runtime.c
+aot_intrinsic.c
+''')
+
+if rtconfig.ARCH == 'arm':
+ if re.match('^cortex-m.*', rtconfig.CPU):
+ src += ['arch/aot_reloc_thumb.c']
+ elif re.match('^cortex-a.*', rtconfig.CPU):
+ src += ['arch/aot_reloc_arm.c']
+elif rtconfig.ARCH == 'ia32':
+ src += ['arch/aot_reloc_x86_32.c']
+
+CPPPATH = [cwd, cwd + '/../include']
+
+CPPDEFINES = ['WASM_ENABLE_AOT=1']
+
+group = DefineGroup('iwasm_aot', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.c
new file mode 100644
index 000000000..319eeda5c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.c
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_intrinsic.h"
+
+typedef struct {
+ const char *llvm_intrinsic;
+ const char *native_intrinsic;
+ uint64 flag;
+} aot_intrinsic;
+
+/* clang-format off */
+static const aot_intrinsic g_intrinsic_mapping[] = {
+ { "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD },
+ { "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD },
+ { "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB },
+ { "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB },
+ { "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL },
+ { "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL },
+ { "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV },
+ { "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV },
+ { "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS },
+ { "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS },
+ { "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL },
+ { "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL },
+ { "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR },
+ { "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR },
+ { "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC },
+ { "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC },
+ { "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT },
+ { "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT },
+ { "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT },
+ { "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT },
+ { "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN },
+ { "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN },
+ { "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN },
+ { "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN },
+ { "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX },
+ { "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX },
+ { "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ },
+ { "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ },
+ { "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ },
+ { "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ },
+ { "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT },
+ { "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT },
+ { "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
+ { "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 },
+ { "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 },
+ { "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 },
+ { "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
+ { "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 },
+ { "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 },
+ { "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 },
+ { "i32_trunc_f32_u", "aot_intrinsic_f32_to_u32", AOT_INTRINSIC_FLAG_F32_TO_U32 },
+ { "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 },
+ { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 },
+ { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 },
+ { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 },
+ { "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 },
+ { "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 },
+ { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 },
+ { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 },
+ { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 },
+ { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP },
+ { "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP },
+ { "i32.const", NULL, AOT_INTRINSIC_FLAG_I32_CONST },
+ { "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST },
+ { "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST },
+ { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST },
+ { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S},
+ { "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S},
+ { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U},
+ { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S},
+ { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U},
+ { "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U},
+ { "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S},
+ { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U},
+ { "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR},
+ { "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND},
+};
+/* clang-format on */
+
+static const uint32 g_intrinsic_count =
+ sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic);
+
+float32
+aot_intrinsic_fadd_f32(float32 a, float32 b)
+{
+ return a + b;
+}
+
+float64
+aot_intrinsic_fadd_f64(float64 a, float64 b)
+{
+ return a + b;
+}
+
+float32
+aot_intrinsic_fsub_f32(float32 a, float32 b)
+{
+ return a - b;
+}
+
+float64
+aot_intrinsic_fsub_f64(float64 a, float64 b)
+{
+ return a - b;
+}
+
+float32
+aot_intrinsic_fmul_f32(float32 a, float32 b)
+{
+ return a * b;
+}
+
+float64
+aot_intrinsic_fmul_f64(float64 a, float64 b)
+{
+ return a * b;
+}
+
+float32
+aot_intrinsic_fdiv_f32(float32 a, float32 b)
+{
+ return a / b;
+}
+
+float64
+aot_intrinsic_fdiv_f64(float64 a, float64 b)
+{
+ return a / b;
+}
+
+float32
+aot_intrinsic_fabs_f32(float32 a)
+{
+ return fabsf(a);
+}
+
+float64
+aot_intrinsic_fabs_f64(float64 a)
+{
+ return fabs(a);
+}
+
+float32
+aot_intrinsic_ceil_f32(float32 a)
+{
+ return ceilf(a);
+}
+
+float64
+aot_intrinsic_ceil_f64(float64 a)
+{
+ return ceil(a);
+}
+
+float32
+aot_intrinsic_floor_f32(float32 a)
+{
+ return floorf(a);
+}
+
+float64
+aot_intrinsic_floor_f64(float64 a)
+{
+ return floor(a);
+}
+
+float32
+aot_intrinsic_trunc_f32(float32 a)
+{
+ return truncf(a);
+}
+
+float64
+aot_intrinsic_trunc_f64(float64 a)
+{
+ return trunc(a);
+}
+
+float32
+aot_intrinsic_rint_f32(float32 a)
+{
+ return rintf(a);
+}
+
+float64
+aot_intrinsic_rint_f64(float64 a)
+{
+ return rint(a);
+}
+
+float32
+aot_intrinsic_sqrt_f32(float32 a)
+{
+ return sqrtf(a);
+}
+
+float64
+aot_intrinsic_sqrt_f64(float64 a)
+{
+ return sqrt(a);
+}
+
+float32
+aot_intrinsic_copysign_f32(float32 a, float32 b)
+{
+ return signbit(b) ? -fabsf(a) : fabsf(a);
+}
+
+float64
+aot_intrinsic_copysign_f64(float64 a, float64 b)
+{
+ return signbit(b) ? -fabs(a) : fabs(a);
+}
+
+float32
+aot_intrinsic_fmin_f32(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+float64
+aot_intrinsic_fmin_f64(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+float32
+aot_intrinsic_fmax_f32(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+float64
+aot_intrinsic_fmax_f64(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+uint32
+aot_intrinsic_clz_i32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 0x80000000)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+uint32
+aot_intrinsic_clz_i64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 0x8000000000000000LL)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+uint32
+aot_intrinsic_ctz_i32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+uint32
+aot_intrinsic_ctz_i64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+uint32
+aot_intrinsic_popcnt_i32(uint32 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+uint32
+aot_intrinsic_popcnt_i64(uint64 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+float32
+aot_intrinsic_i32_to_f32(int32 i)
+{
+ return (float32)i;
+}
+
+float32
+aot_intrinsic_u32_to_f32(uint32 u)
+{
+ return (float32)u;
+}
+
+float64
+aot_intrinsic_i32_to_f64(int32 i)
+{
+ return (float64)i;
+}
+
+float64
+aot_intrinsic_u32_to_f64(uint32 u)
+{
+ return (float64)u;
+}
+
+float32
+aot_intrinsic_i64_to_f32(int64 i)
+{
+ return (float32)i;
+}
+
+float32
+aot_intrinsic_u64_to_f32(uint64 u)
+{
+ return (float32)u;
+}
+
+float64
+aot_intrinsic_i64_to_f64(int64 i)
+{
+ return (float64)i;
+}
+
+float64
+aot_intrinsic_u64_to_f64(uint64 u)
+{
+ return (float64)u;
+}
+
+int32
+aot_intrinsic_f32_to_i32(float32 f)
+{
+ return (int32)f;
+}
+
+uint32
+aot_intrinsic_f32_to_u32(float32 f)
+{
+ return (uint32)f;
+}
+
+int64
+aot_intrinsic_f32_to_i64(float32 f)
+{
+ return (int64)f;
+}
+
+uint64
+aot_intrinsic_f32_to_u64(float32 f)
+{
+ return (uint64)f;
+}
+
+int32
+aot_intrinsic_f64_to_i32(float64 f)
+{
+ return (int32)f;
+}
+
+uint32
+aot_intrinsic_f64_to_u32(float64 f)
+{
+ return (uint32)f;
+}
+
+int64
+aot_intrinsic_f64_to_i64(float64 f)
+{
+ return (int64)f;
+}
+
+uint64
+aot_intrinsic_f64_to_u64(float64 f)
+{
+ return (uint64)f;
+}
+
+float64
+aot_intrinsic_f32_to_f64(float32 f)
+{
+ return (float64)f;
+}
+
+float32
+aot_intrinsic_f64_to_f32(float64 f)
+{
+ return (float32)f;
+}
+
+int32
+aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs)
+{
+ switch (cond) {
+ case FLOAT_EQ:
+ return lhs == rhs ? 1 : 0;
+
+ case FLOAT_LT:
+ return lhs < rhs ? 1 : 0;
+
+ case FLOAT_GT:
+ return lhs > rhs ? 1 : 0;
+
+ case FLOAT_LE:
+ return lhs <= rhs ? 1 : 0;
+
+ case FLOAT_GE:
+ return lhs >= rhs ? 1 : 0;
+
+ case FLOAT_NE:
+ return (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
+
+ case FLOAT_UNO:
+ return (isnan(lhs) || isnan(rhs)) ? 1 : 0;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+int32
+aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs)
+{
+ switch (cond) {
+ case FLOAT_EQ:
+ return lhs == rhs ? 1 : 0;
+
+ case FLOAT_LT:
+ return lhs < rhs ? 1 : 0;
+
+ case FLOAT_GT:
+ return lhs > rhs ? 1 : 0;
+
+ case FLOAT_LE:
+ return lhs <= rhs ? 1 : 0;
+
+ case FLOAT_GE:
+ return lhs >= rhs ? 1 : 0;
+
+ case FLOAT_NE:
+ return (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
+
+ case FLOAT_UNO:
+ return (isnan(lhs) || isnan(rhs)) ? 1 : 0;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+int64
+aot_intrinsic_i64_div_s(int64 l, int64 r)
+{
+ return l / r;
+}
+
+int32
+aot_intrinsic_i32_div_s(int32 l, int32 r)
+{
+ return l / r;
+}
+
+uint32
+aot_intrinsic_i32_div_u(uint32 l, uint32 r)
+{
+ return l / r;
+}
+
+int32
+aot_intrinsic_i32_rem_s(int32 l, int32 r)
+{
+ return l % r;
+}
+
+uint32
+aot_intrinsic_i32_rem_u(uint32 l, uint32 r)
+{
+ return l % r;
+}
+
+uint64
+aot_intrinsic_i64_div_u(uint64 l, uint64 r)
+{
+ return l / r;
+}
+
+int64
+aot_intrinsic_i64_rem_s(int64 l, int64 r)
+{
+ return l % r;
+}
+
+uint64
+aot_intrinsic_i64_rem_u(uint64 l, uint64 r)
+{
+ return l % r;
+}
+
+uint64
+aot_intrinsic_i64_bit_or(uint64 l, uint64 r)
+{
+ return l | r;
+}
+
+uint64
+aot_intrinsic_i64_bit_and(uint64 l, uint64 r)
+{
+ return l & r;
+}
+
+const char *
+aot_intrinsic_get_symbol(const char *llvm_intrinsic)
+{
+ uint32 cnt;
+ for (cnt = 0; cnt < g_intrinsic_count; cnt++) {
+ if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) {
+ return g_intrinsic_mapping[cnt].native_intrinsic;
+ }
+ }
+ return NULL;
+}
+
+#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
+
+static void
+add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag)
+{
+ uint64 group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
+ if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) {
+ comp_ctx->flags[group] |= flag;
+ }
+ else {
+ bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__,
+ "intrinsic exceeds max limit.");
+ }
+}
+
+static void
+add_i64_common_intrinsics(AOTCompContext *comp_ctx)
+{
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_DIV_S);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_DIV_U);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_S);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_U);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_OR);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_AND);
+}
+
+static void
+add_i32_common_intrinsics(AOTCompContext *comp_ctx)
+{
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_S);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_U);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_S);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_U);
+}
+
+static void
+add_f32_common_intrinsics(AOTCompContext *comp_ctx)
+{
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FABS);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FADD);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FSUB);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FMUL);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FDIV);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_SQRT);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CMP);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_MIN);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_MAX);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CEIL);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FLOOR);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TRUNC);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_RINT);
+}
+
+static void
+add_f64_common_intrinsics(AOTCompContext *comp_ctx)
+{
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FABS);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FADD);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FSUB);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FMUL);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_MIN);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_MAX);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CEIL);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FLOOR);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TRUNC);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_RINT);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FDIV);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_SQRT);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP);
+}
+
+static void
+add_common_float_integer_convertion(AOTCompContext *comp_ctx)
+{
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64);
+
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64);
+
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64);
+
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64);
+
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_F32);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_F64);
+}
+
+bool
+aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
+ const char *llvm_intrinsic)
+{
+ uint32 cnt;
+ uint64 flag;
+ uint64 group;
+
+ for (cnt = 0; cnt < g_intrinsic_count; cnt++) {
+ if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) {
+ flag = g_intrinsic_mapping[cnt].flag;
+ group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
+ flag &= AOT_INTRINSIC_FLAG_MASK;
+ if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) {
+ if (comp_ctx->flags[group] & flag) {
+ return true;
+ }
+ }
+ else {
+ bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__,
+ "intrinsic exceeds max limit.");
+ }
+ }
+ }
+ return false;
+}
+
+void
+aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
+{
+ memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags));
+
+ if (!comp_ctx->target_cpu)
+ return;
+
+ if (!strncmp(comp_ctx->target_arch, "thumb", 5)) {
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
+ add_i32_common_intrinsics(comp_ctx);
+ if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) {
+ }
+ else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) {
+ add_f64_common_intrinsics(comp_ctx);
+ }
+ else {
+ add_f32_common_intrinsics(comp_ctx);
+ add_f64_common_intrinsics(comp_ctx);
+ add_i64_common_intrinsics(comp_ctx);
+ add_common_float_integer_convertion(comp_ctx);
+ }
+ }
+ else if (!strncmp(comp_ctx->target_arch, "riscv", 5)) {
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
+ /*
+ * Note: Use builtin intrinsics since hardware float operation
+ * will cause rodata relocation
+ */
+ add_f32_common_intrinsics(comp_ctx);
+ add_f64_common_intrinsics(comp_ctx);
+ add_common_float_integer_convertion(comp_ctx);
+ if (!strncmp(comp_ctx->target_arch, "riscv32", 7)) {
+ add_i64_common_intrinsics(comp_ctx);
+ }
+ }
+ else if (!strncmp(comp_ctx->target_arch, "xtensa", 6)) {
+ /*
+ * Note: Use builtin intrinsics since hardware float operation
+ * will cause rodata relocation
+ */
+ add_f32_common_intrinsics(comp_ctx);
+ add_i32_common_intrinsics(comp_ctx);
+ add_f64_common_intrinsics(comp_ctx);
+ add_i64_common_intrinsics(comp_ctx);
+ add_common_float_integer_convertion(comp_ctx);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_CONST);
+ }
+ else {
+ /*
+ * Use constant value table by default
+ */
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST);
+ add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST);
+ }
+}
+
+#endif /* WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.h
new file mode 100644
index 000000000..2123058b9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_intrinsic.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_INTRINSIC_H
+#define _AOT_INTRINSIC_H
+
+#include "aot_runtime.h"
+#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
+#include "aot_llvm.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AOT_INTRINSIC_GROUPS 2
+
+/* Use uint64 as flag container:
+ * - The upper 16 bits are the intrinsic group number
+ * - The lower 48 bits are the intrinsic capability mask
+ */
+
+#define AOT_INTRINSIC_FLAG(group, number) \
+ ((((uint64)(group & 0xffffLL)) << 48) | ((uint64)1 << number))
+
+#define AOT_INTRINSIC_FLAG_MASK (0x0000ffffffffffffLL)
+
+#define AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag) \
+ ((((uint64)flag) >> 48) & 0xffffLL)
+
+/* clang-format off */
+#define AOT_INTRINSIC_FLAG_F32_FADD AOT_INTRINSIC_FLAG(0, 0)
+#define AOT_INTRINSIC_FLAG_F32_FSUB AOT_INTRINSIC_FLAG(0, 1)
+#define AOT_INTRINSIC_FLAG_F32_FMUL AOT_INTRINSIC_FLAG(0, 2)
+#define AOT_INTRINSIC_FLAG_F32_FDIV AOT_INTRINSIC_FLAG(0, 3)
+#define AOT_INTRINSIC_FLAG_F32_FABS AOT_INTRINSIC_FLAG(0, 4)
+#define AOT_INTRINSIC_FLAG_F32_CEIL AOT_INTRINSIC_FLAG(0, 5)
+#define AOT_INTRINSIC_FLAG_F32_FLOOR AOT_INTRINSIC_FLAG(0, 6)
+#define AOT_INTRINSIC_FLAG_F32_TRUNC AOT_INTRINSIC_FLAG(0, 7)
+#define AOT_INTRINSIC_FLAG_F32_RINT AOT_INTRINSIC_FLAG(0, 8)
+#define AOT_INTRINSIC_FLAG_F32_SQRT AOT_INTRINSIC_FLAG(0, 9)
+#define AOT_INTRINSIC_FLAG_F32_COPYSIGN AOT_INTRINSIC_FLAG(0, 10)
+#define AOT_INTRINSIC_FLAG_F32_MIN AOT_INTRINSIC_FLAG(0, 11)
+#define AOT_INTRINSIC_FLAG_F32_MAX AOT_INTRINSIC_FLAG(0, 12)
+#define AOT_INTRINSIC_FLAG_I32_CLZ AOT_INTRINSIC_FLAG(0, 13)
+#define AOT_INTRINSIC_FLAG_I32_CTZ AOT_INTRINSIC_FLAG(0, 14)
+#define AOT_INTRINSIC_FLAG_I32_POPCNT AOT_INTRINSIC_FLAG(0, 15)
+#define AOT_INTRINSIC_FLAG_I32_TO_F32 AOT_INTRINSIC_FLAG(0, 16)
+#define AOT_INTRINSIC_FLAG_U32_TO_F32 AOT_INTRINSIC_FLAG(0, 17)
+#define AOT_INTRINSIC_FLAG_I32_TO_F64 AOT_INTRINSIC_FLAG(0, 18)
+#define AOT_INTRINSIC_FLAG_U32_TO_F64 AOT_INTRINSIC_FLAG(0, 19)
+#define AOT_INTRINSIC_FLAG_F32_TO_I32 AOT_INTRINSIC_FLAG(0, 20)
+#define AOT_INTRINSIC_FLAG_F32_TO_U32 AOT_INTRINSIC_FLAG(0, 21)
+#define AOT_INTRINSIC_FLAG_F32_TO_I64 AOT_INTRINSIC_FLAG(0, 22)
+#define AOT_INTRINSIC_FLAG_F32_TO_U64 AOT_INTRINSIC_FLAG(0, 23)
+#define AOT_INTRINSIC_FLAG_F32_TO_F64 AOT_INTRINSIC_FLAG(0, 24)
+#define AOT_INTRINSIC_FLAG_F32_CMP AOT_INTRINSIC_FLAG(0, 25)
+#define AOT_INTRINSIC_FLAG_F32_CONST AOT_INTRINSIC_FLAG(0, 26)
+#define AOT_INTRINSIC_FLAG_I32_CONST AOT_INTRINSIC_FLAG(0, 27)
+#define AOT_INTRINSIC_FLAG_I32_DIV_U AOT_INTRINSIC_FLAG(0, 28)
+#define AOT_INTRINSIC_FLAG_I32_REM_S AOT_INTRINSIC_FLAG(0, 29)
+#define AOT_INTRINSIC_FLAG_I32_REM_U AOT_INTRINSIC_FLAG(0, 30)
+#define AOT_INTRINSIC_FLAG_I32_DIV_S AOT_INTRINSIC_FLAG(0, 31)
+
+#define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0)
+#define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1)
+#define AOT_INTRINSIC_FLAG_F64_FMUL AOT_INTRINSIC_FLAG(1, 2)
+#define AOT_INTRINSIC_FLAG_F64_FDIV AOT_INTRINSIC_FLAG(1, 3)
+#define AOT_INTRINSIC_FLAG_F64_FABS AOT_INTRINSIC_FLAG(1, 4)
+#define AOT_INTRINSIC_FLAG_F64_CEIL AOT_INTRINSIC_FLAG(1, 5)
+#define AOT_INTRINSIC_FLAG_F64_FLOOR AOT_INTRINSIC_FLAG(1, 6)
+#define AOT_INTRINSIC_FLAG_F64_TRUNC AOT_INTRINSIC_FLAG(1, 7)
+#define AOT_INTRINSIC_FLAG_F64_RINT AOT_INTRINSIC_FLAG(1, 8)
+#define AOT_INTRINSIC_FLAG_F64_SQRT AOT_INTRINSIC_FLAG(1, 9)
+#define AOT_INTRINSIC_FLAG_F64_COPYSIGN AOT_INTRINSIC_FLAG(1, 10)
+#define AOT_INTRINSIC_FLAG_F64_MIN AOT_INTRINSIC_FLAG(1, 11)
+#define AOT_INTRINSIC_FLAG_F64_MAX AOT_INTRINSIC_FLAG(1, 12)
+#define AOT_INTRINSIC_FLAG_I64_CLZ AOT_INTRINSIC_FLAG(1, 13)
+#define AOT_INTRINSIC_FLAG_I64_CTZ AOT_INTRINSIC_FLAG(1, 14)
+#define AOT_INTRINSIC_FLAG_I64_POPCNT AOT_INTRINSIC_FLAG(1, 15)
+#define AOT_INTRINSIC_FLAG_I64_TO_F32 AOT_INTRINSIC_FLAG(1, 16)
+#define AOT_INTRINSIC_FLAG_U64_TO_F32 AOT_INTRINSIC_FLAG(1, 17)
+#define AOT_INTRINSIC_FLAG_I64_TO_F64 AOT_INTRINSIC_FLAG(1, 18)
+#define AOT_INTRINSIC_FLAG_U64_TO_F64 AOT_INTRINSIC_FLAG(1, 19)
+#define AOT_INTRINSIC_FLAG_F64_TO_I32 AOT_INTRINSIC_FLAG(1, 20)
+#define AOT_INTRINSIC_FLAG_F64_TO_U32 AOT_INTRINSIC_FLAG(1, 21)
+#define AOT_INTRINSIC_FLAG_F64_TO_I64 AOT_INTRINSIC_FLAG(1, 22)
+#define AOT_INTRINSIC_FLAG_F64_TO_U64 AOT_INTRINSIC_FLAG(1, 23)
+#define AOT_INTRINSIC_FLAG_F64_TO_F32 AOT_INTRINSIC_FLAG(1, 24)
+#define AOT_INTRINSIC_FLAG_F64_CMP AOT_INTRINSIC_FLAG(1, 25)
+#define AOT_INTRINSIC_FLAG_F64_CONST AOT_INTRINSIC_FLAG(1, 26)
+#define AOT_INTRINSIC_FLAG_I64_CONST AOT_INTRINSIC_FLAG(1, 27)
+#define AOT_INTRINSIC_FLAG_I64_DIV_S AOT_INTRINSIC_FLAG(1, 28)
+#define AOT_INTRINSIC_FLAG_I64_DIV_U AOT_INTRINSIC_FLAG(1, 29)
+#define AOT_INTRINSIC_FLAG_I64_REM_S AOT_INTRINSIC_FLAG(1, 30)
+#define AOT_INTRINSIC_FLAG_I64_REM_U AOT_INTRINSIC_FLAG(1, 31)
+#define AOT_INTRINSIC_FLAG_I64_BIT_OR AOT_INTRINSIC_FLAG(1, 32)
+#define AOT_INTRINSIC_FLAG_I64_BIT_AND AOT_INTRINSIC_FLAG(1, 33)
+
+/* clang-format on */
+
+float32
+aot_intrinsic_fadd_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_fadd_f64(float64 a, float64 b);
+
+float32
+aot_intrinsic_fsub_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_fsub_f64(float64 a, float64 b);
+
+float32
+aot_intrinsic_fmul_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_fmul_f64(float64 a, float64 b);
+
+float32
+aot_intrinsic_fdiv_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_fdiv_f64(float64 a, float64 b);
+
+float32
+aot_intrinsic_fabs_f32(float32 a);
+
+float64
+aot_intrinsic_fabs_f64(float64 a);
+
+float32
+aot_intrinsic_ceil_f32(float32 a);
+
+float64
+aot_intrinsic_ceil_f64(float64 a);
+
+float32
+aot_intrinsic_floor_f32(float32 a);
+
+float64
+aot_intrinsic_floor_f64(float64 a);
+
+float32
+aot_intrinsic_trunc_f32(float32 a);
+
+float64
+aot_intrinsic_trunc_f64(float64 a);
+
+float32
+aot_intrinsic_rint_f32(float32 a);
+
+float64
+aot_intrinsic_rint_f64(float64 a);
+
+float32
+aot_intrinsic_sqrt_f32(float32 a);
+
+float64
+aot_intrinsic_sqrt_f64(float64 a);
+
+float32
+aot_intrinsic_copysign_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_copysign_f64(float64 a, float64 b);
+
+float32
+aot_intrinsic_fmin_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_fmin_f64(float64 a, float64 b);
+
+float32
+aot_intrinsic_fmax_f32(float32 a, float32 b);
+
+float64
+aot_intrinsic_fmax_f64(float64 a, float64 b);
+
+uint32
+aot_intrinsic_clz_i32(uint32 type);
+
+uint32
+aot_intrinsic_clz_i64(uint64 type);
+
+uint32
+aot_intrinsic_ctz_i32(uint32 type);
+
+uint32
+aot_intrinsic_ctz_i64(uint64 type);
+
+uint32
+aot_intrinsic_popcnt_i32(uint32 u);
+
+uint32
+aot_intrinsic_popcnt_i64(uint64 u);
+
+float32
+aot_intrinsic_i32_to_f32(int32 i);
+
+float32
+aot_intrinsic_u32_to_f32(uint32 u);
+
+float64
+aot_intrinsic_i32_to_f64(int32 i);
+
+float64
+aot_intrinsic_u32_to_f64(uint32 u);
+
+float32
+aot_intrinsic_i64_to_f32(int64 i);
+
+float32
+aot_intrinsic_u64_to_f32(uint64 u);
+
+float64
+aot_intrinsic_i64_to_f64(int64 i);
+
+float64
+aot_intrinsic_u64_to_f64(uint64 u);
+
+int32
+aot_intrinsic_f32_to_i32(float32 f);
+
+uint32
+aot_intrinsic_f32_to_u32(float32 f);
+
+int64
+aot_intrinsic_f32_to_i64(float32 f);
+
+uint64
+aot_intrinsic_f32_to_u64(float32 f);
+
+int32
+aot_intrinsic_f64_to_i32(float64 f);
+
+uint32
+aot_intrinsic_f64_to_u32(float64 f);
+
+int64
+aot_intrinsic_f64_to_i64(float64 f);
+
+uint64
+aot_intrinsic_f64_to_u64(float64 f);
+
+float64
+aot_intrinsic_f32_to_f64(float32 f);
+
+float32
+aot_intrinsic_f64_to_f32(float64 f);
+
+int32
+aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs);
+
+int32
+aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs);
+
+int64
+aot_intrinsic_i64_div_s(int64 l, int64 r);
+
+int32
+aot_intrinsic_i32_div_s(int32 l, int32 r);
+
+uint32
+aot_intrinsic_i32_div_u(uint32 l, uint32 r);
+
+int32
+aot_intrinsic_i32_rem_s(int32 l, int32 r);
+
+uint32
+aot_intrinsic_i32_rem_u(uint32 l, uint32 r);
+
+uint64
+aot_intrinsic_i64_div_u(uint64 l, uint64 r);
+
+int64
+aot_intrinsic_i64_rem_s(int64 l, int64 r);
+
+uint64
+aot_intrinsic_i64_rem_u(uint64 l, uint64 r);
+
+uint64
+aot_intrinsic_i64_bit_or(uint64 l, uint64 r);
+
+uint64
+aot_intrinsic_i64_bit_and(uint64 l, uint64 r);
+
+const char *
+aot_intrinsic_get_symbol(const char *llvm_intrinsic);
+
+#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
+bool
+aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
+ const char *llvm_intrinsic);
+
+void
+aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _AOT_INTRINSIC_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_loader.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_loader.c
new file mode 100644
index 000000000..5345fb2d7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_loader.c
@@ -0,0 +1,3035 @@
+/*
+ * 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_log.h"
+#include "aot_reloc.h"
+#include "../common/wasm_runtime_common.h"
+#include "../common/wasm_native.h"
+#include "../compilation/aot.h"
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+#include "debug/elf_parser.h"
+#include "debug/jit_debug.h"
+#endif
+
+#define YMM_PLT_PREFIX "__ymm@"
+#define XMM_PLT_PREFIX "__xmm@"
+#define REAL_PLT_PREFIX "__real@"
+
+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, "AOT module load failed: %s",
+ string);
+ }
+}
+
+static void
+set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
+{
+ va_list args;
+ char buf[128];
+
+ if (error_buf != NULL) {
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ snprintf(error_buf, error_buf_size, "AOT module load failed: %s", buf);
+ }
+}
+
+#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)
+{
+ uint32 value;
+
+ value = *(uint32 *)pData;
+ *(uint32 *)pData = *(uint32 *)(pData + 4);
+ *(uint32 *)(pData + 4) = value;
+ exchange_uint32(pData);
+ exchange_uint32(pData + 4);
+}
+
+static union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+static bool
+check_buf(const uint8 *buf, const uint8 *buf_end, uint32 length,
+ char *error_buf, uint32 error_buf_size)
+{
+ if ((uintptr_t)buf + length < (uintptr_t)buf
+ || (uintptr_t)buf + length > (uintptr_t)buf_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpect end");
+ return false;
+ }
+ return true;
+}
+
+#define CHECK_BUF(buf, buf_end, length) \
+ do { \
+ if (!check_buf(buf, buf_end, length, error_buf, error_buf_size)) { \
+ 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;
+}
+
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+
+static inline uint8
+GET_U8_FROM_ADDR(const uint8 *p)
+{
+ uint8 res = 0;
+ bh_assert(p);
+
+ const uint8 *p_aligned = align_ptr(p, 4);
+ p_aligned = (p_aligned > p) ? p_aligned - 4 : p_aligned;
+
+ uint32 buf32 = *(const uint32 *)p_aligned;
+ const uint8 *pbuf = (const uint8 *)&buf32;
+
+ res = *(uint8 *)(pbuf + (p - p_aligned));
+
+ return res;
+}
+
+static inline uint16
+GET_U16_FROM_ADDR(const uint8 *p)
+{
+ uint16 res = 0;
+ bh_assert(p);
+
+ const uint8 *p_aligned = align_ptr(p, 4);
+ p_aligned = (p_aligned > p) ? p_aligned - 4 : p_aligned;
+
+ uint32 buf32 = *(const uint32 *)p_aligned;
+ const uint8 *pbuf = (const uint8 *)&buf32;
+
+ res = *(uint16 *)(pbuf + (p - p_aligned));
+
+ return res;
+}
+
+#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(uint8)) \
+ res = GET_U8_FROM_ADDR(p); \
+ else if (sizeof(type) == sizeof(uint16)) \
+ res = GET_U16_FROM_ADDR(p); \
+ else if (sizeof(type) == sizeof(uint32)) \
+ 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_byte_array(p, p_end, addr, len) \
+ do { \
+ CHECK_BUF(p, p_end, len); \
+ bh_memcpy_wa(addr, len, p, len); \
+ p += len; \
+ } while (0)
+
+#define read_string(p, p_end, str) \
+ do { \
+ if (!(str = load_string((uint8 **)&p, p_end, module, \
+ is_load_from_file_buf, true, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#else /* else of (WASM_ENABLE_WORD_ALIGN_READ != 0) */
+
+#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_byte_array(p, p_end, addr, len) \
+ do { \
+ CHECK_BUF(p, p_end, len); \
+ bh_memcpy_s(addr, len, p, len); \
+ p += len; \
+ } while (0)
+
+#define read_string(p, p_end, str) \
+ do { \
+ if (!(str = load_string((uint8 **)&p, p_end, module, \
+ is_load_from_file_buf, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#endif /* end of (WASM_ENABLE_WORD_ALIGN_READ != 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)
+
+/* 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 */
+#define BIN_TYPE_COFF32 4 /* 32-bit little endian */
+#define BIN_TYPE_COFF64 6 /* 64-bit little 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 */
+#define E_TYPE_XIP 4 /* eXecute In Place 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_AARCH64 183 /* AArch64 */
+#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_ARC_COMPACT 93 /* ARC International ARCompact */
+#define E_MACHINE_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */
+#define E_MACHINE_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define E_MACHINE_RISCV 243 /* RISC-V 32/64 */
+#define E_MACHINE_WIN_I386 0x14c /* Windows i386 architecture */
+#define E_MACHINE_WIN_X86_64 0x8664 /* Windows x86-64 architecture */
+
+/* Legal values for e_version */
+#define E_VERSION_CURRENT 1 /* Current version */
+
+static void *
+loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+static char *
+const_str_set_insert(const uint8 *str, int32 len, AOTModule *module,
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+ bool is_vram_word_align,
+#endif
+ char *error_buf, uint32 error_buf_size)
+{
+ HashMap *set = module->const_str_set;
+ char *c_str, *value;
+
+ /* Create const string set if it isn't created */
+ if (!set
+ && !(set = module->const_str_set = bh_hash_map_create(
+ 32, false, (HashFunc)wasm_string_hash,
+ (KeyEqualFunc)wasm_string_equal, NULL, wasm_runtime_free))) {
+ set_error_buf(error_buf, error_buf_size,
+ "create const string set failed");
+ return NULL;
+ }
+
+ /* Lookup const string set, use the string if found */
+ if (!(c_str = loader_malloc((uint32)len + 1, error_buf, error_buf_size))) {
+ return NULL;
+ }
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+ if (is_vram_word_align) {
+ bh_memcpy_wa(c_str, (uint32)(len + 1), str, (uint32)len);
+ }
+ else
+#endif
+ {
+ 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_runtime_free(c_str);
+ return value;
+ }
+
+ if (!bh_hash_map_insert(set, c_str, c_str)) {
+ set_error_buf(error_buf, error_buf_size,
+ "insert string to hash map failed");
+ wasm_runtime_free(c_str);
+ return NULL;
+ }
+
+ return c_str;
+}
+
+static char *
+load_string(uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
+ bool is_load_from_file_buf,
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+ bool is_vram_word_align,
+#endif
+ char *error_buf, uint32 error_buf_size)
+{
+ uint8 *p = *p_buf;
+ const uint8 *p_end = buf_end;
+ char *str;
+ uint16 str_len;
+
+ read_uint16(p, p_end, str_len);
+ CHECK_BUF(p, p_end, str_len);
+
+ if (str_len == 0) {
+ str = "";
+ }
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+ else if (is_vram_word_align) {
+ if (!(str = const_str_set_insert((uint8 *)p, str_len, module,
+ is_vram_word_align, error_buf,
+ error_buf_size))) {
+ goto fail;
+ }
+ }
+#endif
+ else if (p[str_len - 1] == '\0') {
+ /* The string is terminated with '\0', use it directly */
+ str = (char *)p;
+ }
+ else if (is_load_from_file_buf) {
+ /* As the file buffer can be referred to after loading,
+ we use the 2 bytes of size to adjust the string:
+ move string 2 byte backward and then append '\0' */
+ str = (char *)(p - 2);
+ bh_memmove_s(str, (uint32)(str_len + 1), p, (uint32)str_len);
+ str[str_len] = '\0';
+ }
+ else {
+ /* Load from sections, the file buffer cannot be reffered to
+ after loading, we must create another string and insert it
+ into const string set */
+ if (!(str = const_str_set_insert((uint8 *)p, str_len, module,
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+ is_vram_word_align,
+#endif
+ error_buf, error_buf_size))) {
+ goto fail;
+ }
+ }
+ p += str_len;
+
+ *p_buf = p;
+ return str;
+fail:
+ return NULL;
+}
+
+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:
+ case E_MACHINE_WIN_X86_64:
+ machine_type = "x86_64";
+ break;
+ case E_MACHINE_386:
+ case E_MACHINE_WIN_I386:
+ machine_type = "i386";
+ break;
+ case E_MACHINE_ARM:
+ case E_MACHINE_AARCH64:
+ machine_type = target_info->arch;
+ break;
+ case E_MACHINE_MIPS:
+ machine_type = "mips";
+ break;
+ case E_MACHINE_XTENSA:
+ machine_type = "xtensa";
+ break;
+ case E_MACHINE_RISCV:
+ machine_type = "riscv";
+ break;
+ case E_MACHINE_ARC_COMPACT:
+ case E_MACHINE_ARC_COMPACT2:
+ machine_type = "arc";
+ break;
+ default:
+ set_error_buf_v(error_buf, error_buf_size,
+ "unknown machine type %d", target_info->e_machine);
+ return false;
+ }
+ if (strncmp(target_info->arch, machine_type, strlen(machine_type))) {
+ set_error_buf_v(
+ error_buf, error_buf_size,
+ "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 (strncmp(target_expected, target_got, strlen(target_expected))) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "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_uint16(p, p_end, target_info.bin_type);
+ read_uint16(p, p_end, target_info.abi_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, "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) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "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) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "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 && target_info.e_type != E_TYPE_XIP) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid object file type, "
+ "expected relocatable or XIP 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, "invalid elf file version");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static void *
+get_native_symbol_by_name(const char *name)
+{
+ void *func = NULL;
+ uint32 symnum = 0;
+ SymbolMap *sym = NULL;
+
+ sym = get_target_symbol_map(&symnum);
+
+ while (symnum--) {
+ if (strcmp(sym->symbol_name, name) == 0) {
+ func = sym->symbol_addr;
+ break;
+ }
+ sym++;
+ }
+
+ return func;
+}
+
+static bool
+str2uint32(const char *buf, uint32 *p_res);
+
+static bool
+str2uint64(const char *buf, uint64 *p_res);
+
+static bool
+load_native_symbol_section(const uint8 *buf, const uint8 *buf_end,
+ AOTModule *module, bool is_load_from_file_buf,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 cnt;
+ int32 i;
+ const char *symbol;
+
+ read_uint32(p, p_end, cnt);
+
+ if (cnt > 0) {
+ module->native_symbol_list = wasm_runtime_malloc(cnt * sizeof(void *));
+ if (module->native_symbol_list == NULL) {
+ set_error_buf(error_buf, error_buf_size,
+ "malloc native symbol list failed");
+ goto fail;
+ }
+
+ for (i = cnt - 1; i >= 0; i--) {
+ read_string(p, p_end, symbol);
+ if (!strncmp(symbol, "f32#", 4) || !strncmp(symbol, "i32#", 4)) {
+ uint32 u32;
+ /* Resolve the raw int bits of f32 const */
+ if (!str2uint32(symbol + 4, &u32)) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto fail;
+ }
+ *(uint32 *)(&module->native_symbol_list[i]) = u32;
+ }
+ else if (!strncmp(symbol, "f64#", 4)
+ || !strncmp(symbol, "i64#", 4)) {
+ uint64 u64;
+ /* Resolve the raw int bits of f64 const */
+ if (!str2uint64(symbol + 4, &u64)) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto fail;
+ }
+ *(uint64 *)(&module->native_symbol_list[i]) = u64;
+ }
+ else if (!strncmp(symbol, "__ignore", 8)) {
+ /* Padding bytes to make f64 on 8-byte aligned address,
+ or it is the second 32-bit slot in 32-bit system */
+ continue;
+ }
+ else {
+ module->native_symbol_list[i] =
+ get_native_symbol_by_name(symbol);
+ if (module->native_symbol_list[i] == NULL) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "missing native symbol: %s", symbol);
+ goto fail;
+ }
+ }
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_name_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 *aux_func_indexes;
+ const char **aux_func_names;
+ uint32 name_type, subsection_size;
+ uint32 previous_name_type = 0;
+ uint32 num_func_name;
+ uint32 func_index;
+ uint32 previous_func_index = ~0U;
+ uint32 name_index;
+ int i = 0;
+ uint32 name_len;
+ uint64 size;
+
+ if (p >= p_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ return false;
+ }
+
+ read_uint32(p, p_end, name_len);
+
+ if (name_len != 4 || p + name_len > p_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ return false;
+ }
+
+ if (memcmp(p, "name", 4) != 0) {
+ set_error_buf(error_buf, error_buf_size, "invalid custom name section");
+ return false;
+ }
+ p += name_len;
+
+ while (p < p_end) {
+ read_uint32(p, p_end, name_type);
+ if (i != 0) {
+ if (name_type == previous_name_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "duplicate sub-section");
+ return false;
+ }
+ if (name_type < previous_name_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "out-of-order sub-section");
+ return false;
+ }
+ }
+ previous_name_type = name_type;
+ read_uint32(p, p_end, subsection_size);
+ CHECK_BUF(p, p_end, subsection_size);
+ switch (name_type) {
+ case SUB_SECTION_TYPE_FUNC:
+ if (subsection_size) {
+ read_uint32(p, p_end, num_func_name);
+ if (num_func_name
+ > module->import_func_count + module->func_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "function name count out of bounds");
+ return false;
+ }
+ module->aux_func_name_count = num_func_name;
+
+ /* Allocate memory */
+ size = sizeof(uint32) * (uint64)module->aux_func_name_count;
+ if (!(aux_func_indexes = module->aux_func_indexes =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+ size =
+ sizeof(char **) * (uint64)module->aux_func_name_count;
+ if (!(aux_func_names = module->aux_func_names =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (name_index = 0; name_index < num_func_name;
+ name_index++) {
+ read_uint32(p, p_end, func_index);
+ if (name_index != 0
+ && func_index == previous_func_index) {
+ set_error_buf(error_buf, error_buf_size,
+ "duplicate function name");
+ return false;
+ }
+ if (name_index != 0
+ && func_index < previous_func_index) {
+ set_error_buf(error_buf, error_buf_size,
+ "out-of-order function index ");
+ return false;
+ }
+ if (func_index
+ >= module->import_func_count + module->func_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "function index out of bounds");
+ return false;
+ }
+ previous_func_index = func_index;
+ *(aux_func_indexes + name_index) = func_index;
+ read_string(p, p_end, *(aux_func_names + name_index));
+#if 0
+ LOG_DEBUG("func_index %u -> aux_func_name = %s\n",
+ func_index, *(aux_func_names + name_index));
+#endif
+ }
+ }
+ break;
+ case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection
+ */
+ case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */
+ default:
+ p = p + subsection_size;
+ break;
+ }
+ i++;
+ }
+
+ return true;
+fail:
+ return false;
+#else
+ return true;
+#endif /* WASM_ENABLE_CUSTOM_NAME_SECTION != 0 */
+}
+
+static bool
+load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 sub_section_type;
+
+ read_uint32(p, p_end, sub_section_type);
+ buf = p;
+
+ switch (sub_section_type) {
+ case AOT_CUSTOM_SECTION_NATIVE_SYMBOL:
+ if (!load_native_symbol_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ goto fail;
+ break;
+ case AOT_CUSTOM_SECTION_NAME:
+ if (!load_name_section(buf, buf_end, module, is_load_from_file_buf,
+ error_buf, error_buf_size))
+ goto fail;
+ break;
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ case AOT_CUSTOM_SECTION_RAW:
+ {
+ const char *section_name;
+ WASMCustomSection *section;
+
+ if (p >= p_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ goto fail;
+ }
+
+ read_string(p, p_end, section_name);
+
+ section = loader_malloc(sizeof(WASMCustomSection), error_buf,
+ error_buf_size);
+ if (!section) {
+ goto fail;
+ }
+
+ section->name_addr = (char *)section_name;
+ section->name_len = (uint32)strlen(section_name);
+ section->content_addr = (uint8 *)p;
+ section->content_len = (uint32)(p_end - p);
+
+ section->next = module->custom_section_list;
+ module->custom_section_list = section;
+ LOG_VERBOSE("Load custom section [%s] success.", section_name);
+ break;
+ }
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
+ default:
+ break;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static void
+destroy_import_memories(AOTImportMemory *import_memories)
+{
+ wasm_runtime_free(import_memories);
+}
+
+static void
+destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
+{
+ uint32 i;
+ for (i = 0; i < count; i++)
+ if (data_list[i])
+ wasm_runtime_free(data_list[i]);
+ wasm_runtime_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 (!(module->mem_init_data_list = data_list =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* 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;
+ uint32 is_passive;
+ uint32 memory_index;
+
+ read_uint32(buf, buf_end, is_passive);
+ read_uint32(buf, buf_end, memory_index);
+ 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 (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ /* is_passive and memory_index is only used in bulk memory mode */
+ data_list[i]->is_passive = (bool)is_passive;
+ data_list[i]->memory_index = memory_index;
+#endif
+ 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)
+{
+ uint32 i;
+ uint64 total_size;
+ const uint8 *buf = *p_buf;
+
+ read_uint32(buf, buf_end, module->import_memory_count);
+ /* We don't support import_memory_count > 0 currently */
+ bh_assert(module->import_memory_count == 0);
+
+ read_uint32(buf, buf_end, module->memory_count);
+ total_size = sizeof(AOTMemory) * (uint64)module->memory_count;
+ if (!(module->memories =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < module->memory_count; i++) {
+ read_uint32(buf, buf_end, module->memories[i].memory_flags);
+ read_uint32(buf, buf_end, module->memories[i].num_bytes_per_page);
+ read_uint32(buf, buf_end, module->memories[i].mem_init_page_count);
+ read_uint32(buf, buf_end, module->memories[i].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_import_tables(AOTImportTable *import_tables)
+{
+ wasm_runtime_free(import_tables);
+}
+
+static void
+destroy_tables(AOTTable *tables)
+{
+ wasm_runtime_free(tables);
+}
+
+static void
+destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
+{
+ uint32 i;
+ for (i = 0; i < count; i++)
+ if (data_list[i])
+ wasm_runtime_free(data_list[i]);
+ wasm_runtime_free(data_list);
+}
+
+static bool
+load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
+ AOTModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ AOTImportTable *import_table;
+ uint64 size;
+ uint32 i, possible_grow;
+
+ /* Allocate memory */
+ size = sizeof(AOTImportTable) * (uint64)module->import_table_count;
+ if (!(module->import_tables = import_table =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* keep sync with aot_emit_table_info() aot_emit_aot_file */
+ for (i = 0; i < module->import_table_count; i++, import_table++) {
+ read_uint32(buf, buf_end, import_table->elem_type);
+ read_uint32(buf, buf_end, import_table->table_init_size);
+ read_uint32(buf, buf_end, import_table->table_max_size);
+ read_uint32(buf, buf_end, possible_grow);
+ import_table->possible_grow = (possible_grow & 0x1);
+ }
+
+ *p_buf = buf;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ AOTTable *table;
+ uint64 size;
+ uint32 i, possible_grow;
+
+ /* Allocate memory */
+ size = sizeof(AOTTable) * (uint64)module->table_count;
+ if (!(module->tables = table =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Create each table data segment */
+ for (i = 0; i < module->table_count; i++, table++) {
+ read_uint32(buf, buf_end, table->elem_type);
+ read_uint32(buf, buf_end, table->table_flags);
+ read_uint32(buf, buf_end, table->table_init_size);
+ read_uint32(buf, buf_end, table->table_max_size);
+ read_uint32(buf, buf_end, possible_grow);
+ table->possible_grow = (possible_grow & 0x1);
+ }
+
+ *p_buf = buf;
+ return true;
+fail:
+ return false;
+}
+
+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 (!(module->table_init_data_list = data_list =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Create each table data segment */
+ for (i = 0; i < module->table_init_data_count; i++) {
+ uint32 mode, elem_type;
+ uint32 table_index, init_expr_type, func_index_count;
+ uint64 init_expr_value, size1;
+
+ read_uint32(buf, buf_end, mode);
+ read_uint32(buf, buf_end, elem_type);
+ read_uint32(buf, buf_end, table_index);
+ 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 (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ data_list[i]->mode = mode;
+ data_list[i]->elem_type = elem_type;
+ data_list[i]->is_dropped = false;
+ data_list[i]->table_index = table_index;
+ 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,
+ (uint32)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->import_table_count);
+ if (module->import_table_count > 0
+ && !load_import_table_list(&buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+
+ read_uint32(buf, buf_end, module->table_count);
+ if (module->table_count > 0
+ && !load_table_list(&buf, buf_end, module, error_buf, error_buf_size))
+ return false;
+
+ 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)
+{
+ uint32 i;
+ for (i = 0; i < count; i++)
+ if (func_types[i])
+ wasm_runtime_free(func_types[i]);
+ wasm_runtime_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 (!(module->func_types = func_types =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Create each function type */
+ for (i = 0; i < module->func_type_count; i++) {
+ uint32 param_count, result_count;
+ uint32 param_cell_num, ret_cell_num;
+ uint64 size1;
+
+ read_uint32(buf, buf_end, param_count);
+ read_uint32(buf, buf_end, result_count);
+
+ if (param_count > UINT16_MAX || result_count > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "param count or result count too large");
+ return false;
+ }
+
+ size1 = (uint64)param_count + (uint64)result_count;
+ size = offsetof(AOTFuncType, types) + size1;
+ if (!(func_types[i] = loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ func_types[i]->param_count = (uint16)param_count;
+ func_types[i]->result_count = (uint16)result_count;
+ read_byte_array(buf, buf_end, func_types[i]->types, (uint32)size1);
+
+ param_cell_num = wasm_get_cell_num(func_types[i]->types, param_count);
+ ret_cell_num =
+ wasm_get_cell_num(func_types[i]->types + param_count, result_count);
+ if (param_cell_num > UINT16_MAX || ret_cell_num > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "param count or result count too large");
+ return false;
+ }
+
+ func_types[i]->param_cell_num = (uint16)param_cell_num;
+ func_types[i]->ret_cell_num = (uint16)ret_cell_num;
+ }
+
+ *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)
+{
+ wasm_runtime_free(import_globals);
+}
+
+static bool
+load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
+ AOTModule *module, bool is_load_from_file_buf,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ AOTImportGlobal *import_globals;
+ uint64 size;
+ uint32 i, data_offset = 0;
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+ WASMGlobalImport tmp_global;
+#endif
+
+ /* Allocate memory */
+ size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count;
+ if (!(module->import_globals = import_globals =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Create each import global */
+ for (i = 0; i < module->import_global_count; i++) {
+ buf = (uint8 *)align_ptr(buf, 2);
+ 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);
+
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+ if (wasm_native_lookup_libc_builtin_global(
+ import_globals[i].module_name, import_globals[i].global_name,
+ &tmp_global)) {
+ if (tmp_global.type != import_globals[i].type
+ || tmp_global.is_mutable != import_globals[i].is_mutable) {
+ set_error_buf(error_buf, error_buf_size,
+ "incompatible import type");
+ return false;
+ }
+ import_globals[i].global_data_linked =
+ tmp_global.global_data_linked;
+ import_globals[i].is_linked = true;
+ }
+#else
+ import_globals[i].is_linked = false;
+#endif
+
+ 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, bool is_load_from_file_buf,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+
+ read_uint32(buf, buf_end, module->import_global_count);
+
+ /* load import globals */
+ if (module->import_global_count > 0
+ && !load_import_globals(&buf, buf_end, module, is_load_from_file_buf,
+ error_buf, error_buf_size))
+ return false;
+
+ *p_buf = buf;
+ return true;
+fail:
+ return false;
+}
+
+static void
+destroy_globals(AOTGlobal *globals)
+{
+ wasm_runtime_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 (!(module->globals = globals =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ 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;
+
+ 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);
+
+ if (init_expr_type != INIT_EXPR_TYPE_V128_CONST) {
+ read_uint64(buf, buf_end, globals[i].init_expr.u.i64);
+ }
+ else {
+ uint64 *i64x2 = (uint64 *)globals[i].init_expr.u.v128.i64x2;
+ CHECK_BUF(buf, buf_end, sizeof(uint64) * 2);
+ wasm_runtime_read_v128(buf, &i64x2[0], &i64x2[1]);
+ buf += sizeof(uint64) * 2;
+ }
+
+ globals[i].init_expr.init_expr_type = (uint8)init_expr_type;
+
+ 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)
+{
+ wasm_runtime_free(import_funcs);
+}
+
+static bool
+load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
+ bool is_load_from_file_buf, 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 (!(module->import_funcs = import_funcs =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* 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, "unknown type");
+ return false;
+ }
+ import_funcs[i].func_type =
+ module->func_types[import_funcs[i].func_type_index];
+ read_string(buf, buf_end, import_funcs[i].module_name);
+ read_string(buf, buf_end, import_funcs[i].func_name);
+
+ module_name = import_funcs[i].module_name;
+ field_name = import_funcs[i].func_name;
+ import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol(
+ module_name, field_name, import_funcs[i].func_type,
+ &import_funcs[i].signature, &import_funcs[i].attachment,
+ &import_funcs[i].call_conv_raw);
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
+ || !strcmp(import_funcs[i].module_name, "wasi_snapshot_preview1"))
+ module->import_wasi_api = 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, bool is_load_from_file_buf,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+
+ read_uint32(buf, buf_end, module->import_func_count);
+
+ /* load import funcs */
+ if (module->import_func_count > 0
+ && !load_import_funcs(&buf, buf_end, module, is_load_from_file_buf,
+ 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)
+ os_munmap(data_section->data, data_section->size);
+ wasm_runtime_free(data_sections);
+}
+
+static bool
+load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end,
+ AOTModule *module, bool is_load_from_file_buf,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ AOTObjectDataSection *data_sections;
+ uint64 size;
+ uint32 i;
+
+ /* Allocate memory */
+ size = sizeof(AOTObjectDataSection) * (uint64)module->data_section_count;
+ if (!(module->data_sections = data_sections =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* 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) \
+ || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+ /* 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].size > 0
+ && !(data_sections[i].data = os_mmap(NULL, data_sections[i].size,
+ map_prot, map_flags))) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ return false;
+ }
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+#if !defined(BH_PLATFORM_LINUX_SGX) && !defined(BH_PLATFORM_WINDOWS) \
+ && !defined(BH_PLATFORM_DARWIN)
+ /* address must be in the first 2 Gigabytes of
+ the process address space */
+ bh_assert((uintptr_t)data_sections[i].data < INT32_MAX);
+#endif
+#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, bool is_load_from_file_buf,
+ 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,
+ is_load_from_file_buf, 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, bool is_load_from_file_buf,
+ 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, is_load_from_file_buf,
+ 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, is_load_from_file_buf,
+ 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->func_count)) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid start function index");
+ return false;
+ }
+
+ read_uint32(p, p_end, module->aux_data_end_global_index);
+ read_uint32(p, p_end, module->aux_data_end);
+ read_uint32(p, p_end, module->aux_heap_base_global_index);
+ read_uint32(p, p_end, module->aux_heap_base);
+ read_uint32(p, p_end, module->aux_stack_top_global_index);
+ read_uint32(p, p_end, module->aux_stack_bottom);
+ read_uint32(p, p_end, module->aux_stack_size);
+
+ if (!load_object_data_sections_info(&p, p_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid init data section size");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+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, "invalid code size");
+ return false;
+ }
+
+ /* The layout is: literal size + literal + code (with plt table) */
+ read_uint32(buf, buf_end, module->literal_size);
+
+ /* literal data is at beginning of the text section */
+ module->literal = (uint8 *)buf;
+ module->code = (void *)(buf + module->literal_size);
+ module->code_size = (uint32)(buf_end - (uint8 *)module->code);
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ module->elf_size = module->code_size;
+
+ if (is_ELF(module->code)) {
+ /* Now code points to an ELF object, we pull it down to .text section */
+ uint64 offset;
+ uint64 size;
+ char *code_buf = module->code;
+ module->elf_hdr = code_buf;
+ if (!get_text_section(code_buf, &offset, &size)) {
+ set_error_buf(error_buf, error_buf_size,
+ "get text section of ELF failed");
+ return false;
+ }
+ module->code = code_buf + offset;
+ module->code_size -= (uint32)offset;
+ }
+#endif
+
+ if ((module->code_size > 0) && !module->is_indirect_mode) {
+ plt_base = (uint8 *)buf_end - get_plt_table_size();
+ init_plt_table(plt_base);
+ }
+ return true;
+fail:
+ return false;
+}
+
+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;
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ RUNTIME_FUNCTION *rtl_func_table;
+ AOTUnwindInfo *unwind_info;
+ uint32 unwind_info_offset = module->code_size - sizeof(AOTUnwindInfo);
+ uint32 unwind_code_offset = unwind_info_offset - PLT_ITEM_SIZE;
+#endif
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ unwind_info = (AOTUnwindInfo *)((uint8 *)module->code + module->code_size
+ - sizeof(AOTUnwindInfo));
+ unwind_info->Version = 1;
+ unwind_info->Flags = UNW_FLAG_NHANDLER;
+ *(uint32 *)&unwind_info->UnwindCode[0] = unwind_code_offset;
+
+ size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count;
+ if (size > 0
+ && !(rtl_func_table = module->rtl_func_table =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+#endif
+
+ size = sizeof(void *) * (uint64)module->func_count;
+ if (size > 0
+ && !(module->func_ptrs =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ 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,
+ "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
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ rtl_func_table[i].BeginAddress = (DWORD)text_offset;
+ if (i > 0) {
+ rtl_func_table[i - 1].EndAddress = rtl_func_table[i].BeginAddress;
+ }
+ rtl_func_table[i].UnwindInfoAddress = (DWORD)unwind_info_offset;
+#endif
+ }
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ if (module->func_count > 0) {
+ uint32 plt_table_size =
+ module->is_indirect_mode ? 0 : get_plt_table_size();
+ rtl_func_table[module->func_count - 1].EndAddress =
+ (DWORD)(module->code_size - plt_table_size);
+
+ if (!RtlAddFunctionTable(rtl_func_table, module->func_count,
+ (DWORD64)(uintptr_t)module->code)) {
+ set_error_buf(error_buf, error_buf_size,
+ "add dynamic function table failed");
+ return false;
+ }
+ module->rtl_func_table_registered = true;
+ }
+#endif
+
+ /* Set start function when function pointers are resolved */
+ if (module->start_func_index != (uint32)-1) {
+ if (module->start_func_index >= module->import_func_count)
+ module->start_function =
+ module->func_ptrs[module->start_func_index
+ - module->import_func_count];
+ else
+ /* TODO: fix start function can be import function issue */
+ module->start_function = NULL;
+ }
+ else {
+ module->start_function = NULL;
+ }
+
+ size = sizeof(uint32) * (uint64)module->func_count;
+ if (size > 0
+ && !(module->func_type_indexes =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ 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, "unknown type");
+ return false;
+ }
+ }
+
+ if (p != buf_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid function section size");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static void
+destroy_exports(AOTExport *exports)
+{
+ wasm_runtime_free(exports);
+}
+
+static bool
+load_exports(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
+ bool is_load_from_file_buf, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ AOTExport *exports;
+ uint64 size;
+ uint32 i;
+
+ /* Allocate memory */
+ size = sizeof(AOTExport) * (uint64)module->export_count;
+ if (!(module->exports = exports =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Create each export */
+ for (i = 0; i < module->export_count; i++) {
+ read_uint32(buf, buf_end, exports[i].index);
+ read_uint8(buf, buf_end, exports[i].kind);
+ read_string(buf, buf_end, exports[i].name);
+#if 0 /* TODO: check kind and index */
+ if (export_funcs[i].index >=
+ module->func_count + module->import_func_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "function index is out of range");
+ return false;
+ }
+#endif
+ }
+
+ *p_buf = buf;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_export_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
+ bool is_load_from_file_buf, 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_count);
+ if (module->export_count > 0
+ && !load_exports(&p, p_end, module, is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "invalid export section size");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+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;
+}
+
+static void *
+resolve_target_sym(const char *symbol, int32 *p_index)
+{
+ uint32 i, num = 0;
+ SymbolMap *target_sym_map;
+
+ if (!(target_sym_map = get_target_symbol_map(&num)))
+ return NULL;
+
+ for (i = 0; i < num; i++) {
+ if (!strcmp(target_sym_map[i].symbol_name, symbol)
+#if defined(_WIN32) || defined(_WIN32_)
+ /* In Win32, the symbol name of function added by
+ LLVMAddFunction() is prefixed by '_', ignore it */
+ || (strlen(symbol) > 1 && symbol[0] == '_'
+ && !strcmp(target_sym_map[i].symbol_name, symbol + 1))
+#endif
+ ) {
+ *p_index = (int32)i;
+ return target_sym_map[i].symbol_addr;
+ }
+ }
+ return NULL;
+}
+
+static bool
+is_literal_relocation(const char *reloc_sec_name)
+{
+ return !strcmp(reloc_sec_name, ".rela.literal");
+}
+
+static bool
+str2uint32(const char *buf, uint32 *p_res)
+{
+ uint32 res = 0, val;
+ const char *buf_end = buf + 8;
+ char ch;
+
+ while (buf < buf_end) {
+ ch = *buf++;
+ if (ch >= '0' && ch <= '9')
+ val = ch - '0';
+ else if (ch >= 'a' && ch <= 'f')
+ val = ch - 'a' + 0xA;
+ else if (ch >= 'A' && ch <= 'F')
+ val = ch - 'A' + 0xA;
+ else
+ return false;
+ res = (res << 4) | val;
+ }
+ *p_res = res;
+ return true;
+}
+
+static bool
+str2uint64(const char *buf, uint64 *p_res)
+{
+ uint64 res = 0, val;
+ const char *buf_end = buf + 16;
+ char ch;
+
+ while (buf < buf_end) {
+ ch = *buf++;
+ if (ch >= '0' && ch <= '9')
+ val = ch - '0';
+ else if (ch >= 'a' && ch <= 'f')
+ val = ch - 'a' + 0xA;
+ else if (ch >= 'A' && ch <= 'F')
+ val = ch - 'A' + 0xA;
+ else
+ return false;
+ res = (res << 4) | val;
+ }
+ *p_res = res;
+ return true;
+}
+
+static bool
+do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
+ char *error_buf, uint32 error_buf_size)
+{
+ bool is_literal = is_literal_relocation(group->section_name);
+ uint8 *aot_text = is_literal ? module->literal : module->code;
+ uint32 aot_text_size =
+ is_literal ? module->literal_size : module->code_size;
+ uint32 i, func_index, symbol_len;
+#if defined(BH_PLATFORM_WINDOWS)
+ uint32 ymm_plt_index = 0, xmm_plt_index = 0;
+ uint32 real_plt_index = 0, float_plt_index = 0, j;
+#endif
+ 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,
+ "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 = loader_malloc(symbol_len + 1, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ }
+ bh_memcpy_s(symbol, symbol_len, 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) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "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, ".sdata")
+ || !strcmp(symbol, ".rdata")
+ || !strcmp(symbol, ".rodata")
+ /* ".rodata.cst4/8/16/.." */
+ || !strncmp(symbol, ".rodata.cst", strlen(".rodata.cst"))
+ /* ".rodata.strn.m" */
+ || !strncmp(symbol, ".rodata.str", strlen(".rodata.str"))) {
+ symbol_addr = get_data_section_addr(module, symbol, NULL);
+ if (!symbol_addr) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "invalid data section (%s)", symbol);
+ goto check_symbol_fail;
+ }
+ }
+ else if (!strcmp(symbol, ".literal")) {
+ symbol_addr = module->literal;
+ }
+#if defined(BH_PLATFORM_WINDOWS)
+ /* Relocation for symbols which start with "__ymm@", "__xmm@" or
+ "__real@" and end with the ymm value, xmm value or real value.
+ In Windows PE file, the data is stored in some individual ".rdata"
+ sections. We simply create extra plt data, parse the values from
+ the symbols and stored them into the extra plt data. */
+ else if (!strcmp(group->section_name, ".text")
+ && !strncmp(symbol, YMM_PLT_PREFIX, strlen(YMM_PLT_PREFIX))
+ && strlen(symbol) == strlen(YMM_PLT_PREFIX) + 64) {
+ char ymm_buf[17] = { 0 };
+
+ symbol_addr = module->extra_plt_data + ymm_plt_index * 32;
+ for (j = 0; j < 4; j++) {
+ bh_memcpy_s(ymm_buf, sizeof(ymm_buf),
+ symbol + strlen(YMM_PLT_PREFIX) + 48 - 16 * j, 16);
+ if (!str2uint64(ymm_buf,
+ (uint64 *)((uint8 *)symbol_addr + 8 * j))) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto check_symbol_fail;
+ }
+ }
+ ymm_plt_index++;
+ }
+ else if (!strcmp(group->section_name, ".text")
+ && !strncmp(symbol, XMM_PLT_PREFIX, strlen(XMM_PLT_PREFIX))
+ && strlen(symbol) == strlen(XMM_PLT_PREFIX) + 32) {
+ char xmm_buf[17] = { 0 };
+
+ symbol_addr = module->extra_plt_data + module->ymm_plt_count * 32
+ + xmm_plt_index * 16;
+ for (j = 0; j < 2; j++) {
+ bh_memcpy_s(xmm_buf, sizeof(xmm_buf),
+ symbol + strlen(XMM_PLT_PREFIX) + 16 - 16 * j, 16);
+ if (!str2uint64(xmm_buf,
+ (uint64 *)((uint8 *)symbol_addr + 8 * j))) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto check_symbol_fail;
+ }
+ }
+ xmm_plt_index++;
+ }
+ else if (!strcmp(group->section_name, ".text")
+ && !strncmp(symbol, REAL_PLT_PREFIX, strlen(REAL_PLT_PREFIX))
+ && strlen(symbol) == strlen(REAL_PLT_PREFIX) + 16) {
+ char real_buf[17] = { 0 };
+
+ symbol_addr = module->extra_plt_data + module->ymm_plt_count * 32
+ + module->xmm_plt_count * 16 + real_plt_index * 8;
+ bh_memcpy_s(real_buf, sizeof(real_buf),
+ symbol + strlen(REAL_PLT_PREFIX), 16);
+ if (!str2uint64(real_buf, (uint64 *)symbol_addr)) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto check_symbol_fail;
+ }
+ real_plt_index++;
+ }
+ else if (!strcmp(group->section_name, ".text")
+ && !strncmp(symbol, REAL_PLT_PREFIX, strlen(REAL_PLT_PREFIX))
+ && strlen(symbol) == strlen(REAL_PLT_PREFIX) + 8) {
+ char float_buf[9] = { 0 };
+
+ symbol_addr = module->extra_plt_data + module->ymm_plt_count * 32
+ + module->xmm_plt_count * 16
+ + module->real_plt_count * 8 + float_plt_index * 4;
+ bh_memcpy_s(float_buf, sizeof(float_buf),
+ symbol + strlen(REAL_PLT_PREFIX), 8);
+ if (!str2uint32(float_buf, (uint32 *)symbol_addr)) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto check_symbol_fail;
+ }
+ float_plt_index++;
+ }
+#endif /* end of defined(BH_PLATFORM_WINDOWS) */
+ else if (!(symbol_addr = resolve_target_sym(symbol, &symbol_index))) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "resolve symbol %s failed", symbol);
+ goto check_symbol_fail;
+ }
+
+ if (symbol != symbol_buf)
+ wasm_runtime_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_runtime_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 if (!strcmp(group->section_name, ".rdata")) {
+ data_section_name = group->section_name;
+ }
+ else {
+ set_error_buf(error_buf, error_buf_size,
+ "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,
+ "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 {
+ set_error_buf_v(error_buf, error_buf_size,
+ "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, bool is_load_from_file_buf,
+ char *error_buf, uint32 error_buf_size)
+{
+ AOTRelocationGroup *groups = NULL, *group;
+ uint32 symbol_count = 0;
+ uint32 group_count = 0, i, j;
+ uint64 size;
+ uint32 *symbol_offsets, total_string_len;
+ uint8 *symbol_buf, *symbol_buf_end;
+ int map_prot, map_flags;
+ bool ret = false;
+ char **symbols = NULL;
+
+ 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,
+ "validate symbol table failed");
+ goto fail;
+ }
+
+ if (symbol_count > 0) {
+ symbols = loader_malloc((uint64)sizeof(*symbols) * symbol_count,
+ error_buf, error_buf_size);
+ if (symbols == NULL) {
+ goto fail;
+ }
+ }
+
+#if defined(BH_PLATFORM_WINDOWS)
+ buf = symbol_buf_end;
+ read_uint32(buf, buf_end, group_count);
+
+ for (i = 0; i < group_count; i++) {
+ uint32 name_index, relocation_count;
+ uint16 group_name_len;
+ uint8 *group_name;
+
+ /* 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,
+ "symbol index out of range");
+ goto fail;
+ }
+
+ group_name = symbol_buf + symbol_offsets[name_index];
+ group_name_len = *(uint16 *)group_name;
+ group_name += sizeof(uint16);
+
+ read_uint32(buf, buf_end, relocation_count);
+
+ for (j = 0; j < relocation_count; j++) {
+ AOTRelocation relocation = { 0 };
+ uint32 symbol_index, offset32;
+ int32 addend32;
+ uint16 symbol_name_len;
+ uint8 *symbol_name;
+
+ if (sizeof(void *) == 8) {
+ read_uint64(buf, buf_end, relocation.relocation_offset);
+ read_uint64(buf, buf_end, relocation.relocation_addend);
+ }
+ else {
+ read_uint32(buf, buf_end, offset32);
+ relocation.relocation_offset = (uint64)offset32;
+ read_uint32(buf, buf_end, addend32);
+ relocation.relocation_addend = (int64)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,
+ "symbol index out of range");
+ goto fail;
+ }
+
+ symbol_name = symbol_buf + symbol_offsets[symbol_index];
+ symbol_name_len = *(uint16 *)symbol_name;
+ symbol_name += sizeof(uint16);
+
+ char group_name_buf[128] = { 0 };
+ char symbol_name_buf[128] = { 0 };
+ memcpy(group_name_buf, group_name, group_name_len);
+ memcpy(symbol_name_buf, symbol_name, symbol_name_len);
+
+ if ((group_name_len == strlen(".text")
+ || (module->is_indirect_mode
+ && group_name_len == strlen(".text") + 1))
+ && !strncmp(group_name, ".text", strlen(".text"))) {
+ if ((symbol_name_len == strlen(YMM_PLT_PREFIX) + 64
+ || (module->is_indirect_mode
+ && symbol_name_len == strlen(YMM_PLT_PREFIX) + 64 + 1))
+ && !strncmp(symbol_name, YMM_PLT_PREFIX,
+ strlen(YMM_PLT_PREFIX))) {
+ module->ymm_plt_count++;
+ }
+ else if ((symbol_name_len == strlen(XMM_PLT_PREFIX) + 32
+ || (module->is_indirect_mode
+ && symbol_name_len
+ == strlen(XMM_PLT_PREFIX) + 32 + 1))
+ && !strncmp(symbol_name, XMM_PLT_PREFIX,
+ strlen(XMM_PLT_PREFIX))) {
+ module->xmm_plt_count++;
+ }
+ else if ((symbol_name_len == strlen(REAL_PLT_PREFIX) + 16
+ || (module->is_indirect_mode
+ && symbol_name_len
+ == strlen(REAL_PLT_PREFIX) + 16 + 1))
+ && !strncmp(symbol_name, REAL_PLT_PREFIX,
+ strlen(REAL_PLT_PREFIX))) {
+ module->real_plt_count++;
+ }
+ else if ((symbol_name_len >= strlen(REAL_PLT_PREFIX) + 8
+ || (module->is_indirect_mode
+ && symbol_name_len
+ == strlen(REAL_PLT_PREFIX) + 8 + 1))
+ && !strncmp(symbol_name, REAL_PLT_PREFIX,
+ strlen(REAL_PLT_PREFIX))) {
+ module->float_plt_count++;
+ }
+ }
+ }
+ }
+
+ /* Allocate memory for extra plt data */
+ size = sizeof(uint64) * 4 * module->ymm_plt_count
+ + sizeof(uint64) * 2 * module->xmm_plt_count
+ + sizeof(uint64) * module->real_plt_count
+ + sizeof(uint32) * module->float_plt_count;
+ if (size > 0) {
+ map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
+ /* aot code and data in x86_64 must be in range 0 to 2G due to
+ relocation for R_X86_64_32/32S/PC32 */
+ map_flags = MMAP_MAP_32BIT;
+
+ if (size > UINT32_MAX
+ || !(module->extra_plt_data =
+ os_mmap(NULL, (uint32)size, map_prot, map_flags))) {
+ set_error_buf(error_buf, error_buf_size, "mmap memory failed");
+ goto fail;
+ }
+ module->extra_plt_data_size = (uint32)size;
+ }
+#endif /* end of defined(BH_PLATFORM_WINDOWS) */
+
+ buf = symbol_buf_end;
+ read_uint32(buf, buf_end, group_count);
+
+ /* Allocate memory for relocation groups */
+ size = sizeof(AOTRelocationGroup) * (uint64)group_count;
+ if (size > 0
+ && !(groups = loader_malloc(size, error_buf, error_buf_size))) {
+ goto fail;
+ }
+
+ /* Load each relocation group */
+ for (i = 0, group = groups; i < group_count; i++, group++) {
+ AOTRelocation *relocation;
+ uint32 name_index;
+
+ /* 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,
+ "symbol index out of range");
+ goto fail;
+ }
+
+ if (symbols[name_index] == NULL) {
+ uint8 *name_addr = symbol_buf + symbol_offsets[name_index];
+
+ read_string(name_addr, buf_end, symbols[name_index]);
+ }
+ group->section_name = symbols[name_index];
+
+ read_uint32(buf, buf_end, group->relocation_count);
+
+ /* Allocate memory for relocations */
+ size = sizeof(AOTRelocation) * (uint64)group->relocation_count;
+ if (!(group->relocations = relocation =
+ loader_malloc(size, error_buf, error_buf_size))) {
+ ret = false;
+ goto fail;
+ }
+
+ /* Load each relocation */
+ for (j = 0; j < group->relocation_count; j++, relocation++) {
+ uint32 symbol_index;
+
+ 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,
+ "symbol index out of range");
+ goto fail;
+ }
+
+ if (symbols[symbol_index] == NULL) {
+ uint8 *symbol_addr = symbol_buf + symbol_offsets[symbol_index];
+
+ read_string(symbol_addr, buf_end, symbols[symbol_index]);
+ }
+ relocation->symbol_name = symbols[symbol_index];
+ }
+
+ if (!strcmp(group->section_name, ".rel.text")
+ || !strcmp(group->section_name, ".rela.text")
+ || !strcmp(group->section_name, ".rela.literal")
+#ifdef BH_PLATFORM_WINDOWS
+ || !strcmp(group->section_name, ".text")
+#endif
+ ) {
+#if !defined(BH_PLATFORM_LINUX) && !defined(BH_PLATFORM_LINUX_SGX) \
+ && !defined(BH_PLATFORM_DARWIN) && !defined(BH_PLATFORM_WINDOWS)
+ if (module->is_indirect_mode) {
+ set_error_buf(error_buf, error_buf_size,
+ "cannot apply relocation to text section "
+ "for aot file generated with "
+ "\"--enable-indirect-mode\" flag");
+ goto fail;
+ }
+#endif
+ if (!do_text_relocation(module, group, error_buf, error_buf_size))
+ goto fail;
+ }
+ else {
+ if (!do_data_relocation(module, group, error_buf, error_buf_size))
+ goto fail;
+ }
+ }
+
+ /* Set read only for AOT code and some data sections */
+ map_prot = MMAP_PROT_READ | MMAP_PROT_EXEC;
+
+ if (module->code) {
+ /* The layout is: literal size + literal + code (with plt table) */
+ uint8 *mmap_addr = module->literal - sizeof(uint32);
+ uint32 total_size =
+ sizeof(uint32) + module->literal_size + module->code_size;
+ os_mprotect(mmap_addr, total_size, map_prot);
+ }
+
+ map_prot = MMAP_PROT_READ;
+
+#if defined(BH_PLATFORM_WINDOWS)
+ if (module->extra_plt_data) {
+ os_mprotect(module->extra_plt_data, module->extra_plt_data_size,
+ map_prot);
+ }
+#endif
+
+ for (i = 0; i < module->data_section_count; i++) {
+ AOTObjectDataSection *data_section = module->data_sections + i;
+ if (!strcmp(data_section->name, ".rdata")
+ || !strcmp(data_section->name, ".rodata")
+ /* ".rodata.cst4/8/16/.." */
+ || !strncmp(data_section->name, ".rodata.cst",
+ strlen(".rodata.cst"))
+ /* ".rodata.strn.m" */
+ || !strncmp(data_section->name, ".rodata.str",
+ strlen(".rodata.str"))) {
+ os_mprotect(data_section->data, data_section->size, map_prot);
+ }
+ }
+
+ ret = true;
+
+fail:
+ if (symbols) {
+ wasm_runtime_free(symbols);
+ }
+ if (groups) {
+ for (i = 0, group = groups; i < group_count; i++, group++)
+ if (group->relocations)
+ wasm_runtime_free(group->relocations);
+ wasm_runtime_free(groups);
+ }
+
+ (void)map_flags;
+ return ret;
+}
+
+static bool
+load_from_sections(AOTModule *module, AOTSection *sections,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ AOTSection *section = sections;
+ const uint8 *buf, *buf_end;
+ uint32 last_section_type = (uint32)-1, section_type;
+ uint32 i, func_index, func_type_index;
+ AOTFuncType *func_type;
+ AOTExport *exports;
+
+ 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
+ && section_type != AOT_SECTION_TYPE_CUSTOM))) {
+ set_error_buf(error_buf, error_buf_size, "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,
+ is_load_from_file_buf, 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,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case AOT_SECTION_TYPE_RELOCATION:
+ if (!load_relocation_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case AOT_SECTION_TYPE_CUSTOM:
+ if (!load_custom_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ default:
+ set_error_buf(error_buf, error_buf_size,
+ "invalid aot section type");
+ return false;
+ }
+
+ section = section->next;
+ }
+
+ if (last_section_type != AOT_SECTION_TYPE_RELOCATION
+ && last_section_type != AOT_SECTION_TYPE_CUSTOM) {
+ set_error_buf(error_buf, error_buf_size, "section missing");
+ return false;
+ }
+
+ /* Resolve malloc and free function */
+ module->malloc_func_index = (uint32)-1;
+ module->free_func_index = (uint32)-1;
+ module->retain_func_index = (uint32)-1;
+
+ exports = module->exports;
+ for (i = 0; i < module->export_count; i++) {
+ if (exports[i].kind == EXPORT_KIND_FUNC
+ && exports[i].index >= module->import_func_count) {
+ if (!strcmp(exports[i].name, "malloc")) {
+ func_index = exports[i].index - module->import_func_count;
+ func_type_index = module->func_type_indexes[func_index];
+ func_type = module->func_types[func_type_index];
+ if (func_type->param_count == 1 && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32) {
+ bh_assert(module->malloc_func_index == (uint32)-1);
+ module->malloc_func_index = func_index;
+ LOG_VERBOSE("Found malloc function, name: %s, index: %u",
+ exports[i].name, exports[i].index);
+ }
+ }
+ else if (!strcmp(exports[i].name, "__new")) {
+ func_index = exports[i].index - module->import_func_count;
+ func_type_index = module->func_type_indexes[func_index];
+ func_type = module->func_types[func_type_index];
+ if (func_type->param_count == 2 && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32
+ && func_type->types[2] == VALUE_TYPE_I32) {
+ uint32 j;
+ WASMExport *export_tmp;
+
+ bh_assert(module->malloc_func_index == (uint32)-1);
+ module->malloc_func_index = func_index;
+ LOG_VERBOSE("Found malloc function, name: %s, index: %u",
+ exports[i].name, exports[i].index);
+
+ /* resolve retain function.
+ If not find, reset malloc function index */
+ export_tmp = module->exports;
+ for (j = 0; j < module->export_count; j++, export_tmp++) {
+ if ((export_tmp->kind == EXPORT_KIND_FUNC)
+ && (!strcmp(export_tmp->name, "__retain")
+ || !strcmp(export_tmp->name, "__pin"))) {
+ func_index =
+ export_tmp->index - module->import_func_count;
+ func_type_index =
+ module->func_type_indexes[func_index];
+ func_type = module->func_types[func_type_index];
+ if (func_type->param_count == 1
+ && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32) {
+ bh_assert(module->retain_func_index
+ == (uint32)-1);
+ module->retain_func_index = export_tmp->index;
+ LOG_VERBOSE("Found retain function, name: %s, "
+ "index: %u",
+ export_tmp->name,
+ export_tmp->index);
+ break;
+ }
+ }
+ }
+ if (j == module->export_count) {
+ module->malloc_func_index = (uint32)-1;
+ LOG_VERBOSE("Can't find retain function,"
+ "reset malloc function index to -1");
+ }
+ }
+ }
+ else if ((!strcmp(exports[i].name, "free"))
+ || (!strcmp(exports[i].name, "__release"))
+ || (!strcmp(exports[i].name, "__unpin"))) {
+ func_index = exports[i].index - module->import_func_count;
+ func_type_index = module->func_type_indexes[func_index];
+ func_type = module->func_types[func_type_index];
+ if (func_type->param_count == 1 && func_type->result_count == 0
+ && func_type->types[0] == VALUE_TYPE_I32) {
+ bh_assert(module->free_func_index == (uint32)-1);
+ module->free_func_index = func_index;
+ LOG_VERBOSE("Found free function, name: %s, index: %u",
+ exports[i].name, exports[i].index);
+ }
+ }
+ }
+ }
+
+ /* Flush data cache before executing AOT code,
+ * otherwise unpredictable behavior can occur. */
+ os_dcache_flush();
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module);
+#endif
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ if (!jit_code_entry_create(module->elf_hdr, module->elf_size)) {
+ set_error_buf(error_buf, error_buf_size,
+ "create jit code entry failed");
+ return false;
+ }
+#endif
+ return true;
+}
+
+static AOTModule *
+create_module(char *error_buf, uint32 error_buf_size)
+{
+ AOTModule *module =
+ loader_malloc(sizeof(AOTModule), error_buf, error_buf_size);
+
+ if (!module) {
+ return NULL;
+ }
+
+ module->module_type = Wasm_Module_AoT;
+
+ 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, false, 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)
+ os_munmap((uint8 *)section->section_body,
+ section->section_body_size);
+ wasm_runtime_free(section);
+ section = next;
+ }
+}
+
+static bool
+resolve_execute_mode(const uint8 *buf, uint32 size, bool *p_mode,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf + size;
+ uint32 section_type;
+ uint32 section_size = 0;
+ uint16 e_type = 0;
+
+ p += 8;
+ while (p < p_end) {
+ read_uint32(p, p_end, section_type);
+ if (section_type <= AOT_SECTION_TYPE_SIGANATURE
+ || section_type == AOT_SECTION_TYPE_TARGET_INFO) {
+ read_uint32(p, p_end, section_size);
+ CHECK_BUF(p, p_end, section_size);
+ if (section_type == AOT_SECTION_TYPE_TARGET_INFO) {
+ p += 4;
+ read_uint16(p, p_end, e_type);
+ if (e_type == E_TYPE_XIP) {
+ *p_mode = true;
+ }
+ else {
+ *p_mode = false;
+ }
+ break;
+ }
+ }
+ else if (section_type > AOT_SECTION_TYPE_SIGANATURE) {
+ set_error_buf(error_buf, error_buf_size,
+ "resolve execute mode failed");
+ break;
+ }
+ p += section_size;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+create_sections(AOTModule *module, 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;
+ bool destroy_aot_text = false;
+ bool is_indirect_mode = false;
+ uint32 section_type;
+ uint32 section_size;
+ uint64 total_size;
+ uint8 *aot_text;
+
+ if (!resolve_execute_mode(buf, size, &is_indirect_mode, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ module->is_indirect_mode = is_indirect_mode;
+
+ p += 8;
+ while (p < p_end) {
+ read_uint32(p, p_end, section_type);
+ if (section_type < AOT_SECTION_TYPE_SIGANATURE
+ || section_type == AOT_SECTION_TYPE_CUSTOM) {
+ read_uint32(p, p_end, section_size);
+ CHECK_BUF(p, p_end, section_size);
+
+ if (!(section = loader_malloc(sizeof(AOTSection), error_buf,
+ error_buf_size))) {
+ goto fail;
+ }
+
+ memset(section, 0, sizeof(AOTSection));
+ section->section_type = (int32)section_type;
+ section->section_body = (uint8 *)p;
+ section->section_body_size = section_size;
+
+ if (section_type == AOT_SECTION_TYPE_TEXT) {
+ if ((section_size > 0) && !module->is_indirect_mode) {
+ int map_prot =
+ MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+ /* 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 = os_mmap(NULL, (uint32)total_size,
+ map_prot, map_flags))) {
+ wasm_runtime_free(section);
+ set_error_buf(error_buf, error_buf_size,
+ "mmap memory failed");
+ goto fail;
+ }
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+#if !defined(BH_PLATFORM_LINUX_SGX) && !defined(BH_PLATFORM_WINDOWS) \
+ && !defined(BH_PLATFORM_DARWIN)
+ /* address must be in the first 2 Gigabytes of
+ the process address space */
+ bh_assert((uintptr_t)aot_text < INT32_MAX);
+#endif
+#endif
+ bh_memcpy_s(aot_text, (uint32)total_size,
+ section->section_body, (uint32)section_size);
+ section->section_body = aot_text;
+ destroy_aot_text = true;
+
+ 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;
+ }
+ }
+ }
+
+ 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, "invalid section id");
+ goto fail;
+ }
+ }
+
+ if (!section_list) {
+ set_error_buf(error_buf, error_buf_size, "create section list failed");
+ return false;
+ }
+
+ *p_section_list = section_list;
+ return true;
+fail:
+ if (section_list)
+ destroy_sections(section_list, destroy_aot_text);
+ 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(module, buf, size, &section_list, error_buf,
+ error_buf_size))
+ return false;
+
+ ret = load_from_sections(module, section_list, true, error_buf,
+ error_buf_size);
+ if (!ret) {
+ /* If load_from_sections() fails, then aot text is destroyed
+ in destroy_sections() */
+ destroy_sections(section_list, module->is_indirect_mode ? false : 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;
+}
+
+void
+aot_unload(AOTModule *module)
+{
+ if (module->import_memories)
+ destroy_import_memories(module->import_memories);
+
+ if (module->memories)
+ wasm_runtime_free(module->memories);
+
+ if (module->mem_init_data_list)
+ destroy_mem_init_data_list(module->mem_init_data_list,
+ module->mem_init_data_count);
+
+ if (module->native_symbol_list)
+ wasm_runtime_free(module->native_symbol_list);
+
+ if (module->import_tables)
+ destroy_import_tables(module->import_tables);
+
+ if (module->tables)
+ destroy_tables(module->tables);
+
+ if (module->table_init_data_list)
+ destroy_table_init_data_list(module->table_init_data_list,
+ module->table_init_data_count);
+
+ if (module->func_types)
+ destroy_func_types(module->func_types, module->func_type_count);
+
+ if (module->import_globals)
+ destroy_import_globals(module->import_globals);
+
+ if (module->globals)
+ destroy_globals(module->globals);
+
+ if (module->import_funcs)
+ destroy_import_funcs(module->import_funcs);
+
+ if (module->exports)
+ destroy_exports(module->exports);
+
+ if (module->func_type_indexes)
+ wasm_runtime_free(module->func_type_indexes);
+
+ if (module->func_ptrs)
+ wasm_runtime_free(module->func_ptrs);
+
+ if (module->const_str_set)
+ bh_hash_map_destroy(module->const_str_set);
+
+ if (module->code && !module->is_indirect_mode) {
+ /* The layout is: literal size + literal + code (with plt table) */
+ uint8 *mmap_addr = module->literal - sizeof(uint32);
+ uint32 total_size =
+ sizeof(uint32) + module->literal_size + module->code_size;
+ os_munmap(mmap_addr, total_size);
+ }
+
+#if defined(BH_PLATFORM_WINDOWS)
+ if (module->extra_plt_data) {
+ os_munmap(module->extra_plt_data, module->extra_plt_data_size);
+ }
+#endif
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ if (module->rtl_func_table) {
+ if (module->rtl_func_table_registered)
+ RtlDeleteFunctionTable(module->rtl_func_table);
+ wasm_runtime_free(module->rtl_func_table);
+ }
+#endif
+
+ if (module->data_sections)
+ destroy_object_data_sections(module->data_sections,
+ module->data_section_count);
+#if WASM_ENABLE_DEBUG_AOT != 0
+ jit_code_entry_destroy(module->elf_hdr);
+#endif
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ if (module->aux_func_indexes) {
+ wasm_runtime_free(module->aux_func_indexes);
+ }
+ if (module->aux_func_names) {
+ wasm_runtime_free((void *)module->aux_func_names);
+ }
+#endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ wasm_runtime_destroy_custom_sections(module->custom_section_list);
+#endif
+
+ wasm_runtime_free(module);
+}
+
+uint32
+aot_get_plt_table_size()
+{
+ return get_plt_table_size();
+}
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+const uint8 *
+aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len)
+{
+ WASMCustomSection *section = module->custom_section_list;
+
+ while (section) {
+ if (strcmp(section->name_addr, name) == 0) {
+ if (len) {
+ *len = section->content_len;
+ }
+ return section->content_addr;
+ }
+
+ section = section->next;
+ }
+
+ return NULL;
+}
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_reloc.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_reloc.h
new file mode 100644
index 000000000..9f5c2d57f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_reloc.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_RELOC_H_
+#define _AOT_RELOC_H_
+
+#include "aot_runtime.h"
+#include "aot_intrinsic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ const char *symbol_name;
+ void *symbol_addr;
+} SymbolMap;
+
+/* clang-format off */
+#define REG_SYM(symbol) { #symbol, (void *)symbol }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+#define REG_BULK_MEMORY_SYM() \
+ REG_SYM(aot_memory_init), \
+ REG_SYM(aot_data_drop),
+#else
+#define REG_BULK_MEMORY_SYM()
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#define REG_ATOMIC_WAIT_SYM() \
+ REG_SYM(wasm_runtime_atomic_wait), \
+ REG_SYM(wasm_runtime_atomic_notify),
+#else
+#define REG_ATOMIC_WAIT_SYM()
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+#define REG_REF_TYPES_SYM() \
+ REG_SYM(aot_drop_table_seg), \
+ REG_SYM(aot_table_init), \
+ REG_SYM(aot_table_copy), \
+ REG_SYM(aot_table_fill), \
+ REG_SYM(aot_table_grow),
+#else
+#define REG_REF_TYPES_SYM()
+#endif
+
+#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+#define REG_AOT_TRACE_SYM() \
+ REG_SYM(aot_alloc_frame), \
+ REG_SYM(aot_free_frame),
+#else
+#define REG_AOT_TRACE_SYM()
+#endif
+
+#define REG_INTRINSIC_SYM() \
+ REG_SYM(aot_intrinsic_fabs_f32), \
+ REG_SYM(aot_intrinsic_fabs_f64), \
+ REG_SYM(aot_intrinsic_floor_f32), \
+ REG_SYM(aot_intrinsic_floor_f64), \
+ REG_SYM(aot_intrinsic_ceil_f32), \
+ REG_SYM(aot_intrinsic_ceil_f64), \
+ REG_SYM(aot_intrinsic_trunc_f32), \
+ REG_SYM(aot_intrinsic_trunc_f64), \
+ REG_SYM(aot_intrinsic_rint_f32), \
+ REG_SYM(aot_intrinsic_rint_f64), \
+ REG_SYM(aot_intrinsic_sqrt_f32), \
+ REG_SYM(aot_intrinsic_sqrt_f64), \
+ REG_SYM(aot_intrinsic_copysign_f32), \
+ REG_SYM(aot_intrinsic_copysign_f64), \
+ REG_SYM(aot_intrinsic_fadd_f32), \
+ REG_SYM(aot_intrinsic_fadd_f64), \
+ REG_SYM(aot_intrinsic_fsub_f32), \
+ REG_SYM(aot_intrinsic_fsub_f64), \
+ REG_SYM(aot_intrinsic_fmul_f32), \
+ REG_SYM(aot_intrinsic_fmul_f64), \
+ REG_SYM(aot_intrinsic_fdiv_f32), \
+ REG_SYM(aot_intrinsic_fdiv_f64), \
+ REG_SYM(aot_intrinsic_fmin_f32), \
+ REG_SYM(aot_intrinsic_fmin_f64), \
+ REG_SYM(aot_intrinsic_fmax_f32), \
+ REG_SYM(aot_intrinsic_fmax_f64), \
+ REG_SYM(aot_intrinsic_clz_i32), \
+ REG_SYM(aot_intrinsic_clz_i64), \
+ REG_SYM(aot_intrinsic_ctz_i32), \
+ REG_SYM(aot_intrinsic_ctz_i64), \
+ REG_SYM(aot_intrinsic_popcnt_i32), \
+ REG_SYM(aot_intrinsic_popcnt_i64), \
+ REG_SYM(aot_intrinsic_i32_to_f32), \
+ REG_SYM(aot_intrinsic_u32_to_f32), \
+ REG_SYM(aot_intrinsic_i32_to_f64), \
+ REG_SYM(aot_intrinsic_u32_to_f64), \
+ REG_SYM(aot_intrinsic_i64_to_f32), \
+ REG_SYM(aot_intrinsic_u64_to_f32), \
+ REG_SYM(aot_intrinsic_i64_to_f64), \
+ REG_SYM(aot_intrinsic_u64_to_f64), \
+ REG_SYM(aot_intrinsic_f64_to_f32), \
+ REG_SYM(aot_intrinsic_f32_to_i32), \
+ REG_SYM(aot_intrinsic_f32_to_u32), \
+ REG_SYM(aot_intrinsic_f32_to_i64), \
+ REG_SYM(aot_intrinsic_f32_to_u64), \
+ REG_SYM(aot_intrinsic_f64_to_i32), \
+ REG_SYM(aot_intrinsic_f64_to_u32), \
+ REG_SYM(aot_intrinsic_f64_to_i64), \
+ REG_SYM(aot_intrinsic_f64_to_u64), \
+ REG_SYM(aot_intrinsic_f32_to_f64), \
+ REG_SYM(aot_intrinsic_f32_cmp), \
+ REG_SYM(aot_intrinsic_f64_cmp), \
+ REG_SYM(aot_intrinsic_i64_div_s), \
+ REG_SYM(aot_intrinsic_i64_div_u), \
+ REG_SYM(aot_intrinsic_i64_rem_s), \
+ REG_SYM(aot_intrinsic_i64_rem_u), \
+ REG_SYM(aot_intrinsic_i64_bit_or), \
+ REG_SYM(aot_intrinsic_i64_bit_and), \
+ REG_SYM(aot_intrinsic_i32_div_s), \
+ REG_SYM(aot_intrinsic_i32_div_u), \
+ REG_SYM(aot_intrinsic_i32_rem_s), \
+ REG_SYM(aot_intrinsic_i32_rem_u), \
+
+#define REG_COMMON_SYMBOLS \
+ REG_SYM(aot_set_exception_with_id), \
+ REG_SYM(aot_invoke_native), \
+ REG_SYM(aot_call_indirect), \
+ REG_SYM(aot_enlarge_memory), \
+ REG_SYM(aot_set_exception), \
+ REG_SYM(aot_check_app_addr_and_convert),\
+ { "memset", (void*)aot_memset }, \
+ { "memmove", (void*)aot_memmove }, \
+ { "memcpy", (void*)aot_memmove }, \
+ { "sqrt", (void*)aot_sqrt }, \
+ { "sqrtf", (void*)aot_sqrtf }, \
+ 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), \
+ REG_BULK_MEMORY_SYM() \
+ REG_ATOMIC_WAIT_SYM() \
+ REG_REF_TYPES_SYM() \
+ REG_AOT_TRACE_SYM() \
+ REG_INTRINSIC_SYM() \
+
+#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)
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num);
+
+uint32
+get_plt_table_size();
+
+void
+init_plt_table(uint8 *plt);
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size);
+
+bool
+apply_relocation(AOTModule *module,
+ uint8 *target_section_addr, uint32 target_section_size,
+ uint64 reloc_offset, int64 reloc_addend,
+ uint32 reloc_type, void *symbol_addr, int32 symbol_index,
+ char *error_buf, uint32 error_buf_size);
+/* clang-format off */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _AOT_RELOC_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.c
new file mode 100644
index 000000000..b5c406b96
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.c
@@ -0,0 +1,2836 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_runtime.h"
+#include "bh_log.h"
+#include "mem_alloc.h"
+#include "../common/wasm_runtime_common.h"
+#include "../interpreter/wasm_runtime.h"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "../common/wasm_shared_memory.h"
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#endif
+
+/*
+ * Note: These offsets need to match the values hardcoded in
+ * AoT compilation code: aot_create_func_context, check_suspend_flags.
+ */
+
+bh_static_assert(offsetof(WASMExecEnv, module_inst) == 2 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, argv_buf) == 3 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, native_stack_boundary)
+ == 4 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, suspend_flags) == 5 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, aux_stack_boundary)
+ == 6 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
+ == 7 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, native_stack_top_min)
+ == 9 * sizeof(uintptr_t));
+
+bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64));
+bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64));
+bh_static_assert(offsetof(AOTModuleInstance, func_type_indexes)
+ == 6 * sizeof(uint64));
+bh_static_assert(offsetof(AOTModuleInstance, cur_exception)
+ == 13 * sizeof(uint64));
+bh_static_assert(offsetof(AOTModuleInstance, global_table_data)
+ == 13 * sizeof(uint64) + 128 + 11 * sizeof(uint64));
+
+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, "AOT module instantiate failed: %s",
+ string);
+ }
+}
+
+static void
+set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
+{
+ va_list args;
+ char buf[128];
+
+ if (error_buf != NULL) {
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ snprintf(error_buf, error_buf_size, "AOT module instantiate failed: %s",
+ buf);
+ }
+}
+
+static void *
+runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+static bool
+check_global_init_expr(const AOTModule *module, uint32 global_index,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (global_index >= module->import_global_count + module->global_count) {
+ set_error_buf_v(error_buf, error_buf_size, "unknown global %d",
+ global_index);
+ return false;
+ }
+
+ /**
+ * Currently, constant expressions occurring as initializers of
+ * globals are further constrained in that contained global.get
+ * instructions are only allowed to refer to imported globals.
+ *
+ * And initializer expression cannot reference a mutable global.
+ */
+ if (global_index >= module->import_global_count
+ || module->import_globals->is_mutable) {
+ set_error_buf(error_buf, error_buf_size,
+ "constant expression required");
+ return false;
+ }
+
+ return true;
+}
+
+static void
+init_global_data(uint8 *global_data, uint8 type, WASMValue *initial_value)
+{
+ switch (type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ *(int32 *)global_data = initial_value->i32;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ bh_memcpy_s(global_data, sizeof(int64), &initial_value->i64,
+ sizeof(int64));
+ break;
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ bh_memcpy_s(global_data, sizeof(V128), &initial_value->v128,
+ sizeof(V128));
+ break;
+#endif
+ default:
+ bh_assert(0);
+ }
+}
+
+static bool
+global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint32 i;
+ InitializerExpression *init_expr;
+ uint8 *p = module_inst->global_data;
+ AOTImportGlobal *import_global = module->import_globals;
+ AOTGlobal *global = module->globals;
+
+ /* Initialize import global data */
+ for (i = 0; i < module->import_global_count; i++, import_global++) {
+ bh_assert(import_global->data_offset
+ == (uint32)(p - module_inst->global_data));
+ init_global_data(p, import_global->type,
+ &import_global->global_data_linked);
+ p += import_global->size;
+ }
+
+ /* Initialize defined global data */
+ for (i = 0; i < module->global_count; i++, global++) {
+ bh_assert(global->data_offset
+ == (uint32)(p - module_inst->global_data));
+ init_expr = &global->init_expr;
+ switch (init_expr->init_expr_type) {
+ case INIT_EXPR_TYPE_GET_GLOBAL:
+ {
+ if (!check_global_init_expr(module, init_expr->u.global_index,
+ error_buf, error_buf_size)) {
+ return false;
+ }
+ init_global_data(
+ p, global->type,
+ &module->import_globals[init_expr->u.global_index]
+ .global_data_linked);
+ break;
+ }
+#if WASM_ENABLE_REF_TYPES != 0
+ case INIT_EXPR_TYPE_REFNULL_CONST:
+ {
+ *(uint32 *)p = NULL_REF;
+ break;
+ }
+#endif
+ default:
+ {
+ init_global_data(p, global->type, &init_expr->u);
+ break;
+ }
+ }
+ p += global->size;
+ }
+
+ bh_assert(module_inst->global_data_size
+ == (uint32)(p - module_inst->global_data));
+ return true;
+}
+
+static bool
+tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
+ AOTTableInstance *first_tbl_inst, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 i, global_index, global_data_offset, base_offset, length;
+ uint64 total_size;
+ AOTTableInitData *table_seg;
+ AOTTableInstance *tbl_inst = first_tbl_inst;
+
+ total_size = (uint64)sizeof(WASMTableInstance *) * module_inst->table_count;
+ if (total_size > 0
+ && !(module_inst->tables =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /*
+ * treat import table like a local one until we enable module linking
+ * in AOT mode
+ */
+ for (i = 0; i != module_inst->table_count; ++i) {
+ if (i < module->import_table_count) {
+ AOTImportTable *import_table = module->import_tables + i;
+ tbl_inst->cur_size = import_table->table_init_size;
+ tbl_inst->max_size =
+ aot_get_imp_tbl_data_slots(import_table, false);
+ }
+ else {
+ AOTTable *table = module->tables + (i - module->import_table_count);
+ tbl_inst->cur_size = table->table_init_size;
+ tbl_inst->max_size = aot_get_tbl_data_slots(table, false);
+ }
+
+ /* Set all elements to -1 to mark them as uninitialized elements */
+ memset(tbl_inst->elems, 0xff, sizeof(uint32) * tbl_inst->max_size);
+
+ module_inst->tables[i] = tbl_inst;
+ tbl_inst = (AOTTableInstance *)((uint8 *)tbl_inst
+ + offsetof(AOTTableInstance, elems)
+ + sizeof(uint32) * tbl_inst->max_size);
+ }
+
+ /* fill table with element segment content */
+ for (i = 0; i < module->table_init_data_count; i++) {
+ table_seg = module->table_init_data_list[i];
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!wasm_elem_is_active(table_seg->mode))
+ continue;
+#endif
+
+ bh_assert(table_seg->table_index < module_inst->table_count);
+
+ tbl_inst = module_inst->tables[table_seg->table_index];
+ bh_assert(tbl_inst);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ bh_assert(
+ table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
+ || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
+ || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
+ || table_seg->offset.init_expr_type
+ == INIT_EXPR_TYPE_REFNULL_CONST);
+#else
+ bh_assert(table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
+ || table_seg->offset.init_expr_type
+ == INIT_EXPR_TYPE_GET_GLOBAL);
+#endif
+
+ /* 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;
+
+ if (!check_global_init_expr(module, global_index, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+
+ if (global_index < module->import_global_count)
+ global_data_offset =
+ module->import_globals[global_index].data_offset;
+ else
+ global_data_offset =
+ module->globals[global_index - module->import_global_count]
+ .data_offset;
+
+ base_offset =
+ *(uint32 *)(module_inst->global_data + global_data_offset);
+ }
+ else
+ base_offset = (uint32)table_seg->offset.u.i32;
+
+ /* Copy table data */
+ /* base_offset only since length might negative */
+ if (base_offset > tbl_inst->cur_size) {
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds table access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "elements segment does not fit");
+#endif
+ return false;
+ }
+
+ /* base_offset + length(could be zero) */
+ length = table_seg->func_index_count;
+ if (base_offset + length > tbl_inst->cur_size) {
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds table access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "elements segment does not fit");
+#endif
+ return false;
+ }
+
+ /**
+ * Check function index in the current module inst for now.
+ * will check the linked table inst owner in future
+ */
+ bh_memcpy_s(tbl_inst->elems + base_offset,
+ (tbl_inst->max_size - base_offset) * sizeof(uint32),
+ table_seg->func_indexes, length * sizeof(uint32));
+ }
+
+ return true;
+}
+
+static void
+memories_deinstantiate(AOTModuleInstance *module_inst)
+{
+ uint32 i;
+ AOTMemoryInstance *memory_inst;
+
+ for (i = 0; i < module_inst->memory_count; i++) {
+ memory_inst = module_inst->memories[i];
+ if (memory_inst) {
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (memory_inst->is_shared) {
+ int32 ref_count = shared_memory_dec_reference(
+ (WASMModuleCommon *)module_inst->module);
+ bh_assert(ref_count >= 0);
+
+ /* if the reference count is not zero,
+ don't free the memory */
+ if (ref_count > 0)
+ continue;
+ }
+#endif
+ if (memory_inst->heap_handle) {
+ mem_allocator_destroy(memory_inst->heap_handle);
+ wasm_runtime_free(memory_inst->heap_handle);
+ }
+
+ if (memory_inst->memory_data) {
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ wasm_runtime_free(memory_inst->memory_data);
+#else
+#ifdef BH_PLATFORM_WINDOWS
+ os_mem_decommit(memory_inst->memory_data,
+ memory_inst->num_bytes_per_page
+ * memory_inst->cur_page_count);
+#endif
+ os_munmap(memory_inst->memory_data, 8 * (uint64)BH_GB);
+#endif
+ }
+ }
+ }
+ wasm_runtime_free(module_inst->memories);
+}
+
+static AOTMemoryInstance *
+memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
+ AOTMemoryInstance *memory_inst, AOTMemory *memory,
+ uint32 heap_size, char *error_buf, uint32 error_buf_size)
+{
+ void *heap_handle;
+ uint32 num_bytes_per_page = memory->num_bytes_per_page;
+ uint32 init_page_count = memory->mem_init_page_count;
+ uint32 max_page_count = memory->mem_max_page_count;
+ uint32 inc_page_count, aux_heap_base, global_idx;
+ uint32 bytes_of_last_page, bytes_to_page_end;
+ uint32 heap_offset = num_bytes_per_page * init_page_count;
+ uint64 total_size;
+ uint8 *p = NULL, *global_addr;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ uint8 *mapped_mem;
+ uint64 map_size = 8 * (uint64)BH_GB;
+ uint64 page_size = os_getpagesize();
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ bool is_shared_memory = memory->memory_flags & 0x02 ? true : false;
+
+ /* Shared memory */
+ if (is_shared_memory) {
+ AOTMemoryInstance *shared_memory_instance;
+ WASMSharedMemNode *node =
+ wasm_module_get_shared_memory((WASMModuleCommon *)module);
+ /* If the memory of this module has been instantiated,
+ return the memory instance directly */
+ if (node) {
+ uint32 ref_count;
+ ref_count = shared_memory_inc_reference((WASMModuleCommon *)module);
+ bh_assert(ref_count > 0);
+ shared_memory_instance =
+ (AOTMemoryInstance *)shared_memory_get_memory_inst(node);
+ bh_assert(shared_memory_instance);
+
+ (void)ref_count;
+ return shared_memory_instance;
+ }
+ }
+#endif
+
+ if (heap_size > 0 && module->malloc_func_index != (uint32)-1
+ && module->free_func_index != (uint32)-1) {
+ /* Disable app heap, use malloc/free function exported
+ by wasm app to allocate/free memory instead */
+ heap_size = 0;
+ }
+
+ if (init_page_count == max_page_count && init_page_count == 1) {
+ /* If only one page and at most one page, we just append
+ the app heap to the end of linear memory, enlarge the
+ num_bytes_per_page, and don't change the page count */
+ heap_offset = num_bytes_per_page;
+ num_bytes_per_page += heap_size;
+ if (num_bytes_per_page < heap_size) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to insert app heap into linear memory, "
+ "try using `--heap_size=0` option");
+ return NULL;
+ }
+ }
+ else if (heap_size > 0) {
+ if (init_page_count == max_page_count && init_page_count == 0) {
+ /* If the memory data size is always 0, we resize it to
+ one page for app heap */
+ num_bytes_per_page = heap_size;
+ heap_offset = 0;
+ inc_page_count = 1;
+ }
+ else if (module->aux_heap_base_global_index != (uint32)-1
+ && module->aux_heap_base
+ < num_bytes_per_page * init_page_count) {
+ /* Insert app heap before __heap_base */
+ aux_heap_base = module->aux_heap_base;
+ bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+ if (bytes_of_last_page == 0)
+ bytes_of_last_page = num_bytes_per_page;
+ bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
+ inc_page_count =
+ (heap_size - bytes_to_page_end + num_bytes_per_page - 1)
+ / num_bytes_per_page;
+ heap_offset = aux_heap_base;
+ aux_heap_base += heap_size;
+
+ bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+ if (bytes_of_last_page == 0)
+ bytes_of_last_page = num_bytes_per_page;
+ bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
+ if (bytes_to_page_end < 1 * BH_KB) {
+ aux_heap_base += 1 * BH_KB;
+ inc_page_count++;
+ }
+
+ /* Adjust __heap_base global value */
+ global_idx = module->aux_heap_base_global_index
+ - module->import_global_count;
+ global_addr = module_inst->global_data
+ + module->globals[global_idx].data_offset;
+ *(uint32 *)global_addr = aux_heap_base;
+ LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base);
+ }
+ else {
+ /* Insert app heap before new page */
+ inc_page_count =
+ (heap_size + num_bytes_per_page - 1) / num_bytes_per_page;
+ heap_offset = num_bytes_per_page * init_page_count;
+ heap_size = num_bytes_per_page * inc_page_count;
+ if (heap_size > 0)
+ heap_size -= 1 * BH_KB;
+ }
+ init_page_count += inc_page_count;
+ max_page_count += inc_page_count;
+ if (init_page_count > DEFAULT_MAX_PAGES) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to insert app heap into linear memory, "
+ "try using `--heap_size=0` option");
+ return NULL;
+ }
+ else if (init_page_count == DEFAULT_MAX_PAGES) {
+ num_bytes_per_page = UINT32_MAX;
+ init_page_count = max_page_count = 1;
+ }
+ if (max_page_count > DEFAULT_MAX_PAGES)
+ max_page_count = DEFAULT_MAX_PAGES;
+ }
+
+ LOG_VERBOSE("Memory instantiate:");
+ LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u",
+ num_bytes_per_page, init_page_count, max_page_count);
+ LOG_VERBOSE(" data offset: %u, stack size: %d", module->aux_data_end,
+ module->aux_stack_size);
+ LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size);
+
+ total_size = (uint64)num_bytes_per_page * init_page_count;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (is_shared_memory) {
+ /* Allocate max page for shared memory */
+ total_size = (uint64)num_bytes_per_page * max_page_count;
+ }
+#endif
+ bh_assert(total_size <= UINT32_MAX);
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ /* Allocate memory */
+ if (total_size > 0
+ && !(p = runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+#else
+ total_size = (total_size + page_size - 1) & ~(page_size - 1);
+
+ /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G:
+ * ea = i + memarg.offset
+ * both i and memarg.offset are u32 in range 0 to 4G
+ * so the range of ea is 0 to 8G
+ */
+ if (!(p = mapped_mem =
+ os_mmap(NULL, map_size, MMAP_PROT_NONE, MMAP_MAP_NONE))) {
+ set_error_buf(error_buf, error_buf_size, "mmap memory failed");
+ return NULL;
+ }
+
+#ifdef BH_PLATFORM_WINDOWS
+ if (!os_mem_commit(p, total_size, MMAP_PROT_READ | MMAP_PROT_WRITE)) {
+ set_error_buf(error_buf, error_buf_size, "commit memory failed");
+ os_munmap(mapped_mem, map_size);
+ return NULL;
+ }
+#endif
+
+ if (os_mprotect(p, total_size, MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) {
+ set_error_buf(error_buf, error_buf_size, "mprotect memory failed");
+#ifdef BH_PLATFORM_WINDOWS
+ os_mem_decommit(p, total_size);
+#endif
+ os_munmap(mapped_mem, map_size);
+ return NULL;
+ }
+ /* Newly allocated pages are filled with zero by the OS, we don't fill it
+ * again here */
+#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
+
+ if (total_size > UINT32_MAX)
+ total_size = UINT32_MAX;
+
+ memory_inst->module_type = Wasm_Module_AoT;
+ memory_inst->num_bytes_per_page = num_bytes_per_page;
+ memory_inst->cur_page_count = init_page_count;
+ memory_inst->max_page_count = max_page_count;
+ memory_inst->memory_data_size = (uint32)total_size;
+
+ /* Init memory info */
+ memory_inst->memory_data = p;
+ memory_inst->memory_data_end = p + (uint32)total_size;
+
+ /* Initialize heap info */
+ memory_inst->heap_data = p + heap_offset;
+ memory_inst->heap_data_end = p + heap_offset + heap_size;
+ if (heap_size > 0) {
+ uint32 heap_struct_size = mem_allocator_get_heap_struct_size();
+
+ if (!(heap_handle = runtime_malloc((uint64)heap_struct_size, error_buf,
+ error_buf_size))) {
+ goto fail1;
+ }
+
+ memory_inst->heap_handle = heap_handle;
+
+ if (!mem_allocator_create_with_struct_and_pool(
+ heap_handle, heap_struct_size, memory_inst->heap_data,
+ heap_size)) {
+ set_error_buf(error_buf, error_buf_size, "init app heap failed");
+ goto fail2;
+ }
+ }
+
+ if (total_size > 0) {
+#if UINTPTR_MAX == UINT64_MAX
+ memory_inst->mem_bound_check_1byte.u64 = total_size - 1;
+ memory_inst->mem_bound_check_2bytes.u64 = total_size - 2;
+ memory_inst->mem_bound_check_4bytes.u64 = total_size - 4;
+ memory_inst->mem_bound_check_8bytes.u64 = total_size - 8;
+ memory_inst->mem_bound_check_16bytes.u64 = total_size - 16;
+#else
+ memory_inst->mem_bound_check_1byte.u32[0] = (uint32)total_size - 1;
+ memory_inst->mem_bound_check_2bytes.u32[0] = (uint32)total_size - 2;
+ memory_inst->mem_bound_check_4bytes.u32[0] = (uint32)total_size - 4;
+ memory_inst->mem_bound_check_8bytes.u32[0] = (uint32)total_size - 8;
+ memory_inst->mem_bound_check_16bytes.u32[0] = (uint32)total_size - 16;
+#endif
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (is_shared_memory) {
+ memory_inst->is_shared = true;
+ if (!shared_memory_set_memory_inst(
+ (WASMModuleCommon *)module,
+ (WASMMemoryInstanceCommon *)memory_inst)) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ goto fail3;
+ }
+ }
+#endif
+
+ return memory_inst;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+fail3:
+ if (heap_size > 0)
+ mem_allocator_destroy(memory_inst->heap_handle);
+#endif
+fail2:
+ if (heap_size > 0)
+ wasm_runtime_free(memory_inst->heap_handle);
+fail1:
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ if (memory_inst->memory_data)
+ wasm_runtime_free(memory_inst->memory_data);
+#else
+#ifdef BH_PLATFORM_WINDOWS
+ if (memory_inst->memory_data)
+ os_mem_decommit(p, total_size);
+#endif
+ os_munmap(mapped_mem, map_size);
+#endif
+ memory_inst->memory_data = NULL;
+ return NULL;
+}
+
+static AOTMemoryInstance *
+aot_get_default_memory(AOTModuleInstance *module_inst)
+{
+ if (module_inst->memories)
+ return module_inst->memories[0];
+ else
+ return NULL;
+}
+
+static bool
+memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
+ uint32 heap_size, char *error_buf, uint32 error_buf_size)
+{
+ uint32 global_index, global_data_offset, base_offset, length;
+ uint32 i, memory_count = module->memory_count;
+ AOTMemoryInstance *memories, *memory_inst;
+ AOTMemInitData *data_seg;
+ uint64 total_size;
+
+ module_inst->memory_count = memory_count;
+ total_size = sizeof(AOTMemoryInstance *) * (uint64)memory_count;
+ if (!(module_inst->memories =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ memories = module_inst->global_table_data.memory_instances;
+ for (i = 0; i < memory_count; i++, memories++) {
+ memory_inst = memory_instantiate(module_inst, module, memories,
+ &module->memories[i], heap_size,
+ error_buf, error_buf_size);
+ if (!memory_inst) {
+ return false;
+ }
+
+ module_inst->memories[i] = memory_inst;
+ }
+
+ /* Get default memory instance */
+ memory_inst = aot_get_default_memory(module_inst);
+ if (!memory_inst) {
+ /* Ignore setting memory init data if no memory inst is created */
+ return true;
+ }
+
+ for (i = 0; i < module->mem_init_data_count; i++) {
+ data_seg = module->mem_init_data_list[i];
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if (data_seg->is_passive)
+ continue;
+#endif
+
+ 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;
+
+ if (!check_global_init_expr(module, global_index, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+
+ if (global_index < module->import_global_count)
+ global_data_offset =
+ module->import_globals[global_index].data_offset;
+ else
+ global_data_offset =
+ module->globals[global_index - module->import_global_count]
+ .data_offset;
+
+ base_offset =
+ *(uint32 *)(module_inst->global_data + global_data_offset);
+ }
+ else {
+ base_offset = (uint32)data_seg->offset.u.i32;
+ }
+
+ /* Copy memory data */
+ bh_assert(memory_inst->memory_data
+ || memory_inst->memory_data_size == 0);
+
+ /* Check memory data */
+ /* check offset since length might negative */
+ if (base_offset > memory_inst->memory_data_size) {
+ LOG_DEBUG("base_offset(%d) > memory_data_size(%d)", base_offset,
+ memory_inst->memory_data_size);
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds memory access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "data segment does not fit");
+#endif
+ return false;
+ }
+
+ /* check offset + length(could be zero) */
+ length = data_seg->byte_count;
+ if (base_offset + length > memory_inst->memory_data_size) {
+ LOG_DEBUG("base_offset(%d) + length(%d) > memory_data_size(%d)",
+ base_offset, length, memory_inst->memory_data_size);
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds memory access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "data segment does not fit");
+#endif
+ return false;
+ }
+
+ if (memory_inst->memory_data) {
+ bh_memcpy_s((uint8 *)memory_inst->memory_data + base_offset,
+ memory_inst->memory_data_size - 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 *);
+
+ if (module->import_func_count + module->func_count == 0)
+ return true;
+
+ /* Allocate memory */
+ if (!(module_inst->func_ptrs =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Set import function pointers */
+ func_ptrs = (void **)module_inst->func_ptrs;
+ for (i = 0; i < module->import_func_count; i++, func_ptrs++) {
+ *func_ptrs = (void *)module->import_funcs[i].func_ptr_linked;
+ if (!*func_ptrs) {
+ const char *module_name = module->import_funcs[i].module_name;
+ const char *field_name = module->import_funcs[i].func_name;
+ LOG_WARNING("warning: failed to link import function (%s, %s)",
+ module_name, field_name);
+ }
+ }
+
+ /* Set defined function pointers */
+ bh_memcpy_s(func_ptrs, sizeof(void *) * module->func_count,
+ module->func_ptrs, sizeof(void *) * module->func_count);
+ 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);
+
+ if (module->import_func_count + module->func_count == 0)
+ return true;
+
+ /* Allocate memory */
+ if (!(module_inst->func_type_indexes =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Set import function type indexes */
+ func_type_index = module_inst->func_type_indexes;
+ for (i = 0; i < module->import_func_count; i++, func_type_index++)
+ *func_type_index = module->import_funcs[i].func_type_index;
+
+ bh_memcpy_s(func_type_index, sizeof(uint32) * module->func_count,
+ module->func_type_indexes, sizeof(uint32) * module->func_count);
+ return true;
+}
+
+static bool
+create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ AOTExport *exports = module->exports;
+ AOTFunctionInstance *export_func;
+ uint64 size;
+ uint32 i, func_index, ftype_index;
+
+ if (module_inst->export_func_count > 0) {
+ /* Allocate memory */
+ size = sizeof(AOTFunctionInstance)
+ * (uint64)module_inst->export_func_count;
+ if (!(export_func = runtime_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+ module_inst->export_functions = (void *)export_func;
+
+ for (i = 0; i < module->export_count; i++) {
+ if (exports[i].kind == EXPORT_KIND_FUNC) {
+ export_func->func_name = exports[i].name;
+ export_func->func_index = exports[i].index;
+ if (export_func->func_index < module->import_func_count) {
+ export_func->is_import_func = true;
+ export_func->u.func_import =
+ &module->import_funcs[export_func->func_index];
+ }
+ else {
+ export_func->is_import_func = false;
+ func_index =
+ export_func->func_index - module->import_func_count;
+ ftype_index = module->func_type_indexes[func_index];
+ export_func->u.func.func_type =
+ module->func_types[ftype_index];
+ export_func->u.func.func_ptr =
+ module->func_ptrs[func_index];
+ }
+ export_func++;
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool
+create_exports(AOTModuleInstance *module_inst, AOTModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ AOTExport *exports = module->exports;
+ uint32 i;
+
+ for (i = 0; i < module->export_count; i++) {
+ switch (exports[i].kind) {
+ case EXPORT_KIND_FUNC:
+ module_inst->export_func_count++;
+ break;
+ case EXPORT_KIND_GLOBAL:
+ module_inst->export_global_count++;
+ break;
+ case EXPORT_KIND_TABLE:
+ module_inst->export_table_count++;
+ break;
+ case EXPORT_KIND_MEMORY:
+ module_inst->export_memory_count++;
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return create_export_funcs(module_inst, module, error_buf, error_buf_size);
+}
+
+static AOTFunctionInstance *
+lookup_post_instantiate_func(AOTModuleInstance *module_inst,
+ const char *func_name)
+{
+ AOTFunctionInstance *func;
+ AOTFuncType *func_type;
+
+ if (!(func = aot_lookup_function(module_inst, func_name, NULL)))
+ /* Not found */
+ return NULL;
+
+ func_type = func->u.func.func_type;
+ if (!(func_type->param_count == 0 && func_type->result_count == 0))
+ /* Not a valid function type, ignore it */
+ return NULL;
+
+ return func;
+}
+
+static bool
+execute_post_instantiate_functions(AOTModuleInstance *module_inst,
+ bool is_sub_inst, WASMExecEnv *exec_env_main)
+{
+ AOTModule *module = (AOTModule *)module_inst->module;
+ AOTFunctionInstance *initialize_func = NULL;
+ AOTFunctionInstance *post_inst_func = NULL;
+ AOTFunctionInstance *call_ctors_func = NULL;
+ WASMModuleInstanceCommon *module_inst_main = NULL;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+#endif
+ WASMExecEnv *exec_env = NULL, *exec_env_created = NULL;
+ bool ret = false;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ /*
+ * WASI reactor instances may assume that _initialize will be called by
+ * the environment at most once, and that none of their other exports
+ * are accessed before that call.
+ */
+ if (!is_sub_inst && module->import_wasi_api) {
+ initialize_func =
+ lookup_post_instantiate_func(module_inst, "_initialize");
+ }
+#endif
+
+ /* Execute possible "__post_instantiate" function if wasm app is
+ compiled by emsdk's early version */
+ if (!is_sub_inst) {
+ post_inst_func =
+ lookup_post_instantiate_func(module_inst, "__post_instantiate");
+ }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ /* Only execute the memory init function for main instance since
+ the data segments will be dropped once initialized */
+ if (!is_sub_inst
+#if WASM_ENABLE_LIBC_WASI != 0
+ && !module->import_wasi_api
+#endif
+ ) {
+ call_ctors_func =
+ lookup_post_instantiate_func(module_inst, "__wasm_call_ctors");
+ }
+#endif
+
+ if (!module->start_function && !initialize_func && !post_inst_func
+ && !call_ctors_func) {
+ /* No post instantiation functions to call */
+ return true;
+ }
+
+ if (is_sub_inst) {
+ bh_assert(exec_env_main);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ bh_assert(exec_env_tls == exec_env_main);
+ (void)exec_env_tls;
+#endif
+ exec_env = exec_env_main;
+
+ /* Temporarily replace parent exec_env's module inst to current
+ module inst to avoid checking failure when calling the
+ wasm functions, and ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_main = exec_env_main->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ else {
+ /* Try using the existing exec_env */
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = exec_env_tls;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env)
+ exec_env = wasm_clusters_search_exec_env(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+ if (!exec_env) {
+ if (!(exec_env = exec_env_created = wasm_exec_env_create(
+ (WASMModuleInstanceCommon *)module_inst,
+ module_inst->default_wasm_stack_size))) {
+ aot_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+ else {
+ /* Temporarily replace exec_env's module inst with current
+ module inst to ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_main = exec_env->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ }
+
+ /* Execute start function for both main insance and sub instance */
+ if (module->start_function) {
+ AOTFunctionInstance start_func = { 0 };
+ uint32 func_type_idx;
+
+ start_func.func_name = "";
+ start_func.func_index = module->start_func_index;
+ start_func.is_import_func = false;
+ func_type_idx = module->func_type_indexes[module->start_func_index
+ - module->import_func_count];
+ start_func.u.func.func_type = module->func_types[func_type_idx];
+ start_func.u.func.func_ptr = module->start_function;
+ if (!aot_call_function(exec_env, &start_func, 0, NULL)) {
+ goto fail;
+ }
+ }
+
+ if (initialize_func
+ && !aot_call_function(exec_env, initialize_func, 0, NULL)) {
+ goto fail;
+ }
+
+ if (post_inst_func
+ && !aot_call_function(exec_env, post_inst_func, 0, NULL)) {
+ goto fail;
+ }
+
+ if (call_ctors_func
+ && !aot_call_function(exec_env, call_ctors_func, 0, NULL)) {
+ goto fail;
+ }
+
+ ret = true;
+
+fail:
+ if (is_sub_inst) {
+ /* Restore the parent exec_env's module inst */
+ exec_env_main->module_inst = module_inst_main;
+ }
+ else {
+ if (module_inst_main)
+ /* Restore the existing exec_env's module inst */
+ exec_env->module_inst = module_inst_main;
+ if (exec_env_created)
+ wasm_exec_env_destroy(exec_env_created);
+ }
+
+ return ret;
+}
+
+static bool
+check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size)
+{
+ uint32 i;
+
+ /* init_func_ptrs() will go through import functions */
+
+ for (i = 0; i < module->import_global_count; i++) {
+ AOTImportGlobal *global = module->import_globals + i;
+ if (!global->is_linked) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "failed to link import global (%s, %s)",
+ global->module_name, global->global_name);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+AOTModuleInstance *
+aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
+ uint32 stack_size, uint32 heap_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ AOTModuleInstance *module_inst;
+ const uint32 module_inst_struct_size =
+ offsetof(AOTModuleInstance, global_table_data.bytes);
+ const uint64 module_inst_mem_inst_size =
+ (uint64)module->memory_count * sizeof(AOTMemoryInstance);
+ uint64 total_size, table_size = 0;
+ uint8 *p;
+ uint32 i, extra_info_offset;
+
+ /* Check heap size */
+ heap_size = align_uint(heap_size, 8);
+ if (heap_size > APP_HEAP_SIZE_MAX)
+ heap_size = APP_HEAP_SIZE_MAX;
+
+ total_size = (uint64)module_inst_struct_size + module_inst_mem_inst_size
+ + module->global_data_size;
+
+ /*
+ * calculate size of table data
+ */
+ for (i = 0; i != module->import_table_count; ++i) {
+ table_size += offsetof(AOTTableInstance, elems);
+ table_size += (uint64)sizeof(uint32)
+ * (uint64)aot_get_imp_tbl_data_slots(
+ module->import_tables + i, false);
+ }
+
+ for (i = 0; i != module->table_count; ++i) {
+ table_size += offsetof(AOTTableInstance, elems);
+ table_size +=
+ (uint64)sizeof(uint32)
+ * (uint64)aot_get_tbl_data_slots(module->tables + i, false);
+ }
+ total_size += table_size;
+
+ /* The offset of AOTModuleInstanceExtra, make it 8-byte aligned */
+ total_size = (total_size + 7LL) & ~7LL;
+ extra_info_offset = (uint32)total_size;
+ total_size += sizeof(AOTModuleInstanceExtra);
+
+ /* Allocate module instance, global data, table data and heap data */
+ if (!(module_inst =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ module_inst->module_type = Wasm_Module_AoT;
+ module_inst->module = (void *)module;
+ module_inst->e =
+ (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
+
+ /* Initialize global info */
+ p = (uint8 *)module_inst + module_inst_struct_size
+ + module_inst_mem_inst_size;
+ module_inst->global_data = p;
+ module_inst->global_data_size = module->global_data_size;
+ if (!global_instantiate(module_inst, module, error_buf, error_buf_size))
+ goto fail;
+
+ /* Initialize table info */
+ p += module->global_data_size;
+ module_inst->table_count = module->table_count + module->import_table_count;
+ if (!tables_instantiate(module_inst, module, (AOTTableInstance *)p,
+ error_buf, error_buf_size))
+ goto fail;
+
+ /* Initialize memory space */
+ if (!memories_instantiate(module_inst, module, heap_size, 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 (!check_linked_symbol(module, error_buf, error_buf_size))
+ goto fail;
+
+ if (!create_exports(module_inst, module, error_buf, error_buf_size))
+ goto fail;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ if (!is_sub_inst) {
+ 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.addr_pool, module->wasi_args.addr_count,
+ module->wasi_args.ns_lookup_pool,
+ module->wasi_args.ns_lookup_count, module->wasi_args.argv,
+ module->wasi_args.argc, module->wasi_args.stdio[0],
+ module->wasi_args.stdio[1], module->wasi_args.stdio[2],
+ error_buf, error_buf_size))
+ goto fail;
+ }
+#endif
+
+#if WASM_ENABLE_WASI_NN != 0
+ if (!is_sub_inst) {
+ if (!(((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx =
+ wasi_nn_initialize())) {
+ set_error_buf(error_buf, error_buf_size,
+ "wasi nn initialization failed");
+ goto fail;
+ }
+ }
+#endif
+
+ /* Initialize the thread related data */
+ if (stack_size == 0)
+ stack_size = DEFAULT_WASM_STACK_SIZE;
+#if WASM_ENABLE_SPEC_TEST != 0
+ if (stack_size < 48 * 1024)
+ stack_size = 48 * 1024;
+#endif
+ module_inst->default_wasm_stack_size = stack_size;
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ total_size = (uint64)sizeof(AOTFuncPerfProfInfo)
+ * (module->import_func_count + module->func_count);
+ if (!(module_inst->func_perf_profilings =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ goto fail;
+ }
+#endif
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (!(module_inst->frames =
+ runtime_malloc(sizeof(Vector), error_buf, error_buf_size))) {
+ goto fail;
+ }
+#endif
+
+ if (!execute_post_instantiate_functions(module_inst, is_sub_inst,
+ exec_env_main)) {
+ set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
+ goto fail;
+ }
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ wasm_runtime_dump_module_inst_mem_consumption(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+
+ return module_inst;
+
+fail:
+ aot_deinstantiate(module_inst, is_sub_inst);
+ return NULL;
+}
+
+void
+aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
+{
+ if (module_inst->exec_env_singleton) {
+ /* wasm_exec_env_destroy will call
+ wasm_cluster_wait_for_all_except_self to wait for other
+ threads, so as to destroy their exec_envs and module
+ instances first, and avoid accessing the shared resources
+ of current module instance after it is deinstantiated. */
+ wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
+ }
+
+#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. */
+ /* Only destroy wasi ctx in the main module instance */
+ if (!is_sub_inst)
+ wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
+#endif
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ if (module_inst->func_perf_profilings)
+ wasm_runtime_free(module_inst->func_perf_profilings);
+#endif
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (module_inst->frames) {
+ bh_vector_destroy(module_inst->frames);
+ wasm_runtime_free(module_inst->frames);
+ module_inst->frames = NULL;
+ }
+#endif
+
+ if (module_inst->tables)
+ wasm_runtime_free(module_inst->tables);
+
+ if (module_inst->memories)
+ memories_deinstantiate(module_inst);
+
+ if (module_inst->export_functions)
+ wasm_runtime_free(module_inst->export_functions);
+
+ if (module_inst->func_ptrs)
+ wasm_runtime_free(module_inst->func_ptrs);
+
+ if (module_inst->func_type_indexes)
+ wasm_runtime_free(module_inst->func_type_indexes);
+
+ if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports)
+ wasm_runtime_free(
+ ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
+
+#if WASM_ENABLE_WASI_NN != 0
+ if (!is_sub_inst) {
+ WASINNContext *wasi_nn_ctx =
+ ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+ if (wasi_nn_ctx)
+ wasi_nn_destroy(wasi_nn_ctx);
+ }
+#endif
+
+ wasm_runtime_free(module_inst);
+}
+
+AOTFunctionInstance *
+aot_lookup_function(const AOTModuleInstance *module_inst, const char *name,
+ const char *signature)
+{
+ uint32 i;
+ AOTFunctionInstance *export_funcs =
+ (AOTFunctionInstance *)module_inst->export_functions;
+
+ for (i = 0; i < module_inst->export_func_count; i++)
+ if (!strcmp(export_funcs[i].func_name, name))
+ return &export_funcs[i];
+ (void)signature;
+ return NULL;
+}
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+
+static bool
+invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type,
+ const char *signature, void *attachment,
+ uint32 *argv, uint32 argc, uint32 *argv_ret)
+{
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+ WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
+ uint32 page_size = os_getpagesize();
+ uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+ uint16 param_count = func_type->param_count;
+ uint16 result_count = func_type->result_count;
+ const uint8 *types = func_type->types;
+#ifdef BH_PLATFORM_WINDOWS
+ int result;
+ bool has_exception;
+ char exception[EXCEPTION_BUF_LEN];
+#endif
+ bool ret;
+
+ /* Check native stack overflow firstly to ensure we have enough
+ native stack to run the following codes before actually calling
+ the aot function in invokeNative function. */
+ RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
+ if ((uint8 *)&module_inst < exec_env->native_stack_boundary
+ + page_size * (guard_page_count + 1)) {
+ aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
+ return false;
+ }
+
+ if (exec_env_tls && (exec_env_tls != exec_env)) {
+ aot_set_exception(module_inst, "invalid exec env");
+ return false;
+ }
+
+ if (!os_thread_signal_inited()) {
+ aot_set_exception(module_inst, "thread signal env not inited");
+ return false;
+ }
+
+ wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
+
+ wasm_runtime_set_exec_env_tls(exec_env);
+ if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
+ /* Quick call with func_ptr if the function signature is simple */
+ if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) {
+ if (result_count == 0) {
+ void (*NativeFunc)(WASMExecEnv *, uint32) =
+ (void (*)(WASMExecEnv *, uint32))func_ptr;
+ NativeFunc(exec_env, argv[0]);
+ ret = aot_copy_exception(module_inst, NULL) ? false : true;
+ }
+ else if (result_count == 1
+ && types[param_count] == VALUE_TYPE_I32) {
+ uint32 (*NativeFunc)(WASMExecEnv *, uint32) =
+ (uint32(*)(WASMExecEnv *, uint32))func_ptr;
+ argv_ret[0] = NativeFunc(exec_env, argv[0]);
+ ret = aot_copy_exception(module_inst, NULL) ? false : true;
+ }
+ else {
+ ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
+ signature, attachment, argv,
+ argc, argv_ret);
+ }
+ }
+ else {
+ ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
+ signature, attachment, argv, argc,
+ argv_ret);
+ }
+#ifdef BH_PLATFORM_WINDOWS
+ has_exception = aot_copy_exception(module_inst, exception);
+ if (has_exception && strstr(exception, "native stack overflow")) {
+ /* After a stack overflow, the stack was left
+ in a damaged state, let the CRT repair it */
+ result = _resetstkoflw();
+ bh_assert(result != 0);
+ }
+#endif
+ }
+ else {
+ /* Exception has been set in signal handler before calling longjmp */
+ ret = false;
+ }
+
+ jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
+ bh_assert(&jmpbuf_node == jmpbuf_node_pop);
+ if (!exec_env->jmpbuf_stack_top) {
+ wasm_runtime_set_exec_env_tls(NULL);
+ }
+ if (!ret) {
+ os_sigreturn();
+ os_signal_unmask();
+ }
+ (void)jmpbuf_node_pop;
+ return ret;
+}
+
+#define invoke_native_internal invoke_native_with_hw_bound_check
+#else /* else of OS_ENABLE_HW_BOUND_CHECK */
+#define invoke_native_internal wasm_runtime_invoke_native
+#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
+
+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->u.func.func_type;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
+ bool ret;
+
+ if (argc < func_type->param_cell_num) {
+ char buf[108];
+ snprintf(buf, sizeof(buf),
+ "invalid argument count %u, must be no smaller than %u", argc,
+ func_type->param_cell_num);
+ aot_set_exception(module_inst, buf);
+ return false;
+ }
+ argc = func_type->param_cell_num;
+
+ /* func pointer was looked up previously */
+ bh_assert(function->u.func.func_ptr != NULL);
+
+ /* set thread handle and stack boundary */
+ wasm_exec_env_set_thread_info(exec_env);
+
+ if (ext_ret_count > 0) {
+ uint32 cell_num = 0, i;
+ uint8 *ext_ret_types = func_type->types + func_type->param_count + 1;
+ uint32 argv1_buf[32], *argv1 = argv1_buf, *ext_rets = NULL;
+ uint32 *argv_ret = argv;
+ uint32 ext_ret_cell = wasm_get_cell_num(ext_ret_types, ext_ret_count);
+ uint64 size;
+
+ /* Allocate memory all arguments */
+ size =
+ sizeof(uint32) * (uint64)argc /* original arguments */
+ + sizeof(void *)
+ * (uint64)ext_ret_count /* extra result values' addr */
+ + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */
+ if (size > sizeof(argv1_buf)
+ && !(argv1 = runtime_malloc(size, module_inst->cur_exception,
+ sizeof(module_inst->cur_exception)))) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY);
+ return false;
+ }
+
+ /* Copy original arguments */
+ bh_memcpy_s(argv1, (uint32)size, argv, sizeof(uint32) * argc);
+
+ /* Get the extra result value's address */
+ ext_rets =
+ argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
+
+ /* Append each extra result value's address to original arguments */
+ for (i = 0; i < ext_ret_count; i++) {
+ *(uintptr_t *)(argv1 + argc + sizeof(void *) / sizeof(uint32) * i) =
+ (uintptr_t)(ext_rets + cell_num);
+ cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
+ }
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (!aot_alloc_frame(exec_env, function->func_index)) {
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+ return false;
+ }
+#endif
+
+ ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
+ func_type, NULL, NULL, argv1, argc, argv);
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (!ret) {
+ if (aot_create_call_stack(exec_env)) {
+ aot_dump_call_stack(exec_env, true, NULL, 0);
+ }
+ }
+#endif
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ aot_free_frame(exec_env);
+#endif
+ if (!ret) {
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+ return ret;
+ }
+
+ /* Get extra result values */
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ argv_ret++;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ argv_ret += 2;
+ break;
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ argv_ret += 4;
+ break;
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ ext_rets =
+ argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
+ bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, ext_rets,
+ sizeof(uint32) * cell_num);
+
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+ return true;
+ }
+ else {
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (!aot_alloc_frame(exec_env, function->func_index)) {
+ return false;
+ }
+#endif
+
+ ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
+ func_type, NULL, NULL, argv, argc, argv);
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (aot_copy_exception(module_inst, NULL)) {
+ if (aot_create_call_stack(exec_env)) {
+ aot_dump_call_stack(exec_env, true, NULL, 0);
+ }
+ }
+#endif
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ aot_free_frame(exec_env);
+#endif
+
+ return ret && !aot_copy_exception(module_inst, NULL) ? true : false;
+ }
+}
+
+void
+aot_set_exception(AOTModuleInstance *module_inst, const char *exception)
+{
+ wasm_set_exception(module_inst, exception);
+}
+
+void
+aot_set_exception_with_id(AOTModuleInstance *module_inst, uint32 id)
+{
+ if (id != EXCE_ALREADY_THROWN)
+ wasm_set_exception_with_id(module_inst, id);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+}
+
+const char *
+aot_get_exception(AOTModuleInstance *module_inst)
+{
+ return wasm_get_exception(module_inst);
+}
+
+bool
+aot_copy_exception(AOTModuleInstance *module_inst, char *exception_buf)
+{
+ /* The field offsets of cur_exception in AOTModuleInstance and
+ WASMModuleInstance are the same */
+ return wasm_copy_exception(module_inst, exception_buf);
+}
+
+static bool
+execute_malloc_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env,
+ AOTFunctionInstance *malloc_func,
+ AOTFunctionInstance *retain_func, uint32 size,
+ uint32 *p_result)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+#endif
+ WASMExecEnv *exec_env_created = NULL;
+ WASMModuleInstanceCommon *module_inst_old = NULL;
+ uint32 argv[2], argc;
+ bool ret;
+
+ argv[0] = size;
+ argc = 1;
+ if (retain_func) {
+ argv[1] = 0;
+ argc = 2;
+ }
+
+ if (exec_env) {
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env_tls) {
+ bh_assert(exec_env_tls == exec_env);
+ }
+#endif
+ bh_assert(exec_env->module_inst
+ == (WASMModuleInstanceCommon *)module_inst);
+ }
+ else {
+ /* Try using the existing exec_env */
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = exec_env_tls;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env)
+ exec_env = wasm_clusters_search_exec_env(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+ if (!exec_env) {
+ if (!(exec_env = exec_env_created = wasm_exec_env_create(
+ (WASMModuleInstanceCommon *)module_inst,
+ module_inst->default_wasm_stack_size))) {
+ wasm_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+ else {
+ /* Temporarily replace exec_env's module inst with current
+ module inst to ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_old = exec_env->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ }
+
+ ret = aot_call_function(exec_env, malloc_func, argc, argv);
+
+ if (retain_func && ret)
+ ret = aot_call_function(exec_env, retain_func, 1, argv);
+
+ if (module_inst_old)
+ /* Restore the existing exec_env's module inst */
+ exec_env->module_inst = module_inst_old;
+
+ if (exec_env_created)
+ wasm_exec_env_destroy(exec_env_created);
+
+ if (ret)
+ *p_result = argv[0];
+ return ret;
+}
+
+static bool
+execute_free_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env,
+ AOTFunctionInstance *free_func, uint32 offset)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+#endif
+ WASMExecEnv *exec_env_created = NULL;
+ WASMModuleInstanceCommon *module_inst_old = NULL;
+ uint32 argv[2];
+ bool ret;
+
+ argv[0] = offset;
+
+ if (exec_env) {
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env_tls) {
+ bh_assert(exec_env_tls == exec_env);
+ }
+#endif
+ bh_assert(exec_env->module_inst
+ == (WASMModuleInstanceCommon *)module_inst);
+ }
+ else {
+ /* Try using the existing exec_env */
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = exec_env_tls;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env)
+ exec_env = wasm_clusters_search_exec_env(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+ if (!exec_env) {
+ if (!(exec_env = exec_env_created = wasm_exec_env_create(
+ (WASMModuleInstanceCommon *)module_inst,
+ module_inst->default_wasm_stack_size))) {
+ wasm_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+ else {
+ /* Temporarily replace exec_env's module inst with current
+ module inst to ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_old = exec_env->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ }
+
+ ret = aot_call_function(exec_env, free_func, 1, argv);
+
+ if (module_inst_old)
+ /* Restore the existing exec_env's module inst */
+ exec_env->module_inst = module_inst_old;
+
+ if (exec_env_created)
+ wasm_exec_env_destroy(exec_env_created);
+
+ return ret;
+}
+
+uint32
+aot_module_malloc_internal(AOTModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 size,
+ void **p_native_addr)
+{
+ AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
+ AOTModule *module = (AOTModule *)module_inst->module;
+ uint8 *addr = NULL;
+ uint32 offset = 0;
+
+ if (!memory_inst) {
+ aot_set_exception(module_inst, "uninitialized memory");
+ return 0;
+ }
+
+ if (memory_inst->heap_handle) {
+ addr = mem_allocator_malloc(memory_inst->heap_handle, size);
+ }
+ else if (module->malloc_func_index != (uint32)-1
+ && module->free_func_index != (uint32)-1) {
+ AOTFunctionInstance *malloc_func, *retain_func = NULL;
+ char *malloc_func_name;
+ char *malloc_func_sig;
+
+ if (module->retain_func_index != (uint32)-1) {
+ malloc_func_name = "__new";
+ malloc_func_sig = "(ii)i";
+ retain_func = aot_lookup_function(module_inst, "__retain", "(i)i");
+ if (!retain_func)
+ retain_func = aot_lookup_function(module_inst, "__pin", "(i)i");
+ bh_assert(retain_func);
+ }
+ else {
+ malloc_func_name = "malloc";
+ malloc_func_sig = "(i)i";
+ }
+ malloc_func =
+ aot_lookup_function(module_inst, malloc_func_name, malloc_func_sig);
+
+ if (!malloc_func
+ || !execute_malloc_function(module_inst, exec_env, malloc_func,
+ retain_func, size, &offset)) {
+ return 0;
+ }
+ addr = offset ? (uint8 *)memory_inst->memory_data + offset : NULL;
+ }
+
+ if (!addr) {
+ if (memory_inst->heap_handle
+ && mem_allocator_is_heap_corrupted(memory_inst->heap_handle)) {
+ wasm_runtime_show_app_heap_corrupted_prompt();
+ aot_set_exception(module_inst, "app heap corrupted");
+ }
+ else {
+ LOG_WARNING("warning: allocate %u bytes memory failed", size);
+ }
+ return 0;
+ }
+ if (p_native_addr)
+ *p_native_addr = addr;
+ return (uint32)(addr - memory_inst->memory_data);
+}
+
+uint32
+aot_module_realloc_internal(AOTModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr, uint32 size,
+ void **p_native_addr)
+{
+ AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
+ uint8 *addr = NULL;
+
+ if (!memory_inst) {
+ aot_set_exception(module_inst, "uninitialized memory");
+ return 0;
+ }
+
+ if (memory_inst->heap_handle) {
+ addr = mem_allocator_realloc(
+ memory_inst->heap_handle,
+ ptr ? memory_inst->memory_data + ptr : NULL, size);
+ }
+
+ /* Only support realloc in WAMR's app heap */
+ (void)exec_env;
+
+ if (!addr) {
+ if (memory_inst->heap_handle
+ && mem_allocator_is_heap_corrupted(memory_inst->heap_handle)) {
+ aot_set_exception(module_inst, "app heap corrupted");
+ }
+ else {
+ aot_set_exception(module_inst, "out of memory");
+ }
+ return 0;
+ }
+
+ if (p_native_addr)
+ *p_native_addr = addr;
+ return (uint32)(addr - memory_inst->memory_data);
+}
+
+void
+aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *exec_env,
+ uint32 ptr)
+{
+ AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
+ AOTModule *module = (AOTModule *)module_inst->module;
+
+ if (!memory_inst) {
+ return;
+ }
+
+ if (ptr) {
+ uint8 *addr = memory_inst->memory_data + ptr;
+ if (memory_inst->heap_handle && memory_inst->heap_data < addr
+ && addr < memory_inst->heap_data_end) {
+ mem_allocator_free(memory_inst->heap_handle, addr);
+ }
+ else if (module->malloc_func_index != (uint32)-1
+ && module->free_func_index != (uint32)-1
+ && memory_inst->memory_data <= addr
+ && addr < memory_inst->memory_data_end) {
+ AOTFunctionInstance *free_func;
+ char *free_func_name;
+
+ if (module->retain_func_index != (uint32)-1) {
+ free_func_name = "__release";
+ }
+ else {
+ free_func_name = "free";
+ }
+ free_func =
+ aot_lookup_function(module_inst, free_func_name, "(i)i");
+ if (!free_func && module->retain_func_index != (uint32)-1)
+ free_func = aot_lookup_function(module_inst, "__unpin", "(i)i");
+
+ if (free_func)
+ execute_free_function(module_inst, exec_env, free_func, ptr);
+ }
+ }
+}
+
+uint32
+aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
+ void **p_native_addr)
+{
+ return aot_module_malloc_internal(module_inst, NULL, size, p_native_addr);
+}
+
+uint32
+aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size,
+ void **p_native_addr)
+{
+ return aot_module_realloc_internal(module_inst, NULL, ptr, size,
+ p_native_addr);
+}
+
+void
+aot_module_free(AOTModuleInstance *module_inst, uint32 ptr)
+{
+ aot_module_free_internal(module_inst, NULL, ptr);
+}
+
+uint32
+aot_module_dup_data(AOTModuleInstance *module_inst, const char *src,
+ uint32 size)
+{
+ char *buffer;
+ uint32 buffer_offset =
+ aot_module_malloc(module_inst, size, (void **)&buffer);
+
+ if (buffer_offset != 0) {
+ buffer = wasm_runtime_addr_app_to_native(
+ (WASMModuleInstanceCommon *)module_inst, buffer_offset);
+ bh_memcpy_s(buffer, size, src, size);
+ }
+ return buffer_offset;
+}
+
+bool
+aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
+{
+ return wasm_enlarge_memory(module_inst, inc_page_count);
+}
+
+bool
+aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
+ uint32 *argv)
+{
+ AOTModuleInstance *module_inst =
+ (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env);
+ AOTModule *aot_module = (AOTModule *)module_inst->module;
+ AOTModuleInstanceExtra *module_inst_extra =
+ (AOTModuleInstanceExtra *)module_inst->e;
+ CApiFuncImport *c_api_func_import =
+ module_inst_extra->c_api_func_imports
+ ? module_inst_extra->c_api_func_imports + func_idx
+ : NULL;
+ uint32 *func_type_indexes = module_inst->func_type_indexes;
+ uint32 func_type_idx = func_type_indexes[func_idx];
+ AOTFuncType *func_type = aot_module->func_types[func_type_idx];
+ void **func_ptrs = module_inst->func_ptrs;
+ void *func_ptr = func_ptrs[func_idx];
+ AOTImportFunc *import_func;
+ const char *signature;
+ void *attachment;
+ char buf[96];
+ bool ret = false;
+
+ bh_assert(func_idx < aot_module->import_func_count);
+
+ import_func = aot_module->import_funcs + func_idx;
+ if (import_func->call_conv_wasm_c_api)
+ func_ptr =
+ c_api_func_import ? c_api_func_import->func_ptr_linked : NULL;
+
+ if (!func_ptr) {
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ import_func->module_name, import_func->func_name);
+ aot_set_exception(module_inst, buf);
+ goto fail;
+ }
+
+ attachment = import_func->attachment;
+ if (import_func->call_conv_wasm_c_api) {
+ ret = wasm_runtime_invoke_c_api_native(
+ (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc,
+ argv, c_api_func_import->with_env_arg, c_api_func_import->env_arg);
+ }
+ else if (!import_func->call_conv_raw) {
+ signature = import_func->signature;
+ ret =
+ wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature,
+ attachment, argv, argc, argv);
+ }
+ else {
+ signature = import_func->signature;
+ ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type,
+ signature, attachment, argv, argc,
+ argv);
+ }
+
+fail:
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!ret)
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+ return ret;
+}
+
+bool
+aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
+ uint32 argc, uint32 *argv)
+{
+ AOTModuleInstance *module_inst =
+ (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env);
+ AOTModule *aot_module = (AOTModule *)module_inst->module;
+ uint32 *func_type_indexes = module_inst->func_type_indexes;
+ AOTTableInstance *tbl_inst;
+ AOTFuncType *func_type;
+ void **func_ptrs = module_inst->func_ptrs, *func_ptr;
+ uint32 func_type_idx, func_idx, ext_ret_count;
+ AOTImportFunc *import_func;
+ const char *signature = NULL;
+ void *attachment = NULL;
+ char buf[96];
+ bool ret;
+
+ /* this function is called from native code, so exec_env->handle and
+ exec_env->native_stack_boundary must have been set, we don't set
+ it again */
+
+ RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
+ if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
+ aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
+ goto fail;
+ }
+
+ tbl_inst = module_inst->tables[tbl_idx];
+ bh_assert(tbl_inst);
+
+ if (table_elem_idx >= tbl_inst->cur_size) {
+ aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT);
+ goto fail;
+ }
+
+ func_idx = tbl_inst->elems[table_elem_idx];
+ if (func_idx == NULL_REF) {
+ aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
+ goto fail;
+ }
+
+ func_type_idx = func_type_indexes[func_idx];
+ func_type = aot_module->func_types[func_type_idx];
+
+ if (func_idx >= aot_module->import_func_count) {
+ /* func pointer was looked up previously */
+ bh_assert(func_ptrs[func_idx] != NULL);
+ }
+
+ if (!(func_ptr = func_ptrs[func_idx])) {
+ bh_assert(func_idx < aot_module->import_func_count);
+ import_func = aot_module->import_funcs + func_idx;
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ import_func->module_name, import_func->func_name);
+ aot_set_exception(module_inst, buf);
+ goto fail;
+ }
+
+ if (func_idx < aot_module->import_func_count) {
+ /* Call native function */
+ import_func = aot_module->import_funcs + func_idx;
+ signature = import_func->signature;
+ if (import_func->call_conv_raw) {
+ attachment = import_func->attachment;
+ ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type,
+ signature, attachment, argv,
+ argc, argv);
+ if (!ret)
+ goto fail;
+
+ return true;
+ }
+ }
+
+ ext_ret_count =
+ func_type->result_count > 1 ? func_type->result_count - 1 : 0;
+ if (ext_ret_count > 0) {
+ uint32 argv1_buf[32], *argv1 = argv1_buf;
+ uint32 *ext_rets = NULL, *argv_ret = argv;
+ uint32 cell_num = 0, i;
+ uint8 *ext_ret_types = func_type->types + func_type->param_count + 1;
+ uint32 ext_ret_cell = wasm_get_cell_num(ext_ret_types, ext_ret_count);
+ uint64 size;
+
+ /* Allocate memory all arguments */
+ size =
+ sizeof(uint32) * (uint64)argc /* original arguments */
+ + sizeof(void *)
+ * (uint64)ext_ret_count /* extra result values' addr */
+ + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */
+ if (size > sizeof(argv1_buf)
+ && !(argv1 = runtime_malloc(size, module_inst->cur_exception,
+ sizeof(module_inst->cur_exception)))) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY);
+ goto fail;
+ }
+
+ /* Copy original arguments */
+ bh_memcpy_s(argv1, (uint32)size, argv, sizeof(uint32) * argc);
+
+ /* Get the extra result value's address */
+ ext_rets =
+ argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
+
+ /* Append each extra result value's address to original arguments */
+ for (i = 0; i < ext_ret_count; i++) {
+ *(uintptr_t *)(argv1 + argc + sizeof(void *) / sizeof(uint32) * i) =
+ (uintptr_t)(ext_rets + cell_num);
+ cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
+ }
+
+ ret = invoke_native_internal(exec_env, func_ptr, func_type, signature,
+ attachment, argv1, argc, argv);
+ if (!ret) {
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+ goto fail;
+ }
+
+ /* Get extra result values */
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ argv_ret++;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ argv_ret += 2;
+ break;
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ argv_ret += 4;
+ break;
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ ext_rets =
+ argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
+ bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, ext_rets,
+ sizeof(uint32) * cell_num);
+
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+
+ return true;
+ }
+ else {
+ ret = invoke_native_internal(exec_env, func_ptr, func_type, signature,
+ attachment, argv, argc, argv);
+ if (!ret)
+ goto fail;
+
+ return true;
+ }
+
+fail:
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+ return false;
+}
+
+bool
+aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str,
+ uint32 app_buf_addr, uint32 app_buf_size,
+ void **p_native_addr)
+{
+ bool ret;
+
+ ret = wasm_check_app_addr_and_convert(module_inst, is_str, app_buf_addr,
+ app_buf_size, p_native_addr);
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!ret)
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+
+ return ret;
+}
+
+void *
+aot_memmove(void *dest, const void *src, size_t n)
+{
+ return memmove(dest, src, n);
+}
+
+void *
+aot_memset(void *s, int c, size_t n)
+{
+ return memset(s, c, n);
+}
+
+double
+aot_sqrt(double x)
+{
+ return sqrt(x);
+}
+
+float
+aot_sqrtf(float x)
+{
+ return sqrtf(x);
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset,
+ uint32 len, uint32 dst)
+{
+ AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
+ AOTModule *aot_module;
+ uint8 *data = NULL;
+ uint8 *maddr;
+ uint64 seg_len = 0;
+
+ aot_module = (AOTModule *)module_inst->module;
+ seg_len = aot_module->mem_init_data_list[seg_index]->byte_count;
+ data = aot_module->mem_init_data_list[seg_index]->bytes;
+
+ if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
+ dst, len))
+ return false;
+
+ if ((uint64)offset + (uint64)len > seg_len) {
+ aot_set_exception(module_inst, "out of bounds memory access");
+ return false;
+ }
+
+ maddr = wasm_runtime_addr_app_to_native(
+ (WASMModuleInstanceCommon *)module_inst, dst);
+
+ bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len);
+ return true;
+}
+
+bool
+aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index)
+{
+ AOTModule *aot_module = (AOTModule *)module_inst->module;
+
+ aot_module->mem_init_data_list[seg_index]->byte_count = 0;
+ /* Currently we can't free the dropped data segment
+ as the mem_init_data_count is a continuous array */
+ return true;
+}
+#endif /* WASM_ENABLE_BULK_MEMORY */
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size)
+{
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+ AOTModule *module = (AOTModule *)module_inst->module;
+
+ uint32 stack_top_idx = module->aux_stack_top_global_index;
+ uint32 data_end = module->aux_data_end;
+ uint32 stack_bottom = module->aux_stack_bottom;
+ bool is_stack_before_data = stack_bottom < data_end ? true : false;
+
+ /* Check the aux stack space, currently we don't allocate space in heap */
+ if ((is_stack_before_data && (size > start_offset))
+ || ((!is_stack_before_data) && (start_offset - data_end < size)))
+ return false;
+
+ if (stack_top_idx != (uint32)-1) {
+ /* The aux stack top is a wasm global,
+ set the initial value for the global */
+ uint32 global_offset = module->globals[stack_top_idx].data_offset;
+ uint8 *global_addr = module_inst->global_data + global_offset;
+ *(int32 *)global_addr = start_offset;
+
+ /* The aux stack boundary is a constant value,
+ set the value to exec_env */
+ exec_env->aux_stack_boundary.boundary = start_offset - size;
+ exec_env->aux_stack_bottom.bottom = start_offset;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size)
+{
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+ AOTModule *module = (AOTModule *)module_inst->module;
+
+ /* The aux stack information is resolved in loader
+ and store in module */
+ uint32 stack_bottom = module->aux_stack_bottom;
+ uint32 total_aux_stack_size = module->aux_stack_size;
+
+ if (stack_bottom != 0 && total_aux_stack_size != 0) {
+ if (start_offset)
+ *start_offset = stack_bottom;
+ if (size)
+ *size = total_aux_stack_size;
+ return true;
+ }
+ return false;
+}
+#endif
+
+#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0)
+static void
+const_string_node_size_cb(void *key, void *value, void *p_const_string_size)
+{
+ uint32 const_string_size = 0;
+ const_string_size += bh_hash_map_get_elem_struct_size();
+ const_string_size += strlen((const char *)value) + 1;
+ *(uint32 *)p_const_string_size += const_string_size;
+}
+
+void
+aot_get_module_mem_consumption(const AOTModule *module,
+ WASMModuleMemConsumption *mem_conspn)
+{
+ uint32 i, size;
+
+ memset(mem_conspn, 0, sizeof(*mem_conspn));
+
+ mem_conspn->module_struct_size = sizeof(AOTModule);
+
+ mem_conspn->types_size = sizeof(AOTFuncType *) * module->func_type_count;
+ for (i = 0; i < module->func_type_count; i++) {
+ AOTFuncType *type = module->func_types[i];
+ size = offsetof(AOTFuncType, types)
+ + sizeof(uint8) * (type->param_count + type->result_count);
+ mem_conspn->types_size += size;
+ }
+
+ mem_conspn->imports_size =
+ sizeof(AOTImportMemory) * module->import_memory_count
+ + sizeof(AOTImportTable) * module->import_table_count
+ + sizeof(AOTImportGlobal) * module->import_global_count
+ + sizeof(AOTImportFunc) * module->import_func_count;
+
+ /* func_ptrs and func_type_indexes */
+ mem_conspn->functions_size =
+ (sizeof(void *) + sizeof(uint32)) * module->func_count;
+
+ mem_conspn->tables_size = sizeof(AOTTable) * module->table_count;
+
+ mem_conspn->memories_size = sizeof(AOTMemory) * module->memory_count;
+ mem_conspn->globals_size = sizeof(AOTGlobal) * module->global_count;
+ mem_conspn->exports_size = sizeof(AOTExport) * module->export_count;
+
+ mem_conspn->table_segs_size =
+ sizeof(AOTTableInitData *) * module->table_init_data_count;
+ for (i = 0; i < module->table_init_data_count; i++) {
+ AOTTableInitData *init_data = module->table_init_data_list[i];
+ size = offsetof(AOTTableInitData, func_indexes)
+ + sizeof(uint32) * init_data->func_index_count;
+ mem_conspn->table_segs_size += size;
+ }
+
+ mem_conspn->data_segs_size =
+ sizeof(AOTMemInitData *) * module->mem_init_data_count;
+ for (i = 0; i < module->mem_init_data_count; i++) {
+ mem_conspn->data_segs_size += sizeof(AOTMemInitData);
+ }
+
+ if (module->const_str_set) {
+ uint32 const_string_size = 0;
+
+ mem_conspn->const_strs_size =
+ bh_hash_map_get_struct_size(module->const_str_set);
+
+ bh_hash_map_traverse(module->const_str_set, const_string_node_size_cb,
+ (void *)&const_string_size);
+ mem_conspn->const_strs_size += const_string_size;
+ }
+
+ /* code size + literal size + object data section size */
+ mem_conspn->aot_code_size =
+ module->code_size + module->literal_size
+ + sizeof(AOTObjectDataSection) * module->data_section_count;
+ for (i = 0; i < module->data_section_count; i++) {
+ AOTObjectDataSection *obj_data = module->data_sections + i;
+ mem_conspn->aot_code_size += sizeof(uint8) * obj_data->size;
+ }
+
+ mem_conspn->total_size += mem_conspn->module_struct_size;
+ mem_conspn->total_size += mem_conspn->types_size;
+ mem_conspn->total_size += mem_conspn->imports_size;
+ mem_conspn->total_size += mem_conspn->functions_size;
+ mem_conspn->total_size += mem_conspn->tables_size;
+ mem_conspn->total_size += mem_conspn->memories_size;
+ mem_conspn->total_size += mem_conspn->globals_size;
+ mem_conspn->total_size += mem_conspn->exports_size;
+ mem_conspn->total_size += mem_conspn->table_segs_size;
+ mem_conspn->total_size += mem_conspn->data_segs_size;
+ mem_conspn->total_size += mem_conspn->const_strs_size;
+ mem_conspn->total_size += mem_conspn->aot_code_size;
+}
+
+void
+aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
+ WASMModuleInstMemConsumption *mem_conspn)
+{
+ AOTTableInstance *tbl_inst;
+ uint32 i;
+
+ memset(mem_conspn, 0, sizeof(*mem_conspn));
+
+ mem_conspn->module_inst_struct_size = sizeof(AOTModuleInstance);
+
+ mem_conspn->memories_size =
+ sizeof(void *) * module_inst->memory_count
+ + sizeof(AOTMemoryInstance) * module_inst->memory_count;
+ for (i = 0; i < module_inst->memory_count; i++) {
+ AOTMemoryInstance *mem_inst = module_inst->memories[i];
+ mem_conspn->memories_size +=
+ mem_inst->num_bytes_per_page * mem_inst->cur_page_count;
+ mem_conspn->app_heap_size =
+ mem_inst->heap_data_end - mem_inst->heap_data;
+ /* size of app heap structure */
+ mem_conspn->memories_size += mem_allocator_get_heap_struct_size();
+ }
+
+ mem_conspn->tables_size +=
+ sizeof(AOTTableInstance *) * module_inst->table_count;
+ for (i = 0; i < module_inst->table_count; i++) {
+ tbl_inst = module_inst->tables[i];
+ mem_conspn->tables_size += offsetof(AOTTableInstance, elems);
+ mem_conspn->tables_size += sizeof(uint32) * tbl_inst->max_size;
+ }
+
+ /* func_ptrs and func_type_indexes */
+ mem_conspn->functions_size =
+ (sizeof(void *) + sizeof(uint32))
+ * (((AOTModule *)module_inst->module)->import_func_count
+ + ((AOTModule *)module_inst->module)->func_count);
+
+ mem_conspn->globals_size = module_inst->global_data_size;
+
+ mem_conspn->exports_size =
+ sizeof(AOTFunctionInstance) * (uint64)module_inst->export_func_count;
+
+ mem_conspn->total_size += mem_conspn->module_inst_struct_size;
+ mem_conspn->total_size += mem_conspn->memories_size;
+ mem_conspn->total_size += mem_conspn->functions_size;
+ mem_conspn->total_size += mem_conspn->tables_size;
+ mem_conspn->total_size += mem_conspn->globals_size;
+ mem_conspn->total_size += mem_conspn->exports_size;
+}
+#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
+ || (WASM_ENABLE_MEMORY_TRACING != 0) */
+
+#if WASM_ENABLE_REF_TYPES != 0
+void
+aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx)
+{
+ AOTModule *module = (AOTModule *)module_inst->module;
+ AOTTableInitData *tbl_seg = module->table_init_data_list[tbl_seg_idx];
+ tbl_seg->is_dropped = true;
+}
+
+void
+aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 tbl_seg_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset)
+{
+ AOTTableInstance *tbl_inst;
+ AOTTableInitData *tbl_seg;
+ const AOTModule *module = (AOTModule *)module_inst->module;
+
+ tbl_inst = module_inst->tables[tbl_idx];
+ bh_assert(tbl_inst);
+
+ tbl_seg = module->table_init_data_list[tbl_seg_idx];
+ bh_assert(tbl_seg);
+
+ if (!length) {
+ return;
+ }
+
+ if (length + src_offset > tbl_seg->func_index_count
+ || dst_offset + length > tbl_inst->cur_size) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ if (tbl_seg->is_dropped) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ if (!wasm_elem_is_passive(tbl_seg->mode)) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ bh_memcpy_s((uint8 *)tbl_inst + offsetof(AOTTableInstance, elems)
+ + dst_offset * sizeof(uint32),
+ (tbl_inst->cur_size - dst_offset) * sizeof(uint32),
+ tbl_seg->func_indexes + src_offset, length * sizeof(uint32));
+}
+
+void
+aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset)
+{
+ AOTTableInstance *src_tbl_inst, *dst_tbl_inst;
+
+ src_tbl_inst = module_inst->tables[src_tbl_idx];
+ bh_assert(src_tbl_inst);
+
+ dst_tbl_inst = module_inst->tables[dst_tbl_idx];
+ bh_assert(dst_tbl_inst);
+
+ if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
+ || (uint64)src_offset + length > src_tbl_inst->cur_size) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ /* if src_offset >= dst_offset, copy from front to back */
+ /* if src_offset < dst_offset, copy from back to front */
+ /* merge all together */
+ bh_memmove_s((uint8 *)dst_tbl_inst + offsetof(AOTTableInstance, elems)
+ + dst_offset * sizeof(uint32),
+ (dst_tbl_inst->cur_size - dst_offset) * sizeof(uint32),
+ (uint8 *)src_tbl_inst + offsetof(AOTTableInstance, elems)
+ + src_offset * sizeof(uint32),
+ length * sizeof(uint32));
+}
+
+void
+aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
+ uint32 val, uint32 data_offset)
+{
+ AOTTableInstance *tbl_inst;
+
+ tbl_inst = module_inst->tables[tbl_idx];
+ bh_assert(tbl_inst);
+
+ if (data_offset + length > tbl_inst->cur_size) {
+ aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ for (; length != 0; data_offset++, length--) {
+ tbl_inst->elems[data_offset] = val;
+ }
+}
+
+uint32
+aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 inc_entries, uint32 init_val)
+{
+ uint32 entry_count, i, orig_tbl_sz;
+ AOTTableInstance *tbl_inst;
+
+ tbl_inst = module_inst->tables[tbl_idx];
+ if (!tbl_inst) {
+ return (uint32)-1;
+ }
+
+ orig_tbl_sz = tbl_inst->cur_size;
+
+ if (!inc_entries) {
+ return orig_tbl_sz;
+ }
+
+ if (tbl_inst->cur_size > UINT32_MAX - inc_entries) {
+ return (uint32)-1;
+ }
+
+ entry_count = tbl_inst->cur_size + inc_entries;
+ if (entry_count > tbl_inst->max_size) {
+ return (uint32)-1;
+ }
+
+ /* fill in */
+ for (i = 0; i < inc_entries; ++i) {
+ tbl_inst->elems[tbl_inst->cur_size + i] = init_val;
+ }
+
+ tbl_inst->cur_size = entry_count;
+ return orig_tbl_sz;
+}
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+static const char *
+lookup_func_name(const char **func_names, uint32 *func_indexes,
+ uint32 func_index_count, uint32 func_index)
+{
+ int64 low = 0, mid;
+ int64 high = func_index_count - 1;
+
+ if (!func_names || !func_indexes || func_index_count == 0)
+ return NULL;
+
+ while (low <= high) {
+ mid = (low + high) / 2;
+ if (func_index == func_indexes[mid]) {
+ return func_names[mid];
+ }
+ else if (func_index < func_indexes[mid])
+ high = mid - 1;
+ else
+ low = mid + 1;
+ }
+
+ return NULL;
+}
+#endif /* WASM_ENABLE_CUSTOM_NAME_SECTION != 0 */
+
+static const char *
+get_func_name_from_index(const AOTModuleInstance *module_inst,
+ uint32 func_index)
+{
+ const char *func_name = NULL;
+ AOTModule *module = (AOTModule *)module_inst->module;
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ if ((func_name =
+ lookup_func_name(module->aux_func_names, module->aux_func_indexes,
+ module->aux_func_name_count, func_index))) {
+ return func_name;
+ }
+#endif
+
+ if (func_index < module->import_func_count) {
+ func_name = module->import_funcs[func_index].func_name;
+ }
+ else {
+ uint32 i;
+
+ for (i = 0; i < module->export_count; i++) {
+ AOTExport export = module->exports[i];
+ if (export.index == func_index && export.kind == EXPORT_KIND_FUNC) {
+ func_name = export.name;
+ break;
+ }
+ }
+ }
+
+ return func_name;
+}
+
+bool
+aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index)
+{
+ AOTFrame *frame =
+ wasm_exec_env_alloc_wasm_frame(exec_env, sizeof(AOTFrame));
+#if WASM_ENABLE_PERF_PROFILING != 0
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+ AOTFuncPerfProfInfo *func_perf_prof =
+ module_inst->func_perf_profilings + func_index;
+#endif
+
+ if (!frame) {
+ aot_set_exception((AOTModuleInstance *)exec_env->module_inst,
+ "auxiliary call stack overflow");
+ return false;
+ }
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ frame->time_started = os_time_get_boot_microsecond();
+ frame->func_perf_prof_info = func_perf_prof;
+#endif
+
+ frame->prev_frame = (AOTFrame *)exec_env->cur_frame;
+ exec_env->cur_frame = (struct WASMInterpFrame *)frame;
+
+ frame->func_index = func_index;
+ return true;
+}
+
+void
+aot_free_frame(WASMExecEnv *exec_env)
+{
+ AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame;
+ AOTFrame *prev_frame = cur_frame->prev_frame;
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ cur_frame->func_perf_prof_info->total_exec_time +=
+ os_time_get_boot_microsecond() - cur_frame->time_started;
+ cur_frame->func_perf_prof_info->total_exec_cnt++;
+#endif
+
+ wasm_exec_env_free_wasm_frame(exec_env, cur_frame);
+ exec_env->cur_frame = (struct WASMInterpFrame *)prev_frame;
+}
+#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
+ || (WASM_ENABLE_PERF_PROFILING != 0) */
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+bool
+aot_create_call_stack(struct WASMExecEnv *exec_env)
+{
+ AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame,
+ *first_frame = cur_frame;
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+ uint32 n = 0;
+
+ while (cur_frame) {
+ cur_frame = cur_frame->prev_frame;
+ n++;
+ }
+
+ /* release previous stack frames and create new ones */
+ if (!bh_vector_destroy(module_inst->frames)
+ || !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame),
+ false)) {
+ return false;
+ }
+
+ cur_frame = first_frame;
+ while (cur_frame) {
+ WASMCApiFrame frame = { 0 };
+ frame.instance = module_inst;
+ frame.module_offset = 0;
+ frame.func_index = cur_frame->func_index;
+ frame.func_offset = 0;
+ frame.func_name_wp =
+ get_func_name_from_index(module_inst, cur_frame->func_index);
+
+ if (!bh_vector_append(module_inst->frames, &frame)) {
+ bh_vector_destroy(module_inst->frames);
+ return false;
+ }
+
+ cur_frame = cur_frame->prev_frame;
+ }
+
+ return true;
+}
+
+#define PRINT_OR_DUMP() \
+ do { \
+ total_len += \
+ wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \
+ if ((!print) && buf && (len == 0)) { \
+ return total_len; \
+ } \
+ } while (0)
+
+uint32
+aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len)
+{
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+ uint32 n = 0, total_len = 0, total_frames;
+ /* reserve 256 bytes for line buffer, any line longer than 256 bytes
+ * will be truncated */
+ char line_buf[256];
+
+ if (!module_inst->frames) {
+ return 0;
+ }
+
+ total_frames = (uint32)bh_vector_size(module_inst->frames);
+ if (total_frames == 0) {
+ return 0;
+ }
+
+ snprintf(line_buf, sizeof(line_buf), "\n");
+ PRINT_OR_DUMP();
+
+ while (n < total_frames) {
+ WASMCApiFrame frame = { 0 };
+ uint32 line_length, i;
+
+ if (!bh_vector_get(module_inst->frames, n, &frame)) {
+ return 0;
+ }
+
+ /* function name not exported, print number instead */
+ if (frame.func_name_wp == NULL) {
+ line_length = snprintf(line_buf, sizeof(line_buf), "#%02d $f%d\n",
+ n, frame.func_index);
+ }
+ else {
+ line_length = snprintf(line_buf, sizeof(line_buf), "#%02d %s\n", n,
+ frame.func_name_wp);
+ }
+
+ if (line_length >= sizeof(line_buf)) {
+ uint32 line_buffer_len = sizeof(line_buf);
+ /* If line too long, ensure the last character is '\n' */
+ for (i = line_buffer_len - 5; i < line_buffer_len - 2; i++) {
+ line_buf[i] = '.';
+ }
+ line_buf[line_buffer_len - 2] = '\n';
+ }
+
+ PRINT_OR_DUMP();
+
+ n++;
+ }
+ snprintf(line_buf, sizeof(line_buf), "\n");
+ PRINT_OR_DUMP();
+
+ return total_len + 1;
+}
+#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+void
+aot_dump_perf_profiling(const AOTModuleInstance *module_inst)
+{
+ AOTFuncPerfProfInfo *perf_prof =
+ (AOTFuncPerfProfInfo *)module_inst->func_perf_profilings;
+ AOTModule *module = (AOTModule *)module_inst->module;
+ uint32 total_func_count = module->import_func_count + module->func_count, i;
+ const char *func_name;
+
+ os_printf("Performance profiler data:\n");
+ for (i = 0; i < total_func_count; i++, perf_prof++) {
+ func_name = get_func_name_from_index(module_inst, i);
+
+ if (func_name)
+ os_printf(" func %s, execution time: %.3f ms, execution count: %d "
+ "times\n",
+ func_name, perf_prof->total_exec_time / 1000.0f,
+ perf_prof->total_exec_cnt);
+ else
+ os_printf(" func %d, execution time: %.3f ms, execution count: %d "
+ "times\n",
+ i, perf_prof->total_exec_time / 1000.0f,
+ perf_prof->total_exec_cnt);
+ }
+}
+#endif /* end of WASM_ENABLE_PERF_PROFILING */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.h
new file mode 100644
index 000000000..bcd06534e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/aot_runtime.h
@@ -0,0 +1,571 @@
+/*
+ * 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_WASI_NN != 0
+#include "../libraries/wasi-nn/src/wasi_nn_private.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum AOTSectionType {
+ AOT_SECTION_TYPE_TARGET_INFO = 0,
+ AOT_SECTION_TYPE_INIT_DATA = 1,
+ AOT_SECTION_TYPE_TEXT = 2,
+ AOT_SECTION_TYPE_FUNCTION = 3,
+ AOT_SECTION_TYPE_EXPORT = 4,
+ AOT_SECTION_TYPE_RELOCATION = 5,
+ AOT_SECTION_TYPE_SIGANATURE = 6,
+ AOT_SECTION_TYPE_CUSTOM = 100,
+} AOTSectionType;
+
+typedef enum AOTCustomSectionType {
+ AOT_CUSTOM_SECTION_RAW = 0,
+ AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1,
+ AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2,
+ AOT_CUSTOM_SECTION_NAME = 3,
+} AOTCustomSectionType;
+
+typedef struct AOTObjectDataSection {
+ char *name;
+ uint8 *data;
+ uint32 size;
+} AOTObjectDataSection;
+
+/* Relocation info */
+typedef struct AOTRelocation {
+ uint64 relocation_offset;
+ int64 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;
+
+/* AOT function instance */
+typedef struct AOTFunctionInstance {
+ char *func_name;
+ uint32 func_index;
+ bool is_import_func;
+ union {
+ struct {
+ AOTFuncType *func_type;
+ /* function pointer linked */
+ void *func_ptr;
+ } func;
+ AOTImportFunc *func_import;
+ } u;
+} AOTFunctionInstance;
+
+typedef struct AOTModuleInstanceExtra {
+ CApiFuncImport *c_api_func_imports;
+#if WASM_ENABLE_WASI_NN != 0
+ WASINNContext *wasi_nn_ctx;
+#endif
+} AOTModuleInstanceExtra;
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+/* clang-format off */
+typedef struct AOTUnwindInfo {
+ uint8 Version : 3;
+ uint8 Flags : 5;
+ uint8 SizeOfProlog;
+ uint8 CountOfCodes;
+ uint8 FrameRegister : 4;
+ uint8 FrameOffset : 4;
+ struct {
+ struct {
+ uint8 CodeOffset;
+ uint8 UnwindOp : 4;
+ uint8 OpInfo : 4;
+ };
+ uint16 FrameOffset;
+ } UnwindCode[1];
+} AOTUnwindInfo;
+/* clang-format on */
+
+/* size of mov instruction and jmp instruction */
+#define PLT_ITEM_SIZE 12
+#endif
+
+typedef struct AOTModule {
+ uint32 module_type;
+
+ /* import memories */
+ uint32 import_memory_count;
+ AOTImportMemory *import_memories;
+
+ /* memory info */
+ uint32 memory_count;
+ AOTMemory *memories;
+
+ /* init data */
+ uint32 mem_init_data_count;
+ AOTMemInitData **mem_init_data_list;
+
+ /* native symbol */
+ void **native_symbol_list;
+
+ /* import tables */
+ uint32 import_table_count;
+ AOTImportTable *import_tables;
+
+ /* tables */
+ uint32 table_count;
+ AOTTable *tables;
+
+ /* table init data info */
+ uint32 table_init_data_count;
+ AOTTableInitData **table_init_data_list;
+
+ /* function type info */
+ uint32 func_type_count;
+ AOTFuncType **func_types;
+
+ /* import global variable 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;
+ /* func pointers of AOTed (un-imported) functions */
+ void **func_ptrs;
+ /* func type indexes of AOTed (un-imported) functions */
+ uint32 *func_type_indexes;
+
+ /* export info */
+ uint32 export_count;
+ AOTExport *exports;
+
+ /* start function index, -1 denotes no start function */
+ uint32 start_func_index;
+ /* start function, point to AOTed function */
+ void *start_function;
+
+ uint32 malloc_func_index;
+ uint32 free_func_index;
+ uint32 retain_func_index;
+
+ /* AOTed code */
+ void *code;
+ uint32 code_size;
+
+ /* literal for AOTed code */
+ uint8 *literal;
+ uint32 literal_size;
+
+#if defined(BH_PLATFORM_WINDOWS)
+ /* extra plt data area for __ymm, __xmm and __real constants
+ in Windows platform */
+ uint8 *extra_plt_data;
+ uint32 extra_plt_data_size;
+ uint32 ymm_plt_count;
+ uint32 xmm_plt_count;
+ uint32 real_plt_count;
+ uint32 float_plt_count;
+#endif
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ /* dynamic function table to be added by RtlAddFunctionTable(),
+ used to unwind the call stack and register exception handler
+ for AOT functions */
+ RUNTIME_FUNCTION *rtl_func_table;
+ bool rtl_func_table_registered;
+#endif
+
+ /* data sections in AOT object file, including .data, .rodata
+ and .rodata.cstN. */
+ AOTObjectDataSection *data_sections;
+ uint32 data_section_count;
+
+ /* constant string set */
+ HashMap *const_str_set;
+
+ /* the index of auxiliary __data_end global,
+ -1 means unexported */
+ uint32 aux_data_end_global_index;
+ /* auxiliary __data_end exported by wasm app */
+ uint32 aux_data_end;
+
+ /* the index of auxiliary __heap_base global,
+ -1 means unexported */
+ uint32 aux_heap_base_global_index;
+ /* auxiliary __heap_base exported by wasm app */
+ uint32 aux_heap_base;
+
+ /* the index of auxiliary stack top global,
+ -1 means unexported */
+ uint32 aux_stack_top_global_index;
+ /* auxiliary stack bottom resolved */
+ uint32 aux_stack_bottom;
+ /* auxiliary stack size resolved */
+ uint32 aux_stack_size;
+
+ /* is indirect mode or not */
+ bool is_indirect_mode;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIArguments wasi_args;
+ bool import_wasi_api;
+#endif
+#if WASM_ENABLE_DEBUG_AOT != 0
+ void *elf_hdr;
+ uint32 elf_size;
+#endif
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ const char **aux_func_names;
+ uint32 *aux_func_indexes;
+ uint32 aux_func_name_count;
+#endif
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ WASMCustomSection *custom_section_list;
+#endif
+} AOTModule;
+
+#define AOTMemoryInstance WASMMemoryInstance
+#define AOTTableInstance WASMTableInstance
+#define AOTModuleInstance WASMModuleInstance
+
+/* Target info, read from ELF header of object file */
+typedef struct AOTTargetInfo {
+ /* Binary type, elf32l/elf32b/elf64l/elf64b */
+ uint16 bin_type;
+ /* ABI type */
+ uint16 abi_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;
+
+typedef struct AOTFuncPerfProfInfo {
+ /* total execution time */
+ uint64 total_exec_time;
+ /* total execution count */
+ uint32 total_exec_cnt;
+} AOTFuncPerfProfInfo;
+
+/* AOT auxiliary call stack */
+typedef struct AOTFrame {
+ struct AOTFrame *prev_frame;
+ uint32 func_index;
+#if WASM_ENABLE_PERF_PROFILING != 0
+ uint64 time_started;
+ AOTFuncPerfProfInfo *func_perf_prof_info;
+#endif
+} AOTFrame;
+
+/**
+ * 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);
+
+/**
+ * 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 is_sub_inst the flag of sub instance
+ * @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, bool is_sub_inst, WASMExecEnv *exec_env_main,
+ 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
+ * @param is_sub_inst the flag of sub instance
+ */
+void
+aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_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[]);
+
+/**
+ * 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);
+
+/**
+ * @brief Copy exception in buffer passed as parameter. Thread-safe version of
+ * `aot_get_exception()`
+ * @note Buffer size must be no smaller than EXCEPTION_BUF_LEN
+ * @return true if exception found, false otherwise
+ */
+bool
+aot_copy_exception(AOTModuleInstance *module_inst, char *exception_buf);
+
+uint32
+aot_module_malloc_internal(AOTModuleInstance *module_inst, WASMExecEnv *env,
+ uint32 size, void **p_native_addr);
+
+uint32
+aot_module_realloc_internal(AOTModuleInstance *module_inst, WASMExecEnv *env,
+ uint32 ptr, uint32 size, void **p_native_addr);
+
+void
+aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *env,
+ uint32 ptr);
+
+uint32
+aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
+ void **p_native_addr);
+
+uint32
+aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size,
+ void **p_native_addr);
+
+void
+aot_module_free(AOTModuleInstance *module_inst, uint32 ptr);
+
+uint32
+aot_module_dup_data(AOTModuleInstance *module_inst, const char *src,
+ uint32 size);
+
+bool
+aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count);
+
+/**
+ * Invoke native function from aot code
+ */
+bool
+aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
+ uint32 *argv);
+
+bool
+aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
+ uint32 argc, uint32 *argv);
+
+/**
+ * Check whether the app address and the buf is inside the linear memory,
+ * and convert the app address into native address
+ */
+bool
+aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str,
+ uint32 app_buf_addr, uint32 app_buf_size,
+ void **p_native_addr);
+
+uint32
+aot_get_plt_table_size();
+
+void *
+aot_memmove(void *dest, const void *src, size_t n);
+
+void *
+aot_memset(void *s, int c, size_t n);
+
+double
+aot_sqrt(double x);
+
+float
+aot_sqrtf(float x);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset,
+ uint32 len, uint32 dst);
+
+bool
+aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index);
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size);
+
+bool
+aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size);
+#endif
+
+void
+aot_get_module_mem_consumption(const AOTModule *module,
+ WASMModuleMemConsumption *mem_conspn);
+
+void
+aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
+ WASMModuleInstMemConsumption *mem_conspn);
+
+#if WASM_ENABLE_REF_TYPES != 0
+void
+aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx);
+
+void
+aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 tbl_seg_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset);
+
+void
+aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset);
+
+void
+aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
+ uint32 val, uint32 data_offset);
+
+uint32
+aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 inc_entries, uint32 init_val);
+#endif
+
+bool
+aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
+
+void
+aot_free_frame(WASMExecEnv *exec_env);
+
+bool
+aot_create_call_stack(struct WASMExecEnv *exec_env);
+
+/**
+ * @brief Dump wasm call stack or get the size
+ *
+ * @param exec_env the execution environment
+ * @param print whether to print to stdout or not
+ * @param buf buffer to store the dumped content
+ * @param len length of the buffer
+ *
+ * @return when print is true, return the bytes printed out to stdout; when
+ * print is false and buf is NULL, return the size required to store the
+ * callstack content; when print is false and buf is not NULL, return the size
+ * dumped to the buffer, 0 means error and data in buf may be invalid
+ */
+uint32
+aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len);
+
+void
+aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
+
+const uint8 *
+aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_RUNTIME_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_aarch64.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_aarch64.c
new file mode 100644
index 000000000..4c46eaa00
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_aarch64.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_AARCH64_MOVW_UABS_G0 263
+#define R_AARCH64_MOVW_UABS_G0_NC 264
+#define R_AARCH64_MOVW_UABS_G1 265
+#define R_AARCH64_MOVW_UABS_G1_NC 266
+#define R_AARCH64_MOVW_UABS_G2 267
+#define R_AARCH64_MOVW_UABS_G2_NC 268
+#define R_AARCH64_MOVW_UABS_G3 269
+
+#define R_AARCH64_MOVW_SABS_G0 270
+#define R_AARCH64_MOVW_SABS_G1 271
+#define R_AARCH64_MOVW_SABS_G2 272
+
+#define R_AARCH64_ADR_PREL_LO19 273
+#define R_AARCH64_ADR_PREL_LO21 274
+#define R_AARCH64_ADR_PREL_PG_HI21 275
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
+
+#define R_AARCH64_ADD_ABS_LO12_NC 277
+
+#define R_AARCH64_LDST8_ABS_LO12_NC 278
+#define R_AARCH64_LDST16_ABS_LO12_NC 284
+#define R_AARCH64_LDST32_ABS_LO12_NC 285
+#define R_AARCH64_LDST64_ABS_LO12_NC 286
+#define R_AARCH64_LDST128_ABS_LO12_NC 299
+
+#define R_AARCH64_JUMP26 282
+#define R_AARCH64_CALL26 283
+
+/* clang-format off */
+static SymbolMap target_sym_map[] = {
+ REG_COMMON_SYMBOLS
+};
+/* clang-format on */
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+#define BUILD_TARGET_AARCH64_DEFAULT "aarch64v8"
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ const char *s = BUILD_TARGET;
+ size_t s_size = sizeof(BUILD_TARGET);
+ char *d = target_buf;
+
+ /* Set to "aarch64v8" by default if sub version isn't specified */
+ if (strcmp(s, "AARCH64") == 0) {
+ s = BUILD_TARGET_AARCH64_DEFAULT;
+ s_size = sizeof(BUILD_TARGET_AARCH64_DEFAULT);
+ }
+ if (target_buf_size < s_size) {
+ s_size = target_buf_size;
+ }
+ while (--s_size) {
+ if (*s >= 'A' && *s <= 'Z')
+ *d++ = *s++ + 'a' - 'A';
+ else
+ *d++ = *s++;
+ }
+ /* Ensure the string is null byte ('\0') terminated */
+ *d = '\0';
+}
+#undef BUILD_TARGET_AARCH64_DEFAULT
+
+static uint32
+get_plt_item_size()
+{
+ /* 6*4 bytes instructions and 8 bytes symbol address */
+ return 32;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ for (i = 0; i < num; i++) {
+ uint32 *p = (uint32 *)plt;
+ *p++ = 0xf81f0ffe; /* str x30, [sp, #-16]! */
+ *p++ = 0x100000be; /* adr x30, #20; symbol addr is PC + 5 instructions
+ below */
+ *p++ = 0xf94003de; /* ldr x30, [x30] */
+ *p++ = 0xd63f03c0; /* blr x30 */
+ *p++ = 0xf84107fe; /* ldr x30, [sp], #16 */
+ *p++ = 0xd61f03c0; /* br x30 */
+ /* symbol addr */
+ *(uint64 *)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
+ p += 2;
+ plt += get_plt_item_size();
+ }
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) \
+ do { \
+ int64 m = (int64)((uint64)1 << (bits - 1)); \
+ val_ext = ((int64)val ^ m) - m; \
+ } while (0)
+
+#define Page(expr) ((expr) & ~0xFFF)
+
+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;
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_AARCH64_CALL26:
+ case R_AARCH64_JUMP26:
+ {
+ void *S, *P = (void *)(target_section_addr + reloc_offset);
+ int64 X, A, initial_addend;
+ int32 insn, imm26;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ insn = *(int32 *)P;
+ imm26 = insn & 0x3FFFFFF;
+ SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend);
+ A = initial_addend;
+ A += (int64)reloc_addend;
+
+ if (symbol_index < 0) {
+ /* Symbol address itself is an AOT function.
+ * Apply relocation with the symbol directly.
+ * Suppose the symbol address is in +-128MB relative
+ * to the relocation address.
+ */
+ S = symbol_addr;
+ }
+ else {
+ uint8 *plt;
+ if (reloc_addend > 0) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "AOT module load failed: relocate to plt table "
+ "with reloc addend larger than 0 is unsupported.");
+ return false;
+ }
+ /* Symbol address is not an AOT function,
+ * but a function of runtime or native. Its address is
+ * beyond of the +-128MB space. Apply relocation with
+ * the PLT which branch to the target symbol address.
+ */
+ S = plt = (uint8 *)module->code + module->code_size
+ - get_plt_table_size()
+ + get_plt_item_size() * symbol_index;
+ }
+
+ /* S + A - P */
+ X = (int64)S + A - (int64)P;
+
+ /* Check overflow: +-128MB */
+ if (X > (128 * BH_MB) || X < (-128 * BH_MB)) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "target address out of range.");
+ return false;
+ }
+
+ /* write the imm26 back to instruction */
+ *(int32 *)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF));
+ break;
+ }
+
+ case R_AARCH64_MOVW_UABS_G0:
+ case R_AARCH64_MOVW_UABS_G0_NC:
+ case R_AARCH64_MOVW_UABS_G1:
+ case R_AARCH64_MOVW_UABS_G1_NC:
+ case R_AARCH64_MOVW_UABS_G2:
+ case R_AARCH64_MOVW_UABS_G2_NC:
+ case R_AARCH64_MOVW_UABS_G3:
+ {
+ void *S = symbol_addr,
+ *P = (void *)(target_section_addr + reloc_offset);
+ int64 X, A, initial_addend;
+ int32 insn, imm16;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ insn = *(int32 *)P;
+ imm16 = (insn >> 5) & 0xFFFF;
+
+ SIGN_EXTEND_TO_INT64(imm16, 16, initial_addend);
+ A = initial_addend;
+ A += (int64)reloc_addend;
+
+ /* S + A */
+ X = (int64)S + A;
+
+ /* No need to check overflow for this relocation type */
+ switch (reloc_type) {
+ case R_AARCH64_MOVW_UABS_G0:
+ if (X < 0 || X >= (1LL << 16))
+ goto overflow_check_fail;
+ break;
+ case R_AARCH64_MOVW_UABS_G1:
+ if (X < 0 || X >= (1LL << 32))
+ goto overflow_check_fail;
+ break;
+ case R_AARCH64_MOVW_UABS_G2:
+ if (X < 0 || X >= (1LL << 48))
+ goto overflow_check_fail;
+ break;
+ default:
+ break;
+ }
+
+ /* write the imm16 back to bits[5:20] of instruction */
+ switch (reloc_type) {
+ case R_AARCH64_MOVW_UABS_G0:
+ case R_AARCH64_MOVW_UABS_G0_NC:
+ *(int32 *)P =
+ (insn & 0xFFE0001F) | ((int32)((X & 0xFFFF) << 5));
+ break;
+ case R_AARCH64_MOVW_UABS_G1:
+ case R_AARCH64_MOVW_UABS_G1_NC:
+ *(int32 *)P = (insn & 0xFFE0001F)
+ | ((int32)(((X >> 16) & 0xFFFF) << 5));
+ break;
+ case R_AARCH64_MOVW_UABS_G2:
+ case R_AARCH64_MOVW_UABS_G2_NC:
+ *(int32 *)P = (insn & 0xFFE0001F)
+ | ((int32)(((X >> 32) & 0xFFFF) << 5));
+ break;
+ case R_AARCH64_MOVW_UABS_G3:
+ *(int32 *)P = (insn & 0xFFE0001F)
+ | ((int32)(((X >> 48) & 0xFFFF) << 5));
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ break;
+ }
+
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ case R_AARCH64_ADR_PREL_PG_HI21_NC:
+ {
+ void *S = symbol_addr,
+ *P = (void *)(target_section_addr + reloc_offset);
+ int64 X, A, initial_addend;
+ int32 insn, immhi19, immlo2, imm21;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ insn = *(int32 *)P;
+ immhi19 = (insn >> 5) & 0x7FFFF;
+ immlo2 = (insn >> 29) & 0x3;
+ imm21 = (immhi19 << 2) | immlo2;
+
+ SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend);
+ A = initial_addend;
+ A += (int64)reloc_addend;
+
+ /* Page(S+A) - Page(P) */
+ X = Page((int64)S + A) - Page((int64)P);
+
+ /* Check overflow: +-4GB */
+ if (reloc_type == R_AARCH64_ADR_PREL_PG_HI21
+ && (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)))
+ goto overflow_check_fail;
+
+ /* write the imm21 back to instruction */
+ immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
+ immlo2 = (int32)((X >> 12) & 0x3);
+ *(int32 *)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5);
+
+ break;
+ }
+
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ {
+ void *S = symbol_addr,
+ *P = (void *)(target_section_addr + reloc_offset);
+ int64 X, A, initial_addend;
+ int32 insn, imm12;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ insn = *(int32 *)P;
+ imm12 = (insn >> 10) & 0xFFF;
+
+ SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
+ A = initial_addend;
+ A += (int64)reloc_addend;
+
+ /* S + A */
+ X = (int64)S + A;
+
+ /* No need to check overflow for this relocation type */
+
+ /* write the imm12 back to instruction */
+ *(int32 *)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
+ break;
+ }
+
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ {
+ void *S = symbol_addr,
+ *P = (void *)(target_section_addr + reloc_offset);
+ int64 X, A, initial_addend;
+ int32 insn, imm12;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ insn = *(int32 *)P;
+ imm12 = (insn >> 10) & 0xFFF;
+
+ SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
+ A = initial_addend;
+ A += (int64)reloc_addend;
+
+ /* S + A */
+ X = (int64)S + A;
+
+ /* No need to check overflow for this relocation type */
+
+ /* write the imm12 back to instruction */
+ switch (reloc_type) {
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ *(int32 *)P =
+ (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
+ break;
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ *(int32 *)P = (insn & 0xFFC003FF)
+ | ((int32)(((X & 0xFFF) >> 1) << 10));
+ break;
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ *(int32 *)P = (insn & 0xFFC003FF)
+ | ((int32)(((X & 0xFFF) >> 2) << 10));
+ break;
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ *(int32 *)P = (insn & 0xFFC003FF)
+ | ((int32)(((X & 0xFFF) >> 3) << 10));
+ break;
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ *(int32 *)P = (insn & 0xFFC003FF)
+ | ((int32)(((X & 0xFFF) >> 4) << 10));
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ reloc_type);
+ return false;
+ }
+
+ return true;
+
+overflow_check_fail:
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "target address out of range.");
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arc.c
new file mode 100644
index 000000000..332962998
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arc.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_ARC_S21H_PCREL 14
+#define R_ARC_S21W_PCREL 15
+#define R_ARC_S25H_PCREL 16
+#define R_ARC_S25W_PCREL 17
+#define R_ARC_32 4
+#define R_ARC_32_ME 27
+
+/* clang-format off */
+#ifndef __CCAC__
+void __st_r13_to_r15();
+void __st_r13_to_r16();
+void __st_r13_to_r17();
+void __st_r13_to_r18();
+void __st_r13_to_r19();
+void __st_r13_to_r20();
+void __st_r13_to_r21();
+void __st_r13_to_r22();
+void __st_r13_to_r23();
+void __st_r13_to_r24();
+void __st_r13_to_r25();
+void __ld_r13_to_r15();
+void __ld_r13_to_r16();
+void __ld_r13_to_r17();
+void __ld_r13_to_r18();
+void __ld_r13_to_r19();
+void __ld_r13_to_r20();
+void __ld_r13_to_r21();
+void __ld_r13_to_r22();
+void __ld_r13_to_r23();
+void __ld_r13_to_r24();
+void __ld_r13_to_r25();
+void __adddf3();
+void __addsf3();
+void __divdf3();
+void __divdi3();
+void __divsf3();
+void __divsi3();
+void __extendsfdf2();
+void __fixdfsi();
+void __floatsidf();
+void __floatsisf();
+void __muldf3();
+void __mulsf3();
+void __subdf3();
+void __subsf3();
+void __truncdfsf2();
+void __floatunsisf();
+void __fixunsdfsi();
+void __floatdisf();
+void __floatdidf();
+void __fixdfdi();
+void __ltsf2();
+void __gesf2();
+void __eqdf2();
+void __nedf2();
+void __ltsf2();
+void __nesf2();
+void __unordsf2();
+void __fixunssfsi();
+#else
+void __ac_push_13_to_13();
+void __ac_push_13_to_14();
+void __ac_push_13_to_15();
+void __ac_push_13_to_16();
+void __ac_push_13_to_17();
+void __ac_push_13_to_18();
+void __ac_push_13_to_19();
+void __ac_push_13_to_20();
+void __ac_push_13_to_21();
+void __ac_push_13_to_22();
+void __ac_push_13_to_23();
+void __ac_push_13_to_24();
+void __ac_push_13_to_25();
+void __ac_push_13_to_26();
+void __ac_push_none();
+void __ac_pop_13_to_26();
+void __ac_pop_13_to_26v();
+void __ac_pop_13_to_25();
+void __ac_pop_13_to_25v();
+void __ac_pop_13_to_24();
+void __ac_pop_13_to_24v();
+void __ac_pop_13_to_23();
+void __ac_pop_13_to_23v();
+void __ac_pop_13_to_22();
+void __ac_pop_13_to_22v();
+void __ac_pop_13_to_21();
+void __ac_pop_13_to_21v();
+void __ac_pop_13_to_20();
+void __ac_pop_13_to_20v();
+void __ac_pop_13_to_19();
+void __ac_pop_13_to_19v();
+void __ac_pop_13_to_18();
+void __ac_pop_13_to_18v();
+void __ac_pop_13_to_17();
+void __ac_pop_13_to_17v();
+void __ac_pop_13_to_16();
+void __ac_pop_13_to_16v();
+void __ac_pop_13_to_15();
+void __ac_pop_13_to_15v();
+void __ac_pop_13_to_14();
+void __ac_pop_13_to_14v();
+void __ac_pop_13_to_13();
+void __ac_pop_13_to_13v();
+void __ac_pop_none();
+void __ac_pop_nonev();
+void __eqdf2();
+void __nedf2();
+void __ltsf2();
+void __nesf2();
+void __gesf2();
+void __gtsf2();
+void __unordsf2();
+void __truncdfhf2();
+void __truncsfhf2();
+#endif /* end of __CCAC__ */
+
+void __ledf2();
+void __ltdf2();
+void __gedf2();
+void __gtdf2();
+void __eqsf2();
+void __lesf2();
+void __unorddf2();
+/* clang-format on */
+
+static SymbolMap target_sym_map[] = {
+ /* clang-format off */
+ REG_COMMON_SYMBOLS
+#ifndef __CCAC__
+ REG_SYM(__st_r13_to_r15),
+ REG_SYM(__st_r13_to_r16),
+ REG_SYM(__st_r13_to_r17),
+ REG_SYM(__st_r13_to_r18),
+ REG_SYM(__st_r13_to_r19),
+ REG_SYM(__st_r13_to_r20),
+ REG_SYM(__st_r13_to_r21),
+ REG_SYM(__st_r13_to_r22),
+ REG_SYM(__st_r13_to_r23),
+ REG_SYM(__st_r13_to_r24),
+ REG_SYM(__st_r13_to_r25),
+ REG_SYM(__ld_r13_to_r15),
+ REG_SYM(__ld_r13_to_r16),
+ REG_SYM(__ld_r13_to_r17),
+ REG_SYM(__ld_r13_to_r18),
+ REG_SYM(__ld_r13_to_r19),
+ REG_SYM(__ld_r13_to_r20),
+ REG_SYM(__ld_r13_to_r21),
+ REG_SYM(__ld_r13_to_r22),
+ REG_SYM(__ld_r13_to_r23),
+ REG_SYM(__ld_r13_to_r24),
+ REG_SYM(__ld_r13_to_r25),
+ REG_SYM(__adddf3),
+ REG_SYM(__addsf3),
+ REG_SYM(__divdf3),
+ REG_SYM(__divdi3),
+ REG_SYM(__divsf3),
+ REG_SYM(__divsi3),
+ REG_SYM(__extendsfdf2),
+ REG_SYM(__fixdfsi),
+ REG_SYM(__floatsidf),
+ REG_SYM(__floatsisf),
+ REG_SYM(__muldf3),
+ REG_SYM(__mulsf3),
+ REG_SYM(__subdf3),
+ REG_SYM(__subsf3),
+ REG_SYM(__truncdfsf2),
+ REG_SYM(__floatunsisf),
+ REG_SYM(__fixunsdfsi),
+ REG_SYM(__floatdisf),
+ REG_SYM(__floatdidf),
+ REG_SYM(__fixdfdi),
+ REG_SYM(__ltsf2),
+ REG_SYM(__gesf2),
+ REG_SYM(__eqdf2),
+ REG_SYM(__nedf2),
+ REG_SYM(__ltsf2),
+ REG_SYM(__nesf2),
+ REG_SYM(__unordsf2),
+ REG_SYM(__fixunssfsi),
+#else
+ REG_SYM(__ac_push_13_to_13),
+ REG_SYM(__ac_push_13_to_14),
+ REG_SYM(__ac_push_13_to_15),
+ REG_SYM(__ac_push_13_to_16),
+ REG_SYM(__ac_push_13_to_17),
+ REG_SYM(__ac_push_13_to_18),
+ REG_SYM(__ac_push_13_to_19),
+ REG_SYM(__ac_push_13_to_20),
+ REG_SYM(__ac_push_13_to_21),
+ REG_SYM(__ac_push_13_to_22),
+ REG_SYM(__ac_push_13_to_23),
+ REG_SYM(__ac_push_13_to_24),
+ REG_SYM(__ac_push_13_to_25),
+ REG_SYM(__ac_push_13_to_26),
+ REG_SYM(__ac_push_none),
+ REG_SYM(__ac_pop_13_to_26),
+ REG_SYM(__ac_pop_13_to_26v),
+ REG_SYM(__ac_pop_13_to_25),
+ REG_SYM(__ac_pop_13_to_25v),
+ REG_SYM(__ac_pop_13_to_24),
+ REG_SYM(__ac_pop_13_to_24v),
+ REG_SYM(__ac_pop_13_to_23),
+ REG_SYM(__ac_pop_13_to_23v),
+ REG_SYM(__ac_pop_13_to_22),
+ REG_SYM(__ac_pop_13_to_22v),
+ REG_SYM(__ac_pop_13_to_21),
+ REG_SYM(__ac_pop_13_to_21v),
+ REG_SYM(__ac_pop_13_to_20),
+ REG_SYM(__ac_pop_13_to_20v),
+ REG_SYM(__ac_pop_13_to_19),
+ REG_SYM(__ac_pop_13_to_19v),
+ REG_SYM(__ac_pop_13_to_18),
+ REG_SYM(__ac_pop_13_to_18v),
+ REG_SYM(__ac_pop_13_to_17),
+ REG_SYM(__ac_pop_13_to_17v),
+ REG_SYM(__ac_pop_13_to_16),
+ REG_SYM(__ac_pop_13_to_16v),
+ REG_SYM(__ac_pop_13_to_15),
+ REG_SYM(__ac_pop_13_to_15v),
+ REG_SYM(__ac_pop_13_to_14),
+ REG_SYM(__ac_pop_13_to_14v),
+ REG_SYM(__ac_pop_13_to_13),
+ REG_SYM(__ac_pop_13_to_13v),
+ REG_SYM(__ac_pop_none),
+ REG_SYM(__ac_pop_nonev),
+ REG_SYM(__eqdf2),
+ REG_SYM(__nedf2),
+ REG_SYM(__ltsf2),
+ REG_SYM(__nesf2),
+ REG_SYM(__gesf2),
+ REG_SYM(__gtsf2),
+ REG_SYM(__unordsf2),
+ REG_SYM(__truncdfhf2),
+ REG_SYM(__truncsfhf2),
+#endif /* end of __CCAC__ */
+
+ REG_SYM(__ledf2),
+ REG_SYM(__ltdf2),
+ REG_SYM(__gedf2),
+ REG_SYM(__gtdf2),
+ REG_SYM(__eqsf2),
+ REG_SYM(__lesf2),
+ REG_SYM(__unorddf2),
+ /* clang-format on */
+};
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "arc");
+}
+
+uint32
+get_plt_table_size()
+{
+ return 0;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ (void)plt;
+}
+
+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;
+}
+
+static uint32
+middle_endian_convert(uint32 insn)
+{
+ return ((insn & 0xFFFF0000) >> 16) | ((insn & 0x0000FFFF) << 16);
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_ARC_S25H_PCREL:
+ {
+ uint32 insn = LOAD_I32(target_section_addr + reloc_offset);
+ int32 addend, value;
+ uintptr_t S, P;
+ intptr_t A;
+
+ CHECK_RELOC_OFFSET(sizeof(void *));
+
+ /* Convert from middle endian */
+ insn = middle_endian_convert(insn);
+
+ addend = ((insn << 28) >> 28) << 10;
+ /* Extract the next 10 bits from Position 6 to 15 in insn */
+ addend |= ((insn << 16) >> 22);
+ addend = addend << 10;
+ /* Extract the remaining 10 bits from Position 17 to 26 in insn */
+ addend |= ((insn << 5) >> 22);
+ /* Fill in 1 bits to get the 25 bit Offset Value */
+ addend = addend << 1;
+
+ /* (S + A) - P */
+ S = (uintptr_t)(uint8 *)symbol_addr;
+ A = (intptr_t)reloc_addend;
+ P = (uintptr_t)(target_section_addr + reloc_offset);
+ P &= (uintptr_t)~1;
+ value = (int32)(S + A + addend - P);
+
+ insn = insn & 0xf8010030;
+ insn |= ((((value >> 1) & 0x3ff) << 17)
+ | (((value >> 1) & 0xffc00) >> 3)
+ | (((value >> 1) & 0xf00000) >> 19));
+
+ /* Convert to middle endian */
+ insn = middle_endian_convert(insn);
+
+ STORE_U32(target_section_addr + reloc_offset, insn);
+ break;
+ }
+ case R_ARC_S25W_PCREL:
+ {
+ uint32 insn = LOAD_I32(target_section_addr + reloc_offset);
+ int32 addend, value;
+ uintptr_t S, P;
+ intptr_t A;
+
+ CHECK_RELOC_OFFSET(sizeof(void *));
+
+ /* Convert from middle endian */
+ insn = middle_endian_convert(insn);
+
+ addend = ((insn << 28) >> 28) << 10;
+ /* Extract the next 10 bits from Position 6 to 15 in insn */
+ addend |= ((insn << 16) >> 22);
+ addend = addend << 9;
+ /* Extract the remaining 9 bits from Position 18 to 26 in insn */
+ addend |= ((insn << 5) >> 23);
+ /* Fill in 2 bits to get the 25 bit Offset Value */
+ addend = addend << 2;
+
+ /* (S + A) - P */
+ S = (uintptr_t)(uint8 *)symbol_addr;
+ A = (intptr_t)reloc_addend;
+ P = (uintptr_t)(target_section_addr + reloc_offset);
+ P &= (uintptr_t)~3;
+ value = (int32)(S + A + addend - P);
+
+ insn = insn & 0xf8030030;
+ insn |= ((((value >> 2) & 0x1ff) << 18)
+ | (((value >> 2) & 0x7fe00) >> 3)
+ | (((value >> 2) & 0x780000) >> 19));
+
+ /* Convert to middle endian */
+ insn = middle_endian_convert(insn);
+
+ STORE_U32(target_section_addr + reloc_offset, insn);
+ break;
+ }
+ case R_ARC_32:
+ case R_ARC_32_ME:
+ {
+ uint32 insn;
+
+ CHECK_RELOC_OFFSET(sizeof(void *));
+
+ /* (S + A) */
+ insn = (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ if (reloc_type == R_ARC_32_ME)
+ /* Convert to middle endian */
+ insn = middle_endian_convert(insn);
+
+ STORE_U32(target_section_addr + reloc_offset, insn);
+ break;
+ }
+ default:
+ {
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ reloc_type);
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arm.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arm.c
new file mode 100644
index 000000000..fbf9be13c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_arm.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */
+#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL<cond>). */
+#define R_ARM_ABS32 2 /* Direct 32 bit */
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
+
+/* clang-format off */
+void __adddf3();
+void __addsf3();
+void __aeabi_d2iz();
+void __aeabi_d2lz();
+void __aeabi_d2ulz();
+void __aeabi_dadd();
+void __aeabi_dcmpge();
+void __aeabi_dcmple();
+void __aeabi_dcmplt();
+void __aeabi_dcmpun();
+void __aeabi_ddiv();
+void __aeabi_f2d();
+void __aeabi_f2iz();
+void __aeabi_f2lz();
+void __aeabi_f2ulz();
+void __aeabi_fcmpge();
+void __aeabi_fcmple();
+void __aeabi_fcmplt();
+void __aeabi_fcmpun();
+void __aeabi_i2d();
+void __aeabi_idiv();
+void __aeabi_idivmod();
+void __aeabi_l2d();
+void __aeabi_l2f();
+void __aeabi_ldivmod();
+void __aeabi_memcpy();
+void __aeabi_memmove();
+void __aeabi_memset();
+void __aeabi_uidiv();
+void __aeabi_uidivmod();
+void __aeabi_ul2d();
+void __aeabi_ul2f();
+void __aeabi_uldivmod();
+void __clzsi2();
+void __divdf3();
+void __divdi3();
+void __divsf3();
+void __divsi3();
+void __eqdf2();
+void __extendsfdf2();
+void __fixdfdi();
+void __fixdfsi();
+void __fixsfdi();
+void __fixsfsi();
+void __fixunsdfdi();
+void __fixunsdfsi();
+void __fixunssfdi();
+void __floatdidf();
+void __floatdisf();
+void __floatsidf();
+void __floatsisf();
+void __floatundidf();
+void __floatundisf();
+void __floatunsidf();
+void __floatunsisf();
+void __gedf2();
+void __gesf2();
+void __gtdf2();
+void __gtsf2();
+void __ledf2();
+void __lesf2();
+void __ltdf2();
+void __ltsf2();
+void __moddi3();
+void __modsi3();
+void __muldf3();
+void __mulsf3();
+void __nedf2();
+void __nesf2();
+void __subdf3();
+void __subsf3();
+void __truncdfsf2();
+void __udivdi3();
+void __udivmoddi4();
+void __udivsi3();
+void __umoddi3();
+void __umodsi3();
+void __unorddf2();
+void __unordsf2();
+/* clang-format on */
+
+static SymbolMap target_sym_map[] = {
+ /* clang-format off */
+ REG_COMMON_SYMBOLS
+ /* compiler-rt symbols that come from compiler(e.g. gcc) */
+ REG_SYM(__adddf3),
+ REG_SYM(__addsf3),
+ /* clang-format on */
+ REG_SYM(__aeabi_d2iz),
+ REG_SYM(__aeabi_d2lz),
+ REG_SYM(__aeabi_d2ulz),
+ REG_SYM(__aeabi_dadd),
+ REG_SYM(__aeabi_dcmpge),
+ REG_SYM(__aeabi_dcmple),
+ REG_SYM(__aeabi_dcmplt),
+ REG_SYM(__aeabi_dcmpun),
+ REG_SYM(__aeabi_ddiv),
+ REG_SYM(__aeabi_f2d),
+ REG_SYM(__aeabi_f2iz),
+ REG_SYM(__aeabi_f2lz),
+ REG_SYM(__aeabi_f2ulz),
+ REG_SYM(__aeabi_fcmpge),
+ REG_SYM(__aeabi_fcmple),
+ REG_SYM(__aeabi_fcmplt),
+ REG_SYM(__aeabi_fcmpun),
+ REG_SYM(__aeabi_i2d),
+ REG_SYM(__aeabi_idiv),
+ REG_SYM(__aeabi_idivmod),
+ REG_SYM(__aeabi_l2d),
+ REG_SYM(__aeabi_l2f),
+ REG_SYM(__aeabi_ldivmod),
+ REG_SYM(__aeabi_memcpy),
+ REG_SYM(__aeabi_memmove),
+ REG_SYM(__aeabi_memset),
+ REG_SYM(__aeabi_uidiv),
+ REG_SYM(__aeabi_uidivmod),
+ REG_SYM(__aeabi_ul2d),
+ REG_SYM(__aeabi_ul2f),
+ REG_SYM(__aeabi_uldivmod),
+ REG_SYM(__clzsi2),
+ REG_SYM(__divdf3),
+ REG_SYM(__divdi3),
+ REG_SYM(__divsf3),
+ REG_SYM(__divsi3),
+ REG_SYM(__eqdf2),
+ REG_SYM(__extendsfdf2),
+ REG_SYM(__fixdfdi),
+ REG_SYM(__fixdfsi),
+ REG_SYM(__fixsfdi),
+ REG_SYM(__fixsfsi),
+ REG_SYM(__fixunsdfdi),
+ REG_SYM(__fixunsdfsi),
+ REG_SYM(__fixunssfdi),
+ REG_SYM(__floatdidf),
+ REG_SYM(__floatdisf),
+ REG_SYM(__floatsidf),
+ REG_SYM(__floatsisf),
+ REG_SYM(__floatundidf),
+ REG_SYM(__floatundisf),
+ REG_SYM(__floatunsidf),
+ REG_SYM(__floatunsisf),
+ REG_SYM(__gedf2),
+ REG_SYM(__gesf2),
+ REG_SYM(__gtdf2),
+ REG_SYM(__gtsf2),
+ REG_SYM(__ledf2),
+ REG_SYM(__lesf2),
+ REG_SYM(__ltdf2),
+ REG_SYM(__ltsf2),
+ REG_SYM(__moddi3),
+ REG_SYM(__modsi3),
+ REG_SYM(__muldf3),
+ REG_SYM(__muldf3),
+ REG_SYM(__mulsf3),
+ REG_SYM(__nedf2),
+ REG_SYM(__nesf2),
+ REG_SYM(__subdf3),
+ REG_SYM(__subsf3),
+ REG_SYM(__truncdfsf2),
+ REG_SYM(__udivdi3),
+ REG_SYM(__udivmoddi4),
+ REG_SYM(__udivsi3),
+ REG_SYM(__umoddi3),
+ REG_SYM(__umodsi3),
+ REG_SYM(__unorddf2),
+ REG_SYM(__unordsf2),
+};
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+#define BUILD_TARGET_ARM_DEFAULT "armv4"
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ const char *s = BUILD_TARGET;
+ size_t s_size = sizeof(BUILD_TARGET);
+ char *d = target_buf;
+
+ /* Set to "armv4" by default if sub version isn't specified */
+ if (strcmp(s, "ARM") == 0) {
+ s = BUILD_TARGET_ARM_DEFAULT;
+ s_size = sizeof(BUILD_TARGET_ARM_DEFAULT);
+ }
+ if (target_buf_size < s_size) {
+ s_size = target_buf_size;
+ }
+ while (--s_size) {
+ if (*s >= 'A' && *s <= 'Z')
+ *d++ = *s++ + 'a' - 'A';
+ else
+ *d++ = *s++;
+ }
+ /* Ensure the string is null byte ('\0') terminated */
+ *d = '\0';
+}
+#undef BUILD_TARGET_ARM_DEFAULT
+
+uint32
+get_plt_item_size()
+{
+ /* 8 bytes instructions and 4 bytes symbol address */
+ return 12;
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ for (i = 0; i < num; i++) {
+ uint32 *p = (uint32 *)plt;
+ /* ldr pc, [pc] */
+ *p++ = 0xe59ff000;
+ /* nop */
+ *p++ = 0xe1a00000;
+ /* symbol addr */
+ *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
+ plt += get_plt_item_size();
+ }
+}
+
+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;
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_ARM_CALL:
+ case R_ARM_JMP24:
+ {
+ intptr_t result;
+ int32 RESULT_MASK = 0x03FFFFFE;
+ int32 insn = *(int32 *)(target_section_addr + reloc_offset);
+ /* Initial addend: sign_extend(insn[23:0] << 2) */
+ int32 initial_addend =
+ ((insn & 0xFFFFFF) << 2) | ((insn & 0x800000) ? 0xFC000000 : 0);
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ if (symbol_index < 0) {
+ /* Symbol address itself is an AOT function.
+ * Apply relocation with the symbol directly.
+ * Suppose the symbol address is in +-32MB relative
+ * to the relocation address.
+ */
+ /* operation: ((S + A) | T) - P where S is symbol address and T
+ * is 0 */
+ result =
+ (intptr_t)((uintptr_t)symbol_addr + (intptr_t)reloc_addend
+ - (uintptr_t)(target_section_addr
+ + reloc_offset));
+ }
+ else {
+ if (reloc_addend > 0) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "AOT module load failed: relocate to plt table "
+ "with reloc addend larger than 0 is unsupported.");
+ return false;
+ }
+
+ /* Symbol address is not an AOT function,
+ * but a function of runtime or native. Its address is
+ * beyond of the +-32MB space. Apply relocation with
+ * the PLT which branch to the target symbol address.
+ */
+ /* operation: ((S + A) | T) - P where S is PLT address and T is
+ * 0 */
+ uint8 *plt = (uint8 *)module->code + module->code_size
+ - get_plt_table_size()
+ + get_plt_item_size() * symbol_index;
+ result = (intptr_t)((uintptr_t)plt + (intptr_t)reloc_addend
+ - (uintptr_t)(target_section_addr
+ + reloc_offset));
+ }
+
+ result += initial_addend;
+
+ /* Check overflow: +-32MB */
+ if (result > (32 * BH_MB) || result < (-32 * BH_MB)) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "target address out of range.");
+ return false;
+ }
+
+ *(int32 *)(target_section_addr + reloc_offset) =
+ (int32)((insn & 0xff000000)
+ | (((int32)result & RESULT_MASK) >> 2));
+ break;
+ }
+ case R_ARM_ABS32:
+ {
+ intptr_t initial_addend;
+ /* (S + A) | T where T is 0 */
+ CHECK_RELOC_OFFSET(sizeof(void *));
+ initial_addend =
+ *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
+ *(uintptr_t *)(target_section_addr + reloc_offset) =
+ (uintptr_t)symbol_addr + initial_addend
+ + (intptr_t)reloc_addend;
+ break;
+ }
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ {
+ uintptr_t *loc;
+ uintptr_t addr;
+ CHECK_RELOC_OFFSET(sizeof(void *));
+ loc = (uintptr_t *)(target_section_addr + (uint32)reloc_offset);
+ addr = (uintptr_t)symbol_addr + (intptr_t)reloc_addend;
+ if (reloc_type == R_ARM_MOVT_ABS) {
+ addr >>= 16;
+ }
+ *loc = ((*loc) & 0xfff0f000) | ((addr << 4) & 0x000f0000)
+ | (addr & 0x00000fff);
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ reloc_type);
+ return false;
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_mips.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_mips.c
new file mode 100644
index 000000000..f9f06a053
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_mips.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_MIPS_32 2 /* Direct 32 bit */
+#define R_MIPS_26 4 /* Direct 26 bit shifted */
+
+/* clang-format off */
+static SymbolMap target_sym_map[] = {
+ REG_COMMON_SYMBOLS
+};
+/* clang-format on */
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "mips");
+}
+
+static uint32
+get_plt_item_size()
+{
+ return 0;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ (void)plt;
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ /* TODO: implement relocation for mips */
+ case R_MIPS_26:
+ case R_MIPS_32:
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ reloc_type);
+ return false;
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_riscv.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_riscv.c
new file mode 100644
index 000000000..75fee56fd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_riscv.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_RISCV_32 1
+#define R_RISCV_64 2
+#define R_RISCV_CALL 18
+#define R_RISCV_CALL_PLT 19
+#define R_RISCV_HI20 26
+#define R_RISCV_LO12_I 27
+#define R_RISCV_LO12_S 28
+
+#define RV_OPCODE_SW 0x23
+
+/* clang-format off */
+void __adddf3();
+void __addsf3();
+void __divdi3();
+void __divsi3();
+void __divdf3();
+void __divsf3();
+void __eqsf2();
+void __eqdf2();
+void __extendsfdf2();
+void __fixdfdi();
+void __fixdfsi();
+void __fixsfdi();
+void __fixsfsi();
+void __fixunsdfdi();
+void __fixunsdfsi();
+void __fixunssfdi();
+void __fixunssfsi();
+void __floatdidf();
+void __floatdisf();
+void __floatsisf();
+void __floatsidf();
+void __floatundidf();
+void __floatundisf();
+void __floatunsisf();
+void __floatunsidf();
+void __gedf2();
+void __gesf2();
+void __gtdf2();
+void __gtsf2();
+void __ledf2();
+void __lesf2();
+void __ltdf2();
+void __ltsf2();
+void __moddi3();
+void __modsi3();
+void __muldf3();
+void __muldi3();
+void __mulsf3();
+void __mulsi3();
+void __nedf2();
+void __nesf2();
+void __subdf3();
+void __subsf3();
+void __truncdfsf2();
+void __udivdi3();
+void __udivsi3();
+void __umoddi3();
+void __umodsi3();
+void __unorddf2();
+void __unordsf2();
+/* clang-format on */
+
+static SymbolMap target_sym_map[] = {
+ /* clang-format off */
+ REG_COMMON_SYMBOLS
+#ifndef __riscv_flen
+ REG_SYM(__adddf3),
+ REG_SYM(__addsf3),
+ REG_SYM(__divdf3),
+ REG_SYM(__divsf3),
+ REG_SYM(__gedf2),
+ REG_SYM(__gesf2),
+ REG_SYM(__gtdf2),
+ REG_SYM(__gtsf2),
+ REG_SYM(__ledf2),
+ REG_SYM(__lesf2),
+ REG_SYM(__ltdf2),
+ REG_SYM(__ltsf2),
+ REG_SYM(__muldf3),
+ REG_SYM(__nedf2),
+ REG_SYM(__nesf2),
+ REG_SYM(__eqsf2),
+ REG_SYM(__eqdf2),
+ REG_SYM(__extendsfdf2),
+ REG_SYM(__fixunsdfdi),
+ REG_SYM(__fixunsdfsi),
+ REG_SYM(__fixunssfsi),
+ REG_SYM(__subdf3),
+ REG_SYM(__subsf3),
+ REG_SYM(__truncdfsf2),
+ REG_SYM(__unorddf2),
+ REG_SYM(__unordsf2),
+#endif
+ REG_SYM(__divdi3),
+ REG_SYM(__divsi3),
+#if __riscv_xlen == 32
+ REG_SYM(__fixdfdi),
+ REG_SYM(__fixdfsi),
+ REG_SYM(__fixsfdi),
+ REG_SYM(__fixsfsi),
+#endif
+ REG_SYM(__fixunssfdi),
+#if __riscv_xlen == 32
+ REG_SYM(__floatdidf),
+ REG_SYM(__floatdisf),
+ REG_SYM(__floatsisf),
+ REG_SYM(__floatsidf),
+ REG_SYM(__floatundidf),
+ REG_SYM(__floatundisf),
+ REG_SYM(__floatunsisf),
+ REG_SYM(__floatunsidf),
+#endif
+ REG_SYM(__moddi3),
+ REG_SYM(__modsi3),
+ REG_SYM(__muldi3),
+#if __riscv_xlen == 32
+ REG_SYM(__mulsf3),
+ REG_SYM(__mulsi3),
+#endif
+ REG_SYM(__udivdi3),
+ REG_SYM(__udivsi3),
+ REG_SYM(__umoddi3),
+ REG_SYM(__umodsi3),
+ /* clang-format on */
+};
+
+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);
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "riscv");
+}
+
+uint32
+get_plt_item_size()
+{
+#if __riscv_xlen == 64
+ /* auipc + ld + jalr + nop + addr */
+ return 20;
+#else
+ return 0;
+#endif
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+/* Get a val from given address */
+static uint32
+rv_get_val(uint16 *addr)
+{
+ uint32 ret;
+ ret = *addr | (*(addr + 1)) << 16;
+ return ret;
+}
+
+/* Set a val to given address */
+static void
+rv_set_val(uint16 *addr, uint32 val)
+{
+ *addr = (val & 0xffff);
+ *(addr + 1) = (val >> 16);
+
+ __asm__ volatile("fence.i");
+}
+
+/* Add a val to given address */
+static void
+rv_add_val(uint16 *addr, uint32 val)
+{
+ uint32 cur = rv_get_val(addr);
+ rv_set_val(addr, cur + val);
+}
+
+/**
+ * Get imm_hi and imm_lo from given integer
+ *
+ * @param imm given integer, signed 32bit
+ * @param imm_hi signed 20bit
+ * @param imm_lo signed 12bit
+ *
+ */
+static void
+rv_calc_imm(int32 imm, int32 *imm_hi, int32 *imm_lo)
+{
+ int32 lo;
+ int32 hi = imm / 4096;
+ int32 r = imm % 4096;
+
+ if (2047 < r) {
+ hi++;
+ }
+ else if (r < -2048) {
+ hi--;
+ }
+
+ lo = imm - (hi * 4096);
+
+ *imm_lo = lo;
+ *imm_hi = hi;
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+#if __riscv_xlen == 64
+ uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ uint8 *p;
+
+ for (i = 0; i < num; i++) {
+ p = plt;
+ /* auipc t1, 0 */
+ *(uint16 *)p = 0x0317;
+ p += 2;
+ *(uint16 *)p = 0x0000;
+ p += 2;
+ /* ld t1, 8(t1) */
+ *(uint16 *)p = 0x3303;
+ p += 2;
+ *(uint16 *)p = 0x00C3;
+ p += 2;
+ /* jr t1 */
+ *(uint16 *)p = 0x8302;
+ p += 2;
+ /* nop */
+ *(uint16 *)p = 0x0001;
+ p += 2;
+ bh_memcpy_s(p, 8, &target_sym_map[i].symbol_addr, 8);
+ p += 8;
+ plt += get_plt_item_size();
+ }
+#endif
+}
+
+typedef struct RelocTypeStrMap {
+ uint32 reloc_type;
+ char *reloc_str;
+} RelocTypeStrMap;
+
+#define RELOC_TYPE_MAP(reloc_type) \
+ { \
+ reloc_type, #reloc_type \
+ }
+
+static RelocTypeStrMap reloc_type_str_maps[] = {
+ RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_CALL),
+ RELOC_TYPE_MAP(R_RISCV_CALL_PLT), RELOC_TYPE_MAP(R_RISCV_HI20),
+ RELOC_TYPE_MAP(R_RISCV_LO12_I), RELOC_TYPE_MAP(R_RISCV_LO12_S),
+};
+
+static const char *
+reloc_type_to_str(uint32 reloc_type)
+{
+ uint32 i;
+
+ for (i = 0; i < sizeof(reloc_type_str_maps) / sizeof(RelocTypeStrMap);
+ i++) {
+ if (reloc_type_str_maps[i].reloc_type == reloc_type)
+ return reloc_type_str_maps[i].reloc_str;
+ }
+
+ return "Unknown_Reloc_Type";
+}
+
+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;
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ int32 val, imm_hi, imm_lo, insn;
+ uint8 *addr = target_section_addr + reloc_offset;
+ char buf[128];
+
+ switch (reloc_type) {
+ case R_RISCV_32:
+ {
+ uint32 val_32 =
+ (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ CHECK_RELOC_OFFSET(sizeof(uint32));
+ if (val_32 != ((uintptr_t)symbol_addr + (intptr_t)reloc_addend)) {
+ goto fail_addr_out_of_range;
+ }
+
+ rv_set_val((uint16 *)addr, val_32);
+ break;
+ }
+ case R_RISCV_64:
+ {
+ uint64 val_64 =
+ (uint64)((uintptr_t)symbol_addr + (intptr_t)reloc_addend);
+ CHECK_RELOC_OFFSET(sizeof(uint64));
+ bh_memcpy_s(addr, 8, &val_64, 8);
+ break;
+ }
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT:
+ {
+ val = (int32)(intptr_t)((uint8 *)symbol_addr - addr);
+
+ CHECK_RELOC_OFFSET(sizeof(uint32));
+ if (val != (intptr_t)((uint8 *)symbol_addr - addr)) {
+ if (symbol_index >= 0) {
+ /* Call runtime function by plt code */
+ symbol_addr = (uint8 *)module->code + module->code_size
+ - get_plt_table_size()
+ + get_plt_item_size() * symbol_index;
+ val = (int32)(intptr_t)((uint8 *)symbol_addr - addr);
+ }
+ }
+
+ if (val != (intptr_t)((uint8 *)symbol_addr - addr)) {
+ goto fail_addr_out_of_range;
+ }
+
+ rv_calc_imm(val, &imm_hi, &imm_lo);
+
+ rv_add_val((uint16 *)addr, (imm_hi << 12));
+ if ((rv_get_val((uint16 *)(addr + 4)) & 0x7f) == RV_OPCODE_SW) {
+ /* Adjust imm for SW : S-type */
+ val = (((int32)imm_lo >> 5) << 25)
+ + (((int32)imm_lo & 0x1f) << 7);
+
+ rv_add_val((uint16 *)(addr + 4), val);
+ }
+ else {
+ /* Adjust imm for MV(ADDI)/JALR : I-type */
+ rv_add_val((uint16 *)(addr + 4), ((int32)imm_lo << 20));
+ }
+ break;
+ }
+
+ case R_RISCV_HI20:
+ {
+ val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ CHECK_RELOC_OFFSET(sizeof(uint32));
+ if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
+ goto fail_addr_out_of_range;
+ }
+
+ addr = target_section_addr + reloc_offset;
+ insn = rv_get_val((uint16 *)addr);
+ rv_calc_imm(val, &imm_hi, &imm_lo);
+ insn = (insn & 0x00000fff) | (imm_hi << 12);
+ rv_set_val((uint16 *)addr, insn);
+ break;
+ }
+
+ case R_RISCV_LO12_I:
+ {
+ val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ CHECK_RELOC_OFFSET(sizeof(uint32));
+ if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) {
+ goto fail_addr_out_of_range;
+ }
+
+ addr = target_section_addr + reloc_offset;
+ insn = rv_get_val((uint16 *)addr);
+ rv_calc_imm(val, &imm_hi, &imm_lo);
+ insn = (insn & 0x000fffff) | (imm_lo << 20);
+ rv_set_val((uint16 *)addr, insn);
+ break;
+ }
+
+ case R_RISCV_LO12_S:
+ {
+ val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ CHECK_RELOC_OFFSET(sizeof(uint32));
+ if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
+ goto fail_addr_out_of_range;
+ }
+
+ addr = target_section_addr + reloc_offset;
+ rv_calc_imm(val, &imm_hi, &imm_lo);
+ val = (((int32)imm_lo >> 5) << 25) + (((int32)imm_lo & 0x1f) << 7);
+ rv_add_val((uint16 *)addr, val);
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %" PRIu32 ".",
+ reloc_type);
+ return false;
+ }
+
+ return true;
+
+fail_addr_out_of_range:
+ snprintf(buf, sizeof(buf),
+ "AOT module load failed: "
+ "relocation truncated to fit %s failed.",
+ reloc_type_to_str(reloc_type));
+ set_error_buf(error_buf, error_buf_size, buf);
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_thumb.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_thumb.c
new file mode 100644
index 000000000..26614863b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_thumb.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#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_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+#define R_ARM_THM_MOVW_PREL_NC 49
+#define R_ARM_THM_MOVT_PREL 50
+
+/* clang-format off */
+void __adddf3();
+void __addsf3();
+void __aeabi_d2iz();
+void __aeabi_d2lz();
+void __aeabi_d2uiz();
+void __aeabi_d2ulz();
+void __aeabi_dadd();
+void __aeabi_dcmpge();
+void __aeabi_dcmpgt();
+void __aeabi_dcmple();
+void __aeabi_dcmplt();
+void __aeabi_dcmpun();
+void __aeabi_ddiv();
+void __aeabi_f2d();
+void __aeabi_f2iz();
+void __aeabi_f2lz();
+void __aeabi_f2ulz();
+void __aeabi_fcmpge();
+void __aeabi_fcmple();
+void __aeabi_fcmplt();
+void __aeabi_fcmpun();
+void __aeabi_i2d();
+void __aeabi_idiv();
+void __aeabi_idivmod();
+void __aeabi_l2d();
+void __aeabi_l2f();
+void __aeabi_ldivmod();
+void __aeabi_ui2d();
+void __aeabi_uidiv();
+void __aeabi_uidivmod();
+void __aeabi_ul2d();
+void __aeabi_ul2f();
+void __aeabi_uldivmod();
+void __ashldi3();
+void __clzsi2();
+void __divdf3();
+void __divdi3();
+void __divsi3();
+void __eqdf2();
+void __eqsf2();
+void __extendsfdf2();
+void __fixdfdi();
+void __fixdfsi();
+void __fixsfdi();
+void __fixunsdfdi();
+void __fixunsdfsi();
+void __fixunssfdi();
+void __floatdidf();
+void __floatdisf();
+void __floatsidf();
+void __floatsisf();
+void __floatundidf();
+void __floatundisf();
+void __floatunsidf();
+void __floatunsisf();
+void __gedf2();
+void __gesf2();
+void __gtdf2();
+void __gtsf2();
+void __ledf2();
+void __lesf2();
+void __lshrdi3();
+void __ltdf2();
+void __ltsf2();
+void __moddi3();
+void __modsi3();
+void __muldf3();
+void __muldi3();
+void __mulsf3();
+void __nedf2();
+void __nesf2();
+void __subdf3();
+void __subsf3();
+void __truncdfsf2();
+void __udivdi3();
+void __udivmoddi4();
+void __udivsi3();
+void __umoddi3();
+void __umodsi3();
+void __unorddf2();
+void __unordsf2();
+/* clang-format on */
+
+static SymbolMap target_sym_map[] = {
+ /* clang-format off */
+ REG_COMMON_SYMBOLS
+ /* compiler-rt symbols that come from compiler(e.g. gcc) */
+#if __ARM_ARCH != 6
+ REG_SYM(__adddf3),
+ REG_SYM(__addsf3),
+ REG_SYM(__divdf3),
+ REG_SYM(__extendsfdf2),
+ REG_SYM(__fixdfsi),
+ REG_SYM(__floatsidf),
+ REG_SYM(__floatsisf),
+ REG_SYM(__floatunsidf),
+ REG_SYM(__floatunsisf),
+ REG_SYM(__muldf3),
+ REG_SYM(__mulsf3),
+ REG_SYM(__subdf3),
+ REG_SYM(__subsf3),
+ REG_SYM(__truncdfsf2),
+ REG_SYM(__unorddf2),
+ REG_SYM(__unordsf2),
+#endif
+ /* clang-format on */
+ REG_SYM(__aeabi_d2iz),
+ REG_SYM(__aeabi_d2lz),
+ REG_SYM(__aeabi_d2uiz),
+ REG_SYM(__aeabi_d2ulz),
+ REG_SYM(__aeabi_dadd),
+ REG_SYM(__aeabi_dcmpge),
+ REG_SYM(__aeabi_dcmpgt),
+ REG_SYM(__aeabi_dcmple),
+ REG_SYM(__aeabi_dcmplt),
+ REG_SYM(__aeabi_dcmpun),
+ REG_SYM(__aeabi_ddiv),
+ REG_SYM(__aeabi_f2d),
+ REG_SYM(__aeabi_f2iz),
+ REG_SYM(__aeabi_f2lz),
+ REG_SYM(__aeabi_f2ulz),
+ REG_SYM(__aeabi_fcmpge),
+ REG_SYM(__aeabi_fcmple),
+ REG_SYM(__aeabi_fcmplt),
+ REG_SYM(__aeabi_fcmpun),
+ REG_SYM(__aeabi_i2d),
+ REG_SYM(__aeabi_idiv),
+ REG_SYM(__aeabi_idivmod),
+ REG_SYM(__aeabi_l2d),
+ REG_SYM(__aeabi_l2f),
+ REG_SYM(__aeabi_ldivmod),
+ REG_SYM(__aeabi_ui2d),
+ REG_SYM(__aeabi_uidiv),
+ REG_SYM(__aeabi_uidivmod),
+ REG_SYM(__aeabi_ul2d),
+ REG_SYM(__aeabi_ul2f),
+ REG_SYM(__aeabi_uldivmod),
+ REG_SYM(__ashldi3),
+ REG_SYM(__clzsi2),
+ REG_SYM(__divdi3),
+ REG_SYM(__divsi3),
+ REG_SYM(__eqdf2),
+ REG_SYM(__eqsf2),
+ REG_SYM(__fixdfdi),
+ REG_SYM(__fixsfdi),
+ REG_SYM(__fixunsdfdi),
+ REG_SYM(__fixunsdfsi),
+ REG_SYM(__fixunssfdi),
+ REG_SYM(__floatdidf),
+ REG_SYM(__floatdisf),
+ REG_SYM(__floatundidf),
+ REG_SYM(__floatundisf),
+ REG_SYM(__gedf2),
+ REG_SYM(__gesf2),
+ REG_SYM(__gtdf2),
+ REG_SYM(__gtsf2),
+ REG_SYM(__ledf2),
+ REG_SYM(__lesf2),
+ REG_SYM(__lshrdi3),
+ REG_SYM(__ltdf2),
+ REG_SYM(__ltsf2),
+ REG_SYM(__moddi3),
+ REG_SYM(__modsi3),
+ REG_SYM(__muldi3),
+ REG_SYM(__nedf2),
+ REG_SYM(__nesf2),
+ REG_SYM(__udivdi3),
+ REG_SYM(__udivmoddi4),
+ REG_SYM(__udivsi3),
+ REG_SYM(__umoddi3),
+ REG_SYM(__umodsi3),
+};
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+#define BUILD_TARGET_THUMB_V4T "thumbv4t"
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ const char *s = BUILD_TARGET;
+ size_t s_size = sizeof(BUILD_TARGET);
+ char *d = target_buf;
+
+ /* Set to "thumbv4t" by default if sub version isn't specified */
+ if (strcmp(s, "THUMB") == 0) {
+ s = BUILD_TARGET_THUMB_V4T;
+ s_size = sizeof(BUILD_TARGET_THUMB_V4T);
+ }
+ if (target_buf_size < s_size) {
+ s_size = target_buf_size;
+ }
+ while (--s_size) {
+ if (*s >= 'A' && *s <= 'Z')
+ *d++ = *s++ + 'a' - 'A';
+ else
+ *d++ = *s++;
+ }
+ /* Ensure the string is null byte ('\0') terminated */
+ *d = '\0';
+}
+#undef BUILD_TARGET_THUMB_V4T
+
+uint32
+get_plt_item_size()
+{
+ /* 16 bytes instructions and 4 bytes symbol address */
+ return 20;
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ for (i = 0; i < num; i++) {
+ uint16 *p = (uint16 *)plt;
+ /* nop */
+ *p++ = 0xbf00;
+ /* push {r4} */
+ *p++ = 0xb410;
+ /* add r4, pc, #8 */
+ *p++ = 0xa402;
+ /* ldr r4, [r4, #0] */
+ *p++ = 0x6824;
+ /* mov ip, r4 */
+ *p++ = 0x46a4;
+ /* pop {r4} */
+ *p++ = 0xbc10;
+ /* mov pc, ip */
+ *p++ = 0x46e7;
+ /* nop */
+ *p++ = 0xbf00;
+ /* symbol addr */
+ *(uint32 *)p = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
+ plt += get_plt_item_size();
+ }
+}
+
+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;
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_ARM_THM_CALL:
+ case R_ARM_THM_JMP24:
+ {
+ int32 RESULT_MASK = 0x01FFFFFE;
+ int32 result, result_masked;
+ int16 *reloc_addr;
+ int32 initial_addend_0, initial_addend_1, initial_addend;
+ bool sign;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ reloc_addr = (int16 *)(target_section_addr + reloc_offset);
+ initial_addend_0 = (*reloc_addr) & 0x7FF;
+ initial_addend_1 = (*(reloc_addr + 1)) & 0x7FF;
+ sign = (initial_addend_0 & 0x400) ? true : false;
+ initial_addend = (initial_addend_0 << 12) | (initial_addend_1 << 1)
+ | (sign ? 0xFF800000 : 0);
+
+ if (symbol_index < 0) {
+ /* Symbol address itself is an AOT function.
+ * Apply relocation with the symbol directly.
+ * Suppose the symbol address is in +-4MB relative
+ * to the relocation address.
+ */
+ /* operation: ((S + A) | T) - P where S is symbol address
+ and T is 1 */
+ result =
+ (int32)(((intptr_t)((uintptr_t)symbol_addr
+ + (intptr_t)reloc_addend)
+ | 1)
+ - (intptr_t)(target_section_addr + reloc_offset));
+ }
+ else {
+ if (reloc_addend > 0) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "AOT module load failed: relocate to plt table "
+ "with reloc addend larger than 0 is unsupported.");
+ return false;
+ }
+
+ /* Symbol address is not an AOT function,
+ * but a function of runtime or native. Its address is
+ * beyond of the +-4MB space. Apply relocation with
+ * the PLT which branch to the target symbol address.
+ */
+ /* operation: ((S + A) | T) - P where S is PLT address
+ and T is 1 */
+ uint8 *plt = (uint8 *)module->code + module->code_size
+ - get_plt_table_size()
+ + get_plt_item_size() * symbol_index + 1;
+ result =
+ (int32)(((intptr_t)plt | 1)
+ - (intptr_t)(target_section_addr + reloc_offset));
+ }
+
+ result += initial_addend;
+
+ /* Check overflow: +-4MB */
+ if (result > (4 * BH_MB) || result < (-4 * BH_MB)) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "target address out of range.");
+ return false;
+ }
+
+ result_masked = (int32)result & RESULT_MASK;
+ initial_addend_0 = (result_masked >> 12) & 0x7FF;
+ initial_addend_1 = (result_masked >> 1) & 0x7FF;
+
+ *reloc_addr = (*reloc_addr & ~0x7FF) | initial_addend_0;
+ *(reloc_addr + 1) = (*(reloc_addr + 1) & ~0x7FF) | initial_addend_1;
+ break;
+ }
+ case R_ARM_ABS32:
+ {
+ intptr_t initial_addend;
+ /* (S + A) | T where T is 0 */
+ CHECK_RELOC_OFFSET(sizeof(void *));
+ initial_addend =
+ *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
+ *(uintptr_t *)(target_section_addr + reloc_offset) =
+ (uintptr_t)symbol_addr + initial_addend
+ + (intptr_t)reloc_addend;
+ break;
+ }
+ case R_ARM_THM_MOVW_ABS_NC:
+ case R_ARM_THM_MOVT_ABS:
+ case R_ARM_THM_MOVW_PREL_NC:
+ case R_ARM_THM_MOVT_PREL:
+ {
+ uint16 upper = *(uint16 *)(target_section_addr + reloc_offset);
+ uint16 lower = *(uint16 *)(target_section_addr + reloc_offset + 2);
+ int32 offset;
+
+ /*
+ * MOVT/MOVW instructions encoding in Thumb-2:
+ *
+ * i = upper[10]
+ * imm4 = upper[3:0]
+ * imm3 = lower[14:12]
+ * imm8 = lower[7:0]
+ *
+ * imm16 = imm4:i:imm3:imm8
+ */
+
+ offset = ((upper & 0x000f) << 12) | ((upper & 0x0400) << 1)
+ | ((lower & 0x7000) >> 4) | (lower & 0x00ff);
+ offset = (offset ^ 0x8000) - 0x8000;
+
+ offset += (symbol_addr + reloc_addend);
+
+ if (reloc_type == R_ARM_THM_MOVT_PREL
+ || reloc_type == R_ARM_THM_MOVW_PREL_NC)
+ offset -= (int32)(target_section_addr + reloc_offset);
+ if (reloc_type == R_ARM_THM_MOVT_ABS
+ || reloc_type == R_ARM_THM_MOVT_PREL)
+ offset >>= 16;
+
+ upper = (uint16)((upper & 0xfbf0) | ((offset & 0xf000) >> 12)
+ | ((offset & 0x0800) >> 1));
+ lower = (uint16)((lower & 0x8f00) | ((offset & 0x0700) << 4)
+ | (offset & 0x00ff));
+
+ *(uint16 *)(target_section_addr + reloc_offset) = upper;
+ *(uint16 *)(target_section_addr + reloc_offset + 2) = lower;
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %" PRId32 ".",
+ reloc_type);
+ return false;
+ }
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_32.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_32.c
new file mode 100644
index 000000000..af3e0bb8e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_32.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_386_32 1 /* Direct 32 bit */
+#define R_386_PC32 2 /* PC relative 32 bit */
+#define R_386_PLT32 4 /* 32-bit address ProcedureLinkageTable */
+
+#if !defined(_WIN32) && !defined(_WIN32_)
+/* clang-format off */
+void __divdi3();
+void __udivdi3();
+void __moddi3();
+void __umoddi3();
+/* clang-format on */
+#else
+#pragma function(floor)
+#pragma function(ceil)
+
+static int64
+__divdi3(int64 a, int64 b)
+{
+ return a / b;
+}
+
+static uint64
+__udivdi3(uint64 a, uint64 b)
+{
+ return a / b;
+}
+
+static int64
+__moddi3(int64 a, int64 b)
+{
+ return a % b;
+}
+
+static uint64
+__umoddi3(uint64 a, uint64 b)
+{
+ return a % b;
+}
+#endif
+
+/* clang-format off */
+static SymbolMap target_sym_map[] = {
+ REG_COMMON_SYMBOLS
+ /* compiler-rt symbols that come from compiler(e.g. gcc) */
+ REG_SYM(__divdi3),
+ REG_SYM(__udivdi3),
+ REG_SYM(__moddi3),
+ REG_SYM(__umoddi3)
+};
+/* clang-format on */
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "i386");
+}
+
+uint32
+get_plt_table_size()
+{
+ return 0;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ (void)plt;
+}
+
+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;
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_386_32:
+ {
+ intptr_t value;
+
+ CHECK_RELOC_OFFSET(sizeof(void *));
+ value = *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
+ *(uintptr_t *)(target_section_addr + reloc_offset) =
+ (uintptr_t)symbol_addr + (intptr_t)reloc_addend
+ + value; /* S + A */
+ break;
+ }
+
+ /*
+ * Handle R_386_PLT32 like R_386_PC32 since it should be able to reach
+ * any 32 bit address
+ */
+ case R_386_PLT32:
+ 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)((uintptr_t)symbol_addr + (intptr_t)reloc_addend
+ - (uintptr_t)(target_section_addr
+ + (uint32)reloc_offset)
+ + value); /* S + A - P */
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ reloc_type);
+ return false;
+ }
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_64.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_64.c
new file mode 100644
index 000000000..f4d8eeabd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_x86_64.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#if !defined(BH_PLATFORM_WINDOWS)
+#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 */
+#else
+#ifndef IMAGE_REL_AMD64_ADDR64
+#define IMAGE_REL_AMD64_ADDR64 1 /* The 64-bit VA of the relocation target */
+#define IMAGE_REL_AMD64_ADDR32 2 /* The 32-bit VA of the relocation target */
+/* clang-format off */
+#define IMAGE_REL_AMD64_REL32 4 /* The 32-bit relative address from
+ the byte following the relocation*/
+/* clang-format on */
+#endif
+#endif
+
+#if defined(BH_PLATFORM_WINDOWS)
+#pragma function(floor)
+#pragma function(ceil)
+#pragma function(floorf)
+#pragma function(ceilf)
+#endif
+
+/* clang-format off */
+static SymbolMap target_sym_map[] = {
+ REG_COMMON_SYMBOLS
+};
+/* clang-format on */
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "x86_64");
+}
+
+static uint32
+get_plt_item_size()
+{
+ /* size of mov instruction and jmp instruction */
+ return 12;
+}
+
+uint32
+get_plt_table_size()
+{
+ uint32 size =
+ get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ size += get_plt_item_size() + sizeof(AOTUnwindInfo);
+#endif
+ return size;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ uint8 *p;
+
+ for (i = 0; i < num; i++) {
+ 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();
+ }
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+ p = plt;
+ /* mov exception_handler, rax */
+ *p++ = 0x48;
+ *p++ = 0xB8;
+ *(uint64 *)p = 0; /*(uint64)(uintptr_t)aot_exception_handler;*/
+ p += sizeof(uint64);
+ /* jmp rax */
+ *p++ = 0xFF;
+ *p++ = 0xE0;
+#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;
+}
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+#if !defined(BH_PLATFORM_WINDOWS)
+ case R_X86_64_64:
+#else
+ case IMAGE_REL_AMD64_ADDR64:
+#endif
+ {
+ intptr_t value;
+
+ CHECK_RELOC_OFFSET(sizeof(void *));
+ value = *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
+ *(uintptr_t *)(target_section_addr + reloc_offset) =
+ (uintptr_t)symbol_addr + reloc_addend + value; /* S + A */
+ break;
+ }
+#if defined(BH_PLATFORM_WINDOWS)
+ case IMAGE_REL_AMD64_ADDR32:
+ {
+ int32 value;
+ uintptr_t target_addr;
+
+ CHECK_RELOC_OFFSET(sizeof(void *));
+ value = *(int32 *)(target_section_addr + (uint32)reloc_offset);
+ target_addr = (uintptr_t)symbol_addr + reloc_addend + value;
+ if ((int32)target_addr != target_addr) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "relocation truncated to fit "
+ "IMAGE_REL_AMD64_ADDR32 failed. "
+ "Try using wamrc with --size-level=1 option.");
+ return false;
+ }
+
+ *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr;
+ break;
+ }
+#endif
+#if !defined(BH_PLATFORM_WINDOWS)
+ case R_X86_64_PC32:
+ {
+ intptr_t target_addr = (intptr_t) /* S + A - P */
+ ((uintptr_t)symbol_addr + reloc_addend
+ - (uintptr_t)(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. "
+ "Try using wamrc with --size-level=1 option.");
+ 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 = /* S + A */
+ (uintptr_t)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. "
+ "Try using wamrc with --size-level=1 option.",
+ 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;
+ }
+#endif
+#if !defined(BH_PLATFORM_WINDOWS)
+ case R_X86_64_PLT32:
+#else
+ case IMAGE_REL_AMD64_REL32:
+#endif
+ {
+ uint8 *plt;
+ intptr_t target_addr = 0;
+
+ CHECK_RELOC_OFFSET(sizeof(int32));
+
+ if (symbol_index >= 0) {
+ plt = (uint8 *)module->code + module->code_size
+ - get_plt_table_size()
+ + get_plt_item_size() * symbol_index;
+ target_addr = (intptr_t) /* L + A - P */
+ ((uintptr_t)plt + reloc_addend
+ - (uintptr_t)(target_section_addr + reloc_offset));
+ }
+ else {
+ target_addr = (intptr_t) /* L + A - P */
+ ((uintptr_t)symbol_addr + reloc_addend
+ - (uintptr_t)(target_section_addr + reloc_offset));
+ }
+
+#if defined(BH_PLATFORM_WINDOWS)
+ target_addr -= sizeof(int32);
+#endif
+ if ((int32)target_addr != target_addr) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "relocation truncated to fit "
+#if !defined(BH_PLATFORM_WINDOWS)
+ "R_X86_64_PLT32 failed. "
+#else
+ "IMAGE_REL_AMD64_32 failed."
+#endif
+ "Try using wamrc with --size-level=1 option.");
+ return false;
+ }
+ *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr;
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ reloc_type);
+ return false;
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c
new file mode 100644
index 000000000..3327c396f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_XTENSA_32 1 /* Direct 32 bit */
+#define R_XTENSA_SLOT0_OP 20 /* PC relative */
+
+/* clang-format off */
+/* for soft-float */
+void __floatsidf();
+void __divdf3();
+void __ltdf2();
+
+/* for mul32 */
+void __mulsi3();
+void __muldi3();
+
+void __modsi3();
+
+void __divdi3();
+
+void __udivdi3();
+void __unorddf2();
+void __adddf3();
+void __eqdf2();
+void __muldf3();
+void __gedf2();
+void __ledf2();
+void __fixunsdfsi();
+void __floatunsidf();
+void __subdf3();
+void __nedf2();
+void __fixdfsi();
+void __moddi3();
+void __extendsfdf2();
+void __truncdfsf2();
+void __gtdf2();
+void __umoddi3();
+void __floatdidf();
+void __divsf3();
+void __fixdfdi();
+void __floatundidf();
+
+
+static SymbolMap target_sym_map[] = {
+ REG_COMMON_SYMBOLS
+
+ /* API's for soft-float */
+ /* TODO: only register these symbols when Floating-Point Coprocessor
+ * Option is not enabled */
+ REG_SYM(__floatsidf),
+ REG_SYM(__divdf3),
+ REG_SYM(__ltdf2),
+
+ /* API's for 32-bit integer multiply */
+ /* TODO: only register these symbols when 32-bit Integer Multiply Option
+ * is not enabled */
+ REG_SYM(__mulsi3),
+ REG_SYM(__muldi3),
+
+ REG_SYM(__modsi3),
+ REG_SYM(__divdi3),
+
+ REG_SYM(__udivdi3),
+ REG_SYM(__unorddf2),
+ REG_SYM(__adddf3),
+ REG_SYM(__eqdf2),
+ REG_SYM(__muldf3),
+ REG_SYM(__gedf2),
+ REG_SYM(__ledf2),
+ REG_SYM(__fixunsdfsi),
+ REG_SYM(__floatunsidf),
+ REG_SYM(__subdf3),
+ REG_SYM(__nedf2),
+ REG_SYM(__fixdfsi),
+ REG_SYM(__moddi3),
+ REG_SYM(__extendsfdf2),
+ REG_SYM(__truncdfsf2),
+ REG_SYM(__gtdf2),
+ REG_SYM(__umoddi3),
+ REG_SYM(__floatdidf),
+ REG_SYM(__divsf3),
+ REG_SYM(__fixdfdi),
+ REG_SYM(__floatundidf),
+};
+/* clang-format on */
+
+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);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "xtensa");
+}
+
+static uint32
+get_plt_item_size()
+{
+ return 0;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ (void)plt;
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+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;
+}
+
+/*
+ * CPU like esp32 can read and write data through the instruction bus, but only
+ * in a word aligned manner; non-word-aligned access will cause a CPU exception.
+ * This function uses a world aligned manner to write 16bit value to instruction
+ * addreess.
+ */
+static void
+put_imm16_to_addr(int16 imm16, int16 *addr)
+{
+ int8 bytes[8];
+ int32 *addr_aligned1, *addr_aligned2;
+
+ addr_aligned1 = (int32 *)((intptr_t)addr & ~3);
+
+ if ((intptr_t)addr % 4 != 3) {
+ *(int32 *)bytes = *addr_aligned1;
+ *(int16 *)(bytes + ((intptr_t)addr % 4)) = imm16;
+ *addr_aligned1 = *(int32 *)bytes;
+ }
+ else {
+ addr_aligned2 = (int32 *)(((intptr_t)addr + 3) & ~3);
+ *(int32 *)bytes = *addr_aligned1;
+ *(int32 *)(bytes + 4) = *addr_aligned2;
+ *(int16 *)(bytes + 3) = imm16;
+ memcpy(addr_aligned1, bytes, 8);
+ }
+}
+
+static union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+#if !defined(__packed)
+/*
+ * Note: This version check is a bit relaxed.
+ * The __packed__ attribute has been there since gcc 2 era.
+ */
+#if __GNUC__ >= 3
+#define __packed __attribute__((__packed__))
+#endif
+#endif
+
+typedef union {
+ struct l32r_le {
+ int8 other;
+ int16 imm16;
+ } __packed l;
+
+ struct l32r_be {
+ int16 imm16;
+ int8 other;
+ } __packed b;
+} l32r_insn_t;
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_XTENSA_32:
+ {
+ uint8 *insn_addr = target_section_addr + reloc_offset;
+ int32 initial_addend;
+ /* (S + A) */
+ if ((intptr_t)insn_addr & 3) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "instruction address unaligned.");
+ return false;
+ }
+ CHECK_RELOC_OFFSET(4);
+ initial_addend = *(int32 *)insn_addr;
+ *(uintptr_t *)insn_addr = (uintptr_t)symbol_addr + initial_addend
+ + (intptr_t)reloc_addend;
+ break;
+ }
+
+ case R_XTENSA_SLOT0_OP:
+ {
+ uint8 *insn_addr = target_section_addr + reloc_offset;
+ /* Currently only l32r instruction generates R_XTENSA_SLOT0_OP
+ * relocation */
+ l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr;
+ uint8 *reloc_addr;
+ int32 relative_offset /*, initial_addend */;
+ int16 imm16;
+
+ CHECK_RELOC_OFFSET(3); /* size of l32r instruction */
+
+ /*
+ imm16 = is_little_endian() ?
+ l32r_insn->l.imm16 : l32r_insn->b.imm16;
+ initial_addend = (int32)imm16 << 2;
+ */
+
+ reloc_addr =
+ (uint8 *)((uintptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ if ((intptr_t)reloc_addr & 3) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "relocation address unaligned.");
+ return false;
+ }
+
+ relative_offset =
+ (int32)((intptr_t)reloc_addr
+ - (((intptr_t)insn_addr + 3) & ~(intptr_t)3));
+ /* relative_offset += initial_addend; */
+
+ /* check relative offset boundary */
+ if (relative_offset < -256 * BH_KB || relative_offset > -4) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "target address out of range.\n"
+ "Try using `wamrc --size-level=0` to generate "
+ ".literal island.");
+ return false;
+ }
+
+ imm16 = (int16)(relative_offset >> 2);
+
+ /* write back the imm16 to the l32r instruction */
+
+ /* GCC >= 9 complains if we have a pointer that could be
+ * unaligned. This can happen because the struct is packed.
+ * These pragma are to suppress the warnings because the
+ * function put_imm16_to_addr already handles unaligned
+ * pointers correctly. */
+#if __GNUC__ >= 9
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+ if (is_little_endian())
+ put_imm16_to_addr(imm16, &l32r_insn->l.imm16);
+ else
+ put_imm16_to_addr(imm16, &l32r_insn->b.imm16);
+#if __GNUC__ >= 9
+#pragma GCC diagnostic pop
+#endif
+
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ (int)reloc_type);
+ return false;
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/LICENSE_NUTTX b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/LICENSE_NUTTX
new file mode 100644
index 000000000..43fa6abd1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/LICENSE_NUTTX
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/NOTICE_NUTTX b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/NOTICE_NUTTX
new file mode 100644
index 000000000..17227cb29
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/NOTICE_NUTTX
@@ -0,0 +1,5 @@
+Apache NuttX
+Copyright 2020 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf.h
new file mode 100644
index 000000000..9bdad6521
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf.h
@@ -0,0 +1,368 @@
+/****************************************************************************
+ * include/elf.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_ELF_H
+#define __INCLUDE_ELF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+#define EI_NIDENT 16 /* Size of e_ident[] */
+
+/* NOTE: elf64.h and elf32.h refer EI_NIDENT defined above */
+
+#include "elf64.h"
+#include "elf32.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Values for Elf_Ehdr::e_type */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_LOPROC 0xff00 /* Processor-specific */
+#define ET_HIPROC 0xffff /* Processor-specific */
+
+/* Values for Elf_Ehdr::e_machine (most of this were not included in the
+ * original SCO document but have been gleaned from elsewhere).
+ */
+
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola 68000 */
+#define EM_88K 5 /* Motorola 88000 */
+#define EM_486 6 /* Intel 486+ */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
+#define EM_PARISC 15 /* HPPA */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC64 */
+#define EM_ARM 40 /* ARM */
+#define EM_SH 42 /* SuperH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_H8_300 46
+#define EM_IA_64 50 /* HP/Intel IA-64 */
+#define EM_X86_64 62 /* AMD x86-64 */
+#define EM_S390 22 /* IBM S/390 */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Renesas M32R */
+#define EM_XTENSA 94 /* Tensilica Xtensa */
+#define EM_RISCV 243 /* RISC-V */
+#define EM_ALPHA 0x9026
+#define EM_CYGNUS_V850 0x9080
+#define EM_CYGNUS_M32R 0x9041
+#define EM_S390_OLD 0xa390
+#define EM_FRV 0x5441
+
+/* Values for Elf_Ehdr::e_version */
+
+#define EV_NONE 0 /* Invalid version */
+#define EV_CURRENT 1 /* The current version */
+
+/* Table 2. Ehe ELF identifier */
+
+#define EI_MAG0 0 /* File identification */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4 /* File class */
+#define EI_DATA 5 /* Data encoding */
+#define EI_VERSION 6 /* File version */
+#define EI_OSABI 7 /* OS ABI */
+#define EI_PAD 8 /* Start of padding bytes */
+
+/* EI_NIDENT is defined in "Included Files" section */
+
+#define EI_MAGIC_SIZE 4
+#define EI_MAGIC \
+ { \
+ 0x7f, 'E', 'L', 'F' \
+ }
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+
+/* Table 3. Values for EI_CLASS */
+
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+
+/* Table 4. Values for EI_DATA */
+
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB \
+ 1 /* Least significant byte occupying the lowest address \
+ */
+#define ELFDATA2MSB 2 /* Most significant byte occupying the lowest address */
+
+/* Table 6. Values for EI_OSABI */
+
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_SYSV 0 /* Alias. */
+#define ELFOSABI_HPUX 1 /* HP-UX */
+#define ELFOSABI_NETBSD 2 /* NetBSD. */
+#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */
+#define ELFOSABI_LINUX ELFOSABI_GNU
+/* Compatibility alias. */
+#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
+#define ELFOSABI_AIX 7 /* IBM AIX. */
+#define ELFOSABI_IRIX 8 /* SGI Irix. */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
+#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#ifndef ELF_OSABI
+#define ELF_OSABI ELFOSABI_NONE
+#endif
+
+/* Table 7: Special Section Indexes */
+
+#define SHN_UNDEF 0
+#define SHN_LOPROC 0xff00
+#define SHN_HIPROC 0xff1f
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+
+/* Figure 4-9: Section Types, sh_type */
+
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0xffffffff
+
+/* Figure 4-11: Section Attribute Flags, sh_flags */
+
+#define SHF_WRITE 1
+#define SHF_ALLOC 2
+#define SHF_EXECINSTR 4
+#define SHF_MASKPROC 0xf0000000
+
+/* Figure 4-16: Symbol Binding, ELF_ST_BIND */
+
+#define STB_LOCAL 0
+#define STB_GLOBAL 1
+#define STB_WEAK 2
+#define STB_LOPROC 13
+#define STB_HIPROC 15
+
+/* Figure 4-17: Symbol Types, ELF_ST_TYPE */
+
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+#define STT_LOPROC 13
+#define STT_HIPROC 15
+
+/* Figure 5-2: Segment Types, p_type */
+
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+
+/* Figure 5-3: Segment Flag Bits, p_flags */
+
+#define PF_X 1 /* Execute */
+#define PF_W 2 /* Write */
+#define PF_R 4 /* Read */
+#define PF_MASKPROC 0xf0000000 /* Unspecified */
+
+/* Figure 5-10: Dynamic Array Tags, d_tag */
+
+#define DT_NULL 0 /* d_un=ignored */
+#define DT_NEEDED 1 /* d_un=d_val */
+#define DT_PLTRELSZ 2 /* d_un=d_val */
+#define DT_PLTGOT 3 /* d_un=d_ptr */
+#define DT_HASH 4 /* d_un=d_ptr */
+#define DT_STRTAB 5 /* d_un=d_ptr */
+#define DT_SYMTAB 6 /* d_un=d_ptr */
+#define DT_RELA 7 /* d_un=d_ptr */
+#define DT_RELASZ 8 /* d_un=d_val */
+#define DT_RELAENT 9 /* d_un=d_val */
+#define DT_STRSZ 10 /* d_un=d_val */
+#define DT_SYMENT 11 /* d_un=d_val */
+#define DT_INIT 12 /* d_un=d_ptr */
+#define DT_FINI 13 /* d_un=d_ptr */
+#define DT_SONAME 14 /* d_un=d_val */
+#define DT_RPATH 15 /* d_un=d_val */
+#define DT_SYMBOLIC 16 /* d_un=ignored */
+#define DT_REL 17 /* d_un=d_ptr */
+#define DT_RELSZ 18 /* d_un=d_val */
+#define DT_RELENT 19 /* d_un=d_val */
+#define DT_PLTREL 20 /* d_un=d_val */
+#define DT_DEBUG 21 /* d_un=d_ptr */
+#define DT_TEXTREL 22 /* d_un=ignored */
+#define DT_JMPREL 23 /* d_un=d_ptr */
+#define DT_BINDNOW 24 /* d_un=ignored */
+#define DT_LOPROC 0x70000000 /* d_un=unspecified */
+#define DT_HIPROC 0x7fffffff /* d_un= unspecified */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_PRFPREG 2 /* Contains copy of fpregset struct. */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+#define NT_PRXREG 4 /* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
+#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV 6 /* Contains copy of auxv array */
+#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
+#define NT_ASRS 8 /* Contains copy of asrset struct */
+#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
+#define NT_PSINFO 13 /* Contains copy of psinfo struct */
+#define NT_PRCRED 14 /* Contains copy of prcred struct */
+#define NT_UTSNAME 15 /* Contains copy of utsname struct */
+#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */
+#define NT_SIGINFO 0x53494749
+/* Contains copy of siginfo_t,
+ * size might increase
+ */
+#define NT_FILE 0x46494c45
+/* Contains information about mapped
+ * files
+ */
+#define NT_PRXFPREG 0x46e62b7f
+/* Contains copy of user_fxsr_struct */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
+#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_PPC_TAR 0x103 /* Target Address Register */
+#define NT_PPC_PPR 0x104 /* Program Priority Register */
+#define NT_PPC_DSCR 0x105 /* Data Stream Control Register */
+#define NT_PPC_EBB 0x106 /* Event Based Branch Registers */
+#define NT_PPC_PMU 0x107 /* Performance Monitor Registers */
+#define NT_PPC_TM_CGPR 0x108 /* TM checkpointed GPR Registers */
+#define NT_PPC_TM_CFPR 0x109 /* TM checkpointed FPR Registers */
+#define NT_PPC_TM_CVMX 0x10a /* TM checkpointed VMX Registers */
+#define NT_PPC_TM_CVSX 0x10b /* TM checkpointed VSX Registers */
+#define NT_PPC_TM_SPR 0x10c /* TM Special Purpose Registers */
+#define NT_PPC_TM_CTAR \
+ 0x10d /* TM checkpointed Target Address \
+ * Register \
+ */
+#define NT_PPC_TM_CPPR \
+ 0x10e /* TM checkpointed Program Priority \
+ * Register \
+ */
+#define NT_PPC_TM_CDSCR \
+ 0x10f /* TM checkpointed Data Stream Control \
+ * Register \
+ */
+#define NT_PPC_PKEY \
+ 0x110 /* Memory Protection Keys \
+ * registers. \
+ */
+#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
+#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
+#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
+#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
+#define NT_S390_TIMER 0x301 /* s390 timer register */
+#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
+#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
+#define NT_S390_CTRS 0x304 /* s390 control registers */
+#define NT_S390_PREFIX 0x305 /* s390 prefix register */
+#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
+#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
+#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */
+#define NT_S390_VXRS_LOW \
+ 0x309 /* s390 vector registers 0-15 \
+ * upper half. \
+ */
+#define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31. */
+#define NT_S390_GS_CB 0x30b /* s390 guarded storage registers. */
+#define NT_S390_GS_BC \
+ 0x30c /* s390 guarded storage \
+ * broadcast control block. \
+ */
+#define NT_S390_RI_CB 0x30d /* s390 runtime instrumentation. */
+#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
+#define NT_ARM_TLS 0x401 /* ARM TLS register */
+#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */
+#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
+#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
+#define NT_ARM_SVE \
+ 0x405 /* ARM Scalable Vector Extension \
+ * registers \
+ */
+#define NT_ARM_PAC_MASK \
+ 0x406 /* ARM pointer authentication \
+ * code masks. \
+ */
+#define NT_ARM_PACA_KEYS \
+ 0x407 /* ARM pointer authentication \
+ * address keys. \
+ */
+#define NT_ARM_PACG_KEYS \
+ 0x408 /* ARM pointer authentication \
+ * generic key. \
+ */
+#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note. */
+#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers. */
+#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode. */
+#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers. */
+
+/* Legal values for the note segment descriptor types for object files. */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+#endif /* __INCLUDE_ELF_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf32.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf32.h
new file mode 100644
index 000000000..b4b27948e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf32.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+ * include/elf32.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_ELF32_H
+#define __INCLUDE_ELF32_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ELF32_ST_BIND(i) ((i) >> 4)
+#define ELF32_ST_TYPE(i) ((i)&0xf)
+#define ELF32_ST_INFO(b, t) (((b) << 4) | ((t)&0xf))
+
+/* Definitions for Elf32_Rel*::r_info */
+
+#define ELF32_R_SYM(i) ((i) >> 8)
+#define ELF32_R_TYPE(i) ((i)&0xff)
+#define ELF32_R_INFO(s, t) (((s) << 8) | ((t)&0xff))
+
+#if 0
+#define ELF_R_SYM(i) ELF32_R_SYM(i)
+#endif
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Figure 4.2: 32-Bit Data Types */
+
+typedef uint32_t Elf32_Addr; /* Unsigned program address */
+typedef uint16_t Elf32_Half; /* Unsigned medium integer */
+typedef uint32_t Elf32_Off; /* Unsigned file offset */
+typedef int32_t Elf32_Sword; /* Signed large integer */
+typedef uint32_t Elf32_Word; /* Unsigned large integer */
+
+/* Figure 4-3: ELF Header */
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry;
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+/* Figure 4-8: Section Header */
+
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+/* Figure 4-15: Symbol Table Entry */
+
+typedef struct {
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+/* Figure 4-19: Relocation Entries */
+
+typedef struct {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+/* Figure 5-1: Program Header */
+
+typedef struct {
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+/* Figure 5-7: Note Information */
+
+typedef struct {
+ Elf32_Word n_namesz; /* Length of the note's name. */
+ Elf32_Word n_descsz; /* Length of the note's descriptor. */
+ Elf32_Word n_type; /* Type of the note. */
+} Elf32_Nhdr;
+
+/* Figure 5-9: Dynamic Structure */
+
+typedef struct {
+ Elf32_Sword d_tag;
+ union {
+ Elf32_Word d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+#if 0
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+typedef Elf32_Nhdr Elf_Nhdr;
+typedef Elf32_Phdr Elf_Phdr;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Word Elf_Word;
+#endif
+
+#endif /* __INCLUDE_ELF32_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf64.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf64.h
new file mode 100644
index 000000000..499c737c1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf64.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+ * include/elf64.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_ELF64_H
+#define __INCLUDE_ELF64_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* See ELF-64 Object File Format: Version 1.5 Draft 2 */
+
+/* Definitions for Elf64_Rel*::r_info */
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
+#define ELF64_R_INFO(s, t) (((s) << 32) + ((t)&0xffffffffL))
+
+#if 0
+#define ELF_R_SYM(i) ELF64_R_SYM(i)
+#endif
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Table 1: ELF-64 Data Types */
+
+typedef uint64_t Elf64_Addr; /* Unsigned program address */
+typedef uint64_t Elf64_Off; /* Unsigned file offset */
+typedef uint16_t Elf64_Half; /* Unsigned medium integer */
+typedef uint32_t Elf64_Word; /* Unsigned long integer */
+typedef int32_t Elf64_Sword; /* Signed integer */
+typedef uint64_t Elf64_Xword; /* Unsigned long integer */
+typedef int64_t Elf64_Sxword; /* Signed large integer */
+
+/* Figure 2: ELF-64 Header */
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* ELF identification */
+ Elf64_Half e_type; /* Object file type */
+ Elf64_Half e_machine; /* Machine type */
+ Elf64_Word e_version; /* Object file version */
+ Elf64_Addr e_entry; /* Entry point address */
+ Elf64_Off e_phoff; /* Program header offset */
+ Elf64_Off e_shoff; /* Section header offset */
+ Elf64_Word e_flags; /* Processor-specific flags */
+ Elf64_Half e_ehsize; /* ELF header size */
+ Elf64_Half e_phentsize; /* Size of program header entry */
+ Elf64_Half e_phnum; /* Number of program header entry */
+ Elf64_Half e_shentsize; /* Size of section header entry */
+ Elf64_Half e_shnum; /* Number of section header entries */
+ Elf64_Half e_shstrndx; /* Section name string table index */
+} Elf64_Ehdr;
+
+/* Figure 3: ELF-64 Section Header */
+
+typedef struct {
+ Elf64_Word sh_name; /* Section name */
+ Elf64_Word sh_type; /* Section type */
+ Elf64_Xword sh_flags; /* Section attributes */
+ Elf64_Addr sh_addr; /* Virtual address in memory */
+ Elf64_Off sh_offset; /* Offset in file */
+ Elf64_Xword sh_size; /* Size of section */
+ Elf64_Word sh_link; /* Link to other section */
+ Elf64_Word sh_info; /* Miscellaneous information */
+ Elf64_Xword sh_addralign; /* Address alignment boundary */
+ Elf64_Xword sh_entsize; /* Size of entries, if section has table */
+} Elf64_Shdr;
+
+/* Figure 4: ELF-64 Symbol Table Entry */
+
+typedef struct {
+ Elf64_Word st_name; /* Symbol name */
+ unsigned char st_info; /* Type and Binding attributes */
+ unsigned char st_other; /* Reserved */
+ Elf64_Half st_shndx; /* Section table index */
+ Elf64_Addr st_value; /* Symbol value */
+ Elf64_Xword st_size; /* Size of object (e.g., common) */
+} Elf64_Sym;
+
+/* Figure 5: ELF-64 Relocation Entries */
+
+typedef struct {
+ Elf64_Addr r_offset; /* Address of reference */
+ Elf64_Xword r_info; /* Symbol index and type of relocation */
+} Elf64_Rel;
+
+typedef struct {
+ Elf64_Addr r_offset; /* Address of reference */
+ Elf64_Xword r_info; /* Symbol index and type of relocation */
+ Elf64_Sxword r_addend; /* Constant part of expression */
+} Elf64_Rela;
+
+/* Figure 6: ELF-64 Program Header Table Entry */
+
+typedef struct {
+ Elf64_Word p_type; /* Type of segment */
+ Elf64_Word p_flags; /* Segment attributes */
+ Elf64_Off p_offset; /* Offset in file */
+ Elf64_Addr p_vaddr; /* Virtual address in memory */
+ Elf64_Addr p_paddr; /* Reserved */
+ Elf64_Word p_filesz; /* Size of segment in file */
+ Elf64_Word p_memsz; /* Size of segment in memory */
+ Elf64_Word p_align; /* Alignment of segment */
+} Elf64_Phdr;
+
+/* Figure 7. Format of a Note Section */
+
+typedef struct {
+ Elf64_Word n_namesz; /* Length of the note's name. */
+ Elf64_Word n_descsz; /* Length of the note's descriptor. */
+ Elf64_Word n_type; /* Type of the note. */
+} Elf64_Nhdr;
+
+/* Figure 8: Dynamic Table Structure */
+
+typedef struct {
+ Elf64_Sxword d_tag;
+ union {
+ Elf64_Xword d_val;
+ Elf64_Addr d_ptr;
+ } d_un;
+} Elf64_Dyn;
+
+#if 0
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Rel Elf_Rel;
+typedef Elf64_Rela Elf_Rela;
+typedef Elf64_Nhdr Elf_Nhdr;
+typedef Elf64_Phdr Elf_Phdr;
+typedef Elf64_Sym Elf_Sym;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Word Elf_Word;
+#endif
+
+#endif /* __INCLUDE_ELF64_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.c
new file mode 100644
index 000000000..9fec281d3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include "elf.h"
+
+#include "aot_runtime.h"
+#include "bh_log.h"
+#include "elf_parser.h"
+
+bool
+is_ELF(void *buf)
+{
+ Elf32_Ehdr *eh = (Elf32_Ehdr *)buf;
+ if (!strncmp((char *)eh->e_ident, "\177ELF", 4)) {
+ LOG_VERBOSE("the buffer is ELF entry!");
+ return true;
+ }
+ LOG_VERBOSE("the buffer is not ELF entry!");
+ return false;
+}
+
+static bool
+is64Bit(Elf32_Ehdr *eh)
+{
+ if (eh->e_ident[EI_CLASS] == ELFCLASS64)
+ return true;
+ else
+ return false;
+}
+
+static bool
+is32Bit(Elf32_Ehdr *eh)
+{
+ if (eh->e_ident[EI_CLASS] == ELFCLASS32)
+ return true;
+ else
+ return false;
+}
+
+bool
+is_ELF64(void *buf)
+{
+ Elf64_Ehdr *eh = (Elf64_Ehdr *)buf;
+ if (!strncmp((char *)eh->e_ident, "\177ELF", 4)) {
+ LOG_VERBOSE("the buffer is ELF entry!");
+ return true;
+ }
+ LOG_VERBOSE("the buffer is not ELF entry!");
+ return false;
+}
+
+static void
+read_section_header_table(Elf32_Ehdr *eh, Elf32_Shdr *sh_table[])
+{
+ uint32_t i;
+ char *buf = (char *)eh;
+ buf += eh->e_shoff;
+ LOG_VERBOSE("str index = %d count=%d", eh->e_shstrndx, eh->e_shnum);
+ for (i = 0; i < eh->e_shnum; i++) {
+ sh_table[i] = (Elf32_Shdr *)buf;
+ buf += eh->e_shentsize;
+ }
+}
+
+static void
+read_section_header_table64(Elf64_Ehdr *eh, Elf64_Shdr *sh_table[])
+{
+ uint32_t i;
+ char *buf = (char *)eh;
+ buf += eh->e_shoff;
+
+ for (i = 0; i < eh->e_shnum; i++) {
+ sh_table[i] = (Elf64_Shdr *)buf;
+ buf += eh->e_shentsize;
+ }
+}
+
+static char *
+get_section(Elf32_Ehdr *eh, Elf32_Shdr *section_header)
+{
+ char *buf = (char *)eh;
+ return buf + section_header->sh_offset;
+}
+
+static char *
+get_section64(Elf64_Ehdr *eh, Elf64_Shdr *section_header)
+{
+ char *buf = (char *)eh;
+ return buf + section_header->sh_offset;
+}
+
+bool
+get_text_section(void *buf, uint64_t *offset, uint64_t *size)
+{
+ bool ret = false;
+ uint32 i;
+ char *sh_str;
+
+ if (is64Bit(buf)) {
+ Elf64_Ehdr *eh = (Elf64_Ehdr *)buf;
+ Elf64_Shdr **sh_table =
+ wasm_runtime_malloc(eh->e_shnum * sizeof(Elf64_Shdr *));
+ if (sh_table) {
+ read_section_header_table64(eh, sh_table);
+ sh_str = get_section64(eh, sh_table[eh->e_shstrndx]);
+ for (i = 0; i < eh->e_shnum; i++) {
+ if (!strcmp(sh_str + sh_table[i]->sh_name, ".text")) {
+ *offset = sh_table[i]->sh_offset;
+ *size = sh_table[i]->sh_size;
+ sh_table[i]->sh_addr =
+ (Elf64_Addr)(uintptr_t)((char *)buf
+ + sh_table[i]->sh_offset);
+ ret = true;
+ break;
+ }
+ }
+ wasm_runtime_free(sh_table);
+ }
+ }
+ else if (is32Bit(buf)) {
+ Elf32_Ehdr *eh = (Elf32_Ehdr *)buf;
+ Elf32_Shdr **sh_table =
+ wasm_runtime_malloc(eh->e_shnum * sizeof(Elf32_Shdr *));
+ if (sh_table) {
+ read_section_header_table(eh, sh_table);
+ sh_str = get_section(eh, sh_table[eh->e_shstrndx]);
+ for (i = 0; i < eh->e_shnum; i++) {
+ if (!strcmp(sh_str + sh_table[i]->sh_name, ".text")) {
+ *offset = sh_table[i]->sh_offset;
+ *size = sh_table[i]->sh_size;
+ sh_table[i]->sh_addr =
+ (Elf32_Addr)(uintptr_t)((char *)buf
+ + sh_table[i]->sh_offset);
+ ret = true;
+ break;
+ }
+ }
+ wasm_runtime_free(sh_table);
+ }
+ }
+
+ return ret;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.h
new file mode 100644
index 000000000..887d82fa9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/elf_parser.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _ELF_PARSER_H_
+#define _ELF_PARSER_H_
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+is_ELF(void *buf);
+
+bool
+is_ELF64(void *buf);
+
+bool
+get_text_section(void *buf, uint64_t *offset, uint64_t *size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.c
new file mode 100644
index 000000000..310662f55
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "bh_platform.h"
+#include "../../interpreter/wasm_runtime.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+/* This must be kept in sync with gdb/gdb/jit.h */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* clang-format off */
+typedef enum JITAction {
+ JIT_NOACTION = 0,
+ JIT_REGISTER_FN,
+ JIT_UNREGISTER_FN
+} JITAction;
+/* clang-format on */
+
+typedef struct JITCodeEntry {
+ struct JITCodeEntry *next_;
+ struct JITCodeEntry *prev_;
+ const uint8 *symfile_addr_;
+ uint64 symfile_size_;
+} JITCodeEntry;
+
+typedef struct JITDescriptor {
+ uint32 version_;
+ uint32 action_flag_;
+ JITCodeEntry *relevant_entry_;
+ JITCodeEntry *first_entry_;
+} JITDescriptor;
+
+/* LLVM has already define this */
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
+/**
+ * GDB will place breakpoint into this function.
+ * To prevent GCC from inlining or removing it we place noinline attribute
+ * and inline assembler statement inside.
+ */
+void __attribute__((noinline)) __jit_debug_register_code();
+
+void __attribute__((noinline)) __jit_debug_register_code()
+{
+ int x;
+ *(char *)&x = '\0';
+}
+
+/**
+ * GDB will inspect contents of this descriptor.
+ * Static initialization is necessary to prevent GDB from seeing
+ * uninitialized descriptor.
+ */
+
+JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, NULL, NULL };
+#else
+extern void
+__jit_debug_register_code();
+extern JITDescriptor __jit_debug_descriptor;
+#endif
+
+/**
+ * Call __jit_debug_register_code indirectly via global variable.
+ * This gives the debugger an easy way to inject custom code to
+ * handle the events.
+ */
+void (*__jit_debug_register_code_ptr)() = __jit_debug_register_code;
+
+#ifdef __cplusplus
+}
+#endif
+
+typedef struct WASMJITDebugEngine {
+ korp_mutex jit_entry_lock;
+ bh_list jit_entry_list;
+} WASMJITDebugEngine;
+
+typedef struct WASMJITEntryNode {
+ struct WASMJITEntryNode *next;
+ JITCodeEntry *entry;
+} WASMJITEntryNode;
+
+static WASMJITDebugEngine *jit_debug_engine;
+
+static JITCodeEntry *
+CreateJITCodeEntryInternal(const uint8 *symfile_addr, uint64 symfile_size)
+{
+ JITCodeEntry *entry;
+
+ os_mutex_lock(&jit_debug_engine->jit_entry_lock);
+
+ if (!(entry = wasm_runtime_malloc(sizeof(JITCodeEntry)))) {
+ LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory");
+ os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
+ return NULL;
+ }
+ entry->symfile_addr_ = symfile_addr;
+ entry->symfile_size_ = symfile_size;
+ entry->prev_ = NULL;
+
+ entry->next_ = __jit_debug_descriptor.first_entry_;
+ if (entry->next_ != NULL) {
+ entry->next_->prev_ = entry;
+ }
+ __jit_debug_descriptor.first_entry_ = entry;
+ __jit_debug_descriptor.relevant_entry_ = entry;
+
+ __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
+
+ (*__jit_debug_register_code_ptr)();
+
+ os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
+ return entry;
+}
+
+static void
+DestroyJITCodeEntryInternal(JITCodeEntry *entry)
+{
+ os_mutex_lock(&jit_debug_engine->jit_entry_lock);
+
+ if (entry->prev_ != NULL) {
+ entry->prev_->next_ = entry->next_;
+ }
+ else {
+ __jit_debug_descriptor.first_entry_ = entry->next_;
+ }
+
+ if (entry->next_ != NULL) {
+ entry->next_->prev_ = entry->prev_;
+ }
+
+ __jit_debug_descriptor.relevant_entry_ = entry;
+ __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
+ (*__jit_debug_register_code_ptr)();
+
+ wasm_runtime_free(entry);
+
+ os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
+}
+
+bool
+jit_debug_engine_init()
+{
+ if (jit_debug_engine) {
+ return true;
+ }
+
+ if (!(jit_debug_engine = wasm_runtime_malloc(sizeof(WASMJITDebugEngine)))) {
+ LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory");
+ return false;
+ }
+ memset(jit_debug_engine, 0, sizeof(WASMJITDebugEngine));
+
+ if (os_mutex_init(&jit_debug_engine->jit_entry_lock) != 0) {
+ wasm_runtime_free(jit_debug_engine);
+ jit_debug_engine = NULL;
+ return false;
+ }
+
+ bh_list_init(&jit_debug_engine->jit_entry_list);
+ return true;
+}
+
+void
+jit_debug_engine_destroy()
+{
+ if (jit_debug_engine) {
+ WASMJITEntryNode *node, *node_next;
+
+ /* Destroy all nodes */
+ node = bh_list_first_elem(&jit_debug_engine->jit_entry_list);
+ while (node) {
+ node_next = bh_list_elem_next(node);
+ DestroyJITCodeEntryInternal(node->entry);
+ bh_list_remove(&jit_debug_engine->jit_entry_list, node);
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+
+ /* Destroy JIT Debug Engine */
+ os_mutex_destroy(&jit_debug_engine->jit_entry_lock);
+ wasm_runtime_free(jit_debug_engine);
+ jit_debug_engine = NULL;
+ }
+}
+
+bool
+jit_code_entry_create(const uint8 *symfile_addr, uint64 symfile_size)
+{
+ JITCodeEntry *entry;
+ WASMJITEntryNode *node;
+
+ if (!(node = wasm_runtime_malloc(sizeof(WASMJITEntryNode)))) {
+ LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory");
+ return false;
+ }
+
+ entry = CreateJITCodeEntryInternal(symfile_addr, symfile_size);
+
+ if (!entry) {
+ wasm_runtime_free(node);
+ return false;
+ }
+
+ node->entry = entry;
+ os_mutex_lock(&jit_debug_engine->jit_entry_lock);
+ bh_list_insert(&jit_debug_engine->jit_entry_list, node);
+ os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
+ return true;
+}
+
+void
+jit_code_entry_destroy(const uint8 *symfile_addr)
+{
+ WASMJITEntryNode *node;
+
+ node = bh_list_first_elem(&jit_debug_engine->jit_entry_list);
+ while (node) {
+ WASMJITEntryNode *next_node = bh_list_elem_next(node);
+ if (node->entry->symfile_addr_ == symfile_addr) {
+ DestroyJITCodeEntryInternal(node->entry);
+ os_mutex_lock(&jit_debug_engine->jit_entry_lock);
+ bh_list_remove(&jit_debug_engine->jit_entry_list, node);
+ os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
+ wasm_runtime_free(node);
+ }
+ node = next_node;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.h
new file mode 100644
index 000000000..5e3e36519
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/debug/jit_debug.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_DEBUG_H_
+#define _JIT_DEBUG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_debug_engine_init();
+
+void
+jit_debug_engine_destroy();
+
+bool
+jit_code_entry_create(const uint8 *symfile_addr, uint64 symfile_size);
+
+void
+jit_code_entry_destroy(const uint8 *symfile_addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/iwasm_aot.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/iwasm_aot.cmake
new file mode 100644
index 000000000..8014f2372
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/iwasm_aot.cmake
@@ -0,0 +1,40 @@
+# 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)
+
+if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c)
+elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c)
+elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c)
+elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c)
+elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_thumb.c)
+elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_mips.c)
+elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_xtensa.c)
+elseif (WAMR_BUILD_TARGET MATCHES "RISCV*")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_riscv.c)
+elseif (WAMR_BUILD_TARGET STREQUAL "ARC")
+ set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arc.c)
+else ()
+ message (FATAL_ERROR "Build target isn't set")
+endif ()
+
+if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
+ add_definitions(-DWASM_ENABLE_DEBUG_AOT=1)
+ file(GLOB debug_source ${IWASM_AOT_DIR}/debug/*.c)
+endif()
+
+set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/SConscript
new file mode 100644
index 000000000..0a55f244b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/SConscript
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import re
+
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+
+src = Glob('*.c')
+
+if rtconfig.ARCH == 'arm':
+ if re.match('^cortex-m.*', rtconfig.CPU):
+ src += ['arch/invokeNative_thumb.s']
+ elif re.match('^cortex-a.*', rtconfig.CPU):
+ src += ['arch/invokeNative_arm.s']
+elif rtconfig.ARCH == 'ia32':
+ src += ['arch/invokeNative_ia32.s']
+
+CPPPATH = [cwd, cwd + '/../include']
+
+group = DefineGroup('iwasm_common', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64.s
new file mode 100644
index 000000000..ea5cbcb36
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64.s
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * x0 function ptr
+ * x1 argv
+ * x2 nstacks
+ */
+
+ sub sp, sp, #0x30
+ stp x19, x20, [sp, #0x20] /* save the registers */
+ stp x21, x22, [sp, #0x10]
+ stp x23, x24, [sp, #0x0]
+
+ mov x19, x0 /* x19 = function ptr */
+ mov x20, x1 /* x20 = argv */
+ mov x21, x2 /* x21 = nstacks */
+ mov x22, sp /* save the sp before call function */
+
+ /* Fill in float-point registers */
+ ldp d0, d1, [x20], #16 /* d0 = argv[0], d1 = argv[1] */
+ ldp d2, d3, [x20], #16 /* d2 = argv[2], d3 = argv[3] */
+ ldp d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */
+ ldp d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */
+
+ /* Fill integer registers */
+ ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
+ ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
+ ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
+ ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
+
+ /* Now x20 points to stack args */
+
+ /* Directly call the fucntion if no args in stack */
+ cmp x21, #0
+ beq call_func
+
+ /* Fill all stack args: reserve stack space and fill one by one */
+ mov x23, sp
+ bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */
+ lsl x23, x21, #3 /* x23 = nstacks * 8 */
+ add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */
+ bic x23, x23, #15
+ sub sp, sp, x23 /* reserved stack space for stack arguments */
+ mov x23, sp
+
+loop_stack_args: /* copy stack arguments to stack */
+ cmp x21, #0
+ beq call_func
+ ldr x24, [x20], #8
+ str x24, [x23], #8
+ sub x21, x21, #1
+ b loop_stack_args
+
+call_func:
+ mov x20, x30 /* save x30(lr) */
+ blr x19
+ mov sp, x22 /* restore sp which is saved before calling fuction*/
+
+return:
+ mov x30, x20 /* restore x30(lr) */
+ ldp x19, x20, [sp, #0x20] /* restore the registers in stack */
+ ldp x21, x22, [sp, #0x10]
+ ldp x23, x24, [sp, #0x0]
+ add sp, sp, #0x30 /* restore sp */
+ ret
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64_simd.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64_simd.s
new file mode 100644
index 000000000..a6ccc1508
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_aarch64_simd.s
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 Intel Corporation Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * x0 function ptr
+ * x1 argv
+ * x2 nstacks
+ */
+
+ sub sp, sp, #0x30
+ stp x19, x20, [sp, #0x20] /* save the registers */
+ stp x21, x22, [sp, #0x10]
+ stp x23, x24, [sp, #0x0]
+
+ mov x19, x0 /* x19 = function ptr */
+ mov x20, x1 /* x20 = argv */
+ mov x21, x2 /* x21 = nstacks */
+ mov x22, sp /* save the sp before call function */
+
+ /* Fill in float-point registers */
+ ld1 {v0.2D, v1.2D, v2.2D, v3.2D}, [x20], #64 /* v0 = argv[0], v1 = argv[1], v2 = argv[2], v3 = argv[3]*/
+ ld1 {v4.2D, v5.2D, v6.2D, v7.2D}, [x20], #64 /* v4 = argv[4], v5 = argv[5], v6 = argv[6], v7 = argv[7]*/
+
+ /* Fill inteter registers */
+ ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
+ ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
+ ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
+ ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
+
+ /* Now x20 points to stack args */
+
+ /* Directly call the fucntion if no args in stack */
+ cmp x21, #0
+ beq call_func
+
+ /* Fill all stack args: reserve stack space and fill one by one */
+ mov x23, sp
+ bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */
+ lsl x23, x21, #3 /* x23 = nstacks * 8 */
+ add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */
+ bic x23, x23, #15
+ sub sp, sp, x23 /* reserved stack space for stack arguments */
+ mov x23, sp
+
+loop_stack_args: /* copy stack arguments to stack */
+ cmp x21, #0
+ beq call_func
+ ldr x24, [x20], #8
+ str x24, [x23], #8
+ sub x21, x21, #1
+ b loop_stack_args
+
+call_func:
+ mov x20, x30 /* save x30(lr) */
+ blr x19
+ mov sp, x22 /* restore sp which is saved before calling fuction*/
+
+return:
+ mov x30, x20 /* restore x30(lr) */
+ ldp x19, x20, [sp, #0x20] /* restore the registers in stack */
+ ldp x21, x22, [sp, #0x10]
+ ldp x23, x24, [sp, #0x0]
+ add sp, sp, #0x30 /* restore sp */
+ ret
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arc.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arc.s
new file mode 100644
index 000000000..e448eea65
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arc.s
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ * r0: function ptr
+ * r1: argv
+ * r2: nstacks
+ * ARC ABI:
+ * r0-r7: function arguments, caller-saved
+ * r8-r12: temp registers, caller-saved
+ */
+
+ push_s blink /* push return addr */
+ st.aw fp, [sp, -4] /* push fp */
+ mov fp, sp /* fp = sp */
+
+ mov r8, r0 /* r8 = func_ptr */
+ mov r9, r1 /* r9 = argv */
+ mov r10, r2 /* r10 = nstacks */
+
+ ld r0, [r9, 0] /* r0 = argv[0] */
+ ld r1, [r9, 4] /* r1 = argv[1] */
+ ld r2, [r9, 8] /* r2 = argv[2] */
+ ld r3, [r9, 12] /* r3 = argv[3] */
+ ld r4, [r9, 16] /* r4 = argv[4] */
+ ld r5, [r9, 20] /* r5 = argv[5] */
+ ld r6, [r9, 24] /* r6 = argv[6] */
+ ld r7, [r9, 28] /* r7 = argv[7] */
+
+ add r9, r9, 32 /* r9 = stack_args */
+ breq r10, 0, call_func /* if (r10 == 0) goto call_func */
+
+ asl r11, r10, 2 /* r11 = nstacks * 4 */
+ sub sp, sp, r11 /* sp = sp - nstacks * 4 */
+ and sp, sp, ~7 /* make sp 8-byte aligned */
+ mov r11, sp /* r11 = sp */
+
+loop_stack_args:
+ breq r10, 0, call_func /* if (r10 == 0) goto call_func */
+ ld r12, [r9] /* r12 = stack_args[i] */
+ st r12, [r11] /* stack[i] = r12 */
+ add r9, r9, 4 /* r9 = r9 + 4 */
+ add r11, r11, 4 /* r11 = r11 + 4 */
+ sub r10, r10, 1 /* r10 = r10 + 1 */
+ j loop_stack_args
+
+call_func:
+ jl [r8] /* call function */
+
+ mov sp, fp /* sp = fp */
+ ld.ab fp, [sp, 4] /* pop fp */
+ pop_s blink /* pop return addr */
+ j_s [blink] /* ret */
+ nop_s
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm.s
new file mode 100644
index 000000000..bfe8e3b09
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm.s
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * r0 function ptr
+ * r1 argv
+ * r2 argc
+ */
+
+ stmfd sp!, {r4, r5, r6, r7, lr}
+ sub sp, sp, #4 /* make sp 8 byte aligned */
+ mov ip, r0 /* ip = function ptr */
+ mov r4, r1 /* r4 = argv */
+ mov r5, r2 /* r5 = argc */
+
+ 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] = exec_env */
+ cmp r5, #1
+ beq call_func
+
+ ldr r1, [r4], #4 /* r1 = argv[1] */
+ cmp r5, #2
+ beq call_func
+
+ ldr r2, [r4], #4 /* r2 = argv[2] */
+ cmp r5, #3
+ beq call_func
+
+ ldr r3, [r4], #4 /* r3 = argv[3] */
+ cmp r5, #4
+ beq call_func
+
+ sub r5, r5, #4 /* argc -= 4, now we have r0 ~ r3 */
+
+ /* Ensure address is 8 byte aligned */
+ mov r6, r5, lsl#2 /* r6 = argc * 4 */
+ add r6, r6, #7 /* r6 = (r6 + 7) & ~7 */
+ bic r6, r6, #7
+ sub sp, sp, r6 /* reserved stack space for left arguments */
+ mov r7, sp
+
+loop_args: /* copy left arguments to stack */
+ cmp r5, #0
+ beq call_func
+ ldr lr, [r4], #4
+ str lr, [r7], #4
+ sub r5, r5, #1
+ b loop_args
+
+call_func:
+ blx ip
+ add sp, sp, r6 /* restore sp */
+
+return:
+ add sp, sp, #4
+ ldmfd sp!, {r4, r5, r6, r7, lr}
+ bx lr
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm_vfp.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm_vfp.s
new file mode 100644
index 000000000..78a4bab82
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_arm_vfp.s
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * r0 function ptr
+ * r1 argv
+ * r2 nstacks
+ */
+
+ stmfd sp!, {r4, r5, r6, r7, lr}
+ sub sp, sp, #4 /* make sp 8 byte aligned */
+ 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 one 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:
+ add sp, sp, #4 /* make sp 8 byte aligned */
+ ldmfd sp!, {r4, r5, r6, r7, lr}
+ bx lr
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.asm b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.asm
new file mode 100644
index 000000000..df8115397
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.asm
@@ -0,0 +1,62 @@
+;
+; Copyright (C) 2019 Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+
+_TEXT SEGMENT
+ ; rcx func_ptr
+ ; rdx argv
+ ; r8 n_stacks
+
+invokeNative PROC
+ push rbp
+ mov rbp, rsp
+
+ mov r10, rcx ; func_ptr
+ mov rax, rdx ; argv
+ mov rcx, r8 ; n_stacks
+
+; fill all fp args
+ movsd xmm0, qword ptr [rax + 0]
+ movsd xmm1, qword ptr [rax + 8]
+ movsd xmm2, qword ptr [rax + 16]
+ movsd xmm3, qword ptr [rax + 24]
+
+; check for stack args
+ cmp rcx, 0
+ jz cycle_end
+
+ mov rdx, rsp
+ and rdx, 15
+ jz no_abort
+ int 3
+no_abort:
+ mov rdx, rcx
+ and rdx, 1
+ shl rdx, 3
+ sub rsp, rdx
+
+; store stack args
+ lea r9, qword ptr [rax + rcx * 8 + 56]
+ sub r9, rsp ; offset
+cycle:
+ push qword ptr [rsp + r9]
+ loop cycle
+
+cycle_end:
+ mov rcx, [rax + 32]
+ mov rdx, [rax + 40]
+ mov r8, [rax + 48]
+ mov r9, [rax + 56]
+
+ sub rsp, 32 ; shadow space
+
+ call r10
+ leave
+ ret
+
+invokeNative ENDP
+
+_TEXT ENDS
+
+END
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.s
new file mode 100644
index 000000000..739e84e4c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64.s
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+.globl invokeNative
+ .type invokeNative, @function
+invokeNative:
+#else
+.globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+ /* rdi - function ptr */
+ /* rsi - argv */
+ /* rdx - n_stacks */
+
+ push %rbp
+ mov %rsp, %rbp
+
+ mov %rdx, %r10
+ mov %rsp, %r11 /* Check that stack is aligned on */
+ and $8, %r11 /* 16 bytes. This code may be removed */
+ je check_stack_succ /* when we are sure that compiler always */
+ int3 /* calls us with aligned stack */
+check_stack_succ:
+ mov %r10, %r11 /* Align stack on 16 bytes before pushing */
+ and $1, %r11 /* stack arguments in case we have an odd */
+ shl $3, %r11 /* number of stack arguments */
+ sub %r11, %rsp
+ /* store memory args */
+ movq %rdi, %r11 /* func ptr */
+ movq %r10, %rcx /* counter */
+ lea 64+48-8(%rsi,%rcx,8), %r10
+ sub %rsp, %r10
+ cmpq $0, %rcx
+ je push_args_end
+push_args:
+ push 0(%rsp,%r10)
+ loop push_args
+push_args_end:
+ /* fill all fp args */
+ movq 0x00(%rsi), %xmm0
+ movq 0x08(%rsi), %xmm1
+ movq 0x10(%rsi), %xmm2
+ movq 0x18(%rsi), %xmm3
+ movq 0x20(%rsi), %xmm4
+ movq 0x28(%rsi), %xmm5
+ movq 0x30(%rsi), %xmm6
+ movq 0x38(%rsi), %xmm7
+
+ /* fill all int args */
+ movq 0x40(%rsi), %rdi
+ movq 0x50(%rsi), %rdx
+ movq 0x58(%rsi), %rcx
+ movq 0x60(%rsi), %r8
+ movq 0x68(%rsi), %r9
+ movq 0x48(%rsi), %rsi
+
+ call *%r11
+ leave
+ ret
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.asm b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.asm
new file mode 100644
index 000000000..084a0f667
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.asm
@@ -0,0 +1,62 @@
+;
+; Copyright (C) 2019 Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+
+_TEXT SEGMENT
+ ; rcx func_ptr
+ ; rdx argv
+ ; r8 n_stacks
+
+invokeNative PROC
+ push rbp
+ mov rbp, rsp
+
+ mov r10, rcx ; func_ptr
+ mov rax, rdx ; argv
+ mov rcx, r8 ; n_stacks
+
+; fill all fp args
+ movdqu xmm0, xmmword ptr [rax + 0]
+ movdqu xmm1, xmmword ptr [rax + 16]
+ movdqu xmm2, xmmword ptr [rax + 32]
+ movdqu xmm3, xmmword ptr [rax + 48]
+
+; check for stack args
+ cmp rcx, 0
+ jz cycle_end
+
+ mov rdx, rsp
+ and rdx, 15
+ jz no_abort
+ int 3
+no_abort:
+ mov rdx, rcx
+ and rdx, 1
+ shl rdx, 3
+ sub rsp, rdx
+
+; store stack args
+ lea r9, qword ptr [rax + rcx * 8 + 88]
+ sub r9, rsp ; offset
+cycle:
+ push qword ptr [rsp + r9]
+ loop cycle
+
+cycle_end:
+ mov rcx, [rax + 64]
+ mov rdx, [rax + 72]
+ mov r8, [rax + 80]
+ mov r9, [rax + 88]
+
+ sub rsp, 32 ; shadow space
+
+ call r10
+ leave
+ ret
+
+invokeNative ENDP
+
+_TEXT ENDS
+
+END
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.s
new file mode 100644
index 000000000..0043ac941
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_em64_simd.s
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+.globl invokeNative
+ .type invokeNative, @function
+invokeNative:
+#else
+.globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+ /* rdi - function ptr */
+ /* rsi - argv */
+ /* rdx - n_stacks */
+
+ push %rbp
+ mov %rsp, %rbp
+
+ mov %rdx, %r10
+ mov %rsp, %r11 /* Check that stack is aligned on */
+ and $8, %r11 /* 16 bytes. This code may be removed */
+ je check_stack_succ /* when we are sure that compiler always */
+ int3 /* calls us with aligned stack */
+check_stack_succ:
+ mov %r10, %r11 /* Align stack on 16 bytes before pushing */
+ and $1, %r11 /* stack arguments in case we have an odd */
+ shl $3, %r11 /* number of stack arguments */
+ sub %r11, %rsp
+ /* store memory args */
+ movq %rdi, %r11 /* func ptr */
+ movq %r10, %rcx /* counter */
+ lea 128+48-8(%rsi,%rcx,8), %r10
+ sub %rsp, %r10
+ cmpq $0, %rcx
+ je push_args_end
+push_args:
+ push 0(%rsp,%r10)
+ loop push_args
+push_args_end:
+ /* fill all fp args */
+ movdqu 0x00(%rsi), %xmm0
+ movdqu 0x10(%rsi), %xmm1
+ movdqu 0x20(%rsi), %xmm2
+ movdqu 0x30(%rsi), %xmm3
+ movdqu 0x40(%rsi), %xmm4
+ movdqu 0x50(%rsi), %xmm5
+ movdqu 0x60(%rsi), %xmm6
+ movdqu 0x70(%rsi), %xmm7
+
+ /* fill all int args */
+ movq 0x80(%rsi), %rdi
+ movq 0x90(%rsi), %rdx
+ movq 0x98(%rsi), %rcx
+ movq 0xa0(%rsi), %r8
+ movq 0xa8(%rsi), %r9
+ movq 0x88(%rsi), %rsi
+
+ call *%r11
+ leave
+ ret
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_general.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_general.c
new file mode 100644
index 000000000..4799c9fa8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_general.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "../wasm_runtime_common.h"
+#include "../wasm_exec_env.h"
+
+void
+invokeNative(void (*native_code)(), uint32 argv[], uint32 argc)
+{
+ bh_assert(argc >= sizeof(WASMExecEnv *) / sizeof(uint32));
+
+ switch (argc) {
+ case 0:
+ native_code();
+ break;
+ case 1:
+ native_code(argv[0]);
+ break;
+ case 2:
+ native_code(argv[0], argv[1]);
+ break;
+ case 3:
+ native_code(argv[0], argv[1], argv[2]);
+ break;
+ case 4:
+ native_code(argv[0], argv[1], argv[2], argv[3]);
+ break;
+ case 5:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4]);
+ break;
+ case 6:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+ break;
+ case 7:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6]);
+ break;
+ case 8:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7]);
+ break;
+ case 9:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8]);
+ break;
+ case 10:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9]);
+ break;
+ case 11:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10]);
+ break;
+ case 12:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
+ break;
+ case 13:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12]);
+ break;
+ case 14:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13]);
+ break;
+ case 15:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14]);
+ break;
+ case 16:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14], argv[15]);
+ break;
+ case 17:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14], argv[15], argv[16]);
+ break;
+ case 18:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14], argv[15], argv[16],
+ argv[17]);
+ break;
+ case 19:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14], argv[15], argv[16],
+ argv[17], argv[18]);
+ break;
+ case 20:
+ native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], argv[7], argv[8], argv[9], argv[10], argv[11],
+ argv[12], argv[13], argv[14], argv[15], argv[16],
+ argv[17], argv[18], argv[19]);
+ break;
+ default:
+ {
+ /* FIXME: If this happen, add more cases. */
+ 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.asm b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.asm
new file mode 100644
index 000000000..c52c8d6ed
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.asm
@@ -0,0 +1,27 @@
+;
+; Copyright (C) 2019 Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+
+ .386
+ .model flat
+ .code
+_invokeNative PROC
+ push ebp
+ mov ebp,esp
+ mov ecx, [ebp+16] ; ecx = argc */
+ mov edx, [ebp+12] ; edx = argv */
+ test ecx, ecx
+ jz skip_push_args ; if ecx == 0, skip pushing arguments */
+ lea edx, [edx+ecx*4-4] ; edx = edx + ecx * 4 - 4 */
+ sub edx,esp ; edx = edx - esp */
+loop_push:
+ push [esp+edx]
+ loop loop_push ; loop ecx counts */
+skip_push_args:
+ mov edx, [ebp+8] ; edx = func_ptr */
+ call edx
+ leave
+ ret
+_invokeNative ENDP
+END \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.s
new file mode 100644
index 000000000..de1c1a5e1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_ia32.s
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+.globl invokeNative
+ .type invokeNative, @function
+invokeNative:
+#else
+.globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+ push %ebp
+ movl %esp, %ebp
+ movl 16(%ebp), %ecx /* ecx = argc */
+ leal 2(%ecx), %edx /* edx = ecx + 2 (count return address and saved ebp) */
+ andl $3, %edx /* edx = edx % 4 */
+ jz stack_aligned /* if edx == 0, stack is already 16 bytes aligned */
+ leal -16(%esp, %edx, 4), %esp /* esp = esp - 16 + edx * 4 */
+stack_aligned:
+ test %ecx, %ecx
+ jz skip_push_args /* if ecx == 0, skip pushing arguments */
+ movl 12(%ebp), %edx /* edx = argv */
+ leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */
+ subl %esp, %edx /* edx = edx - esp */
+1:
+ push 0(%esp,%edx)
+ loop 1b /* loop ecx counts */
+skip_push_args:
+ movl 8(%ebp), %edx /* edx = func_ptr */
+ call *%edx
+ leave
+ ret
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64.s
new file mode 100644
index 000000000..cefaa28c1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64.s
@@ -0,0 +1,57 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+.text
+.align 2
+.globl invokeNative
+invokeNative:
+
+ # %rcx func_ptr
+ # %rdx argv
+ # %r8 n_stacks
+
+ push %rbp
+ mov %rsp, %rbp
+
+ mov %rcx, %r10 # func_ptr
+ mov %rdx, %rax # argv
+ mov %r8, %rcx # n_stacks
+
+ # fill all fp args
+ movsd 0(%rax), %xmm0
+ movsd 8(%rax), %xmm1
+ movsd 16(%rax), %xmm2
+ movsd 24(%rax), %xmm3
+
+ # check for stack args
+ cmp $0, %rcx
+ jz cycle_end
+
+ mov %rsp, %rdx
+ and $15, %rdx
+ jz no_abort
+ int $3
+no_abort:
+ mov %rcx, %rdx
+ and $1, %rdx
+ shl $3, %rdx
+ sub %rdx, %rsp
+
+ # store stack args
+ lea 56(%rax, %rcx, 8), %r9
+ sub %rsp, %r9 # offset
+cycle:
+ push (%rsp, %r9)
+ loop cycle
+
+cycle_end:
+ mov 32(%rax), %rcx
+ mov 40(%rax), %rdx
+ mov 48(%rax), %r8
+ mov 56(%rax), %r9
+
+ sub $32, %rsp # shadow space
+
+ call *%r10
+ leave
+ ret
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64_simd.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64_simd.s
new file mode 100644
index 000000000..48ae52480
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mingw_x64_simd.s
@@ -0,0 +1,57 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+.text
+.align 2
+.globl invokeNative
+invokeNative:
+
+ # %rcx func_ptr
+ # %rdx argv
+ # %r8 n_stacks
+
+ push %rbp
+ mov %rsp, %rbp
+
+ mov %rcx, %r10 # func_ptr
+ mov %rdx, %rax # argv
+ mov %r8, %rcx # n_stacks
+
+ # fill all fp args
+ movdqu 0(%rax), %xmm0
+ movdqu 16(%rax), %xmm1
+ movdqu 32(%rax), %xmm2
+ movdqu 48(%rax), %xmm3
+
+ # check for stack args
+ cmp $0, %rcx
+ jz cycle_end
+
+ mov %rsp, %rdx
+ and $15, %rdx
+ jz no_abort
+ int $3
+no_abort:
+ mov %rcx, %rdx
+ and $1, %rdx
+ shl $3, %rdx
+ sub %rdx, %rsp
+
+ # store stack args
+ lea 88(%rax, %rcx, 8), %r9
+ sub %rsp, %r9 # offset
+cycle:
+ push (%rsp, %r9)
+ loop cycle
+
+cycle_end:
+ mov 64(%rax), %rcx
+ mov 72(%rax), %rdx
+ mov 80(%rax), %r8
+ mov 88(%rax), %r9
+
+ sub $32, %rsp # shadow space
+
+ call *%r10
+ leave
+ ret
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mips.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mips.s
new file mode 100644
index 000000000..645f4f2ec
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_mips.s
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+ .text
+ .align 2
+ .globl invokeNative
+ .ent invokeNative
+ .type invokeNative, @function
+
+/**
+ * On function entry parameters:
+ * $4 = func_ptr
+ * $5 = args
+ * $6 = arg_num
+ */
+
+invokeNative:
+ .frame $fp, 8, $0
+ .mask 0x00000000, 0
+ .fmask 0x00000000, 0
+
+ /* Fixed part of frame */
+ subu $sp, 8
+
+ /* save registers */
+ sw $31, 4($sp)
+ sw $fp, 0($sp)
+
+ /* set frame pointer to bottom of fixed frame */
+ move $fp, $sp
+
+ /* allocate enough stack space */
+ sll $11, $6, 2 /* $11 == arg_num * 4 */
+ subu $sp, $11
+
+ /* make 8-byte aligned */
+ and $sp, ~7
+
+ move $9, $sp
+ move $25, $4 /* $25 = func_ptr */
+
+push_args:
+ beq $6, 0, done /* arg_num == 0 ? */
+ lw $8, 0($5) /* $8 = *args */
+ sw $8, 0($9) /* store $8 to stack */
+ addu $5, 4 /* args++ */
+ addu $9, 4 /* sp++ */
+ subu $6, 1 /* arg_num-- */
+ j push_args
+
+done:
+ lw $4, 0($sp) /* Load $4..$7 from stack */
+ lw $5, 4($sp)
+ lw $6, 8($sp)
+ lw $7, 12($sp)
+ ldc1 $f12, 0($sp) /* Load $f12, $f13, $f14, $f15 */
+ ldc1 $f14, 8($sp)
+
+ jalr $25 /* call function */
+
+ nop
+
+ /* restore saved registers */
+ move $sp, $fp
+ lw $31, 4($sp)
+ lw $fp, 0($sp)
+
+ /* pop frame */
+ addu $sp, $sp, 8
+
+ j $31
+ .end invokeNative
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_osx_universal.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_osx_universal.s
new file mode 100644
index 000000000..e2ca654fd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_osx_universal.s
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if defined(__aarch64__)
+#if WASM_ENABLE_SIMD == 0
+#include "invokeNative_aarch64.s"
+#else
+#include "invokeNative_aarch64_simd.s"
+#endif
+#else
+#if WASM_ENABLE_SIMD == 0
+#include "invokeNative_em64.s"
+#else
+#include "invokeNative_em64_simd.s"
+#endif
+#endif \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_riscv.S b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_riscv.S
new file mode 100644
index 000000000..0908f73cc
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_riscv.S
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/*
+ * The float abi macros used bellow are from risc-v c api:
+ * https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md
+ *
+ */
+
+#if defined(__riscv_float_abi_soft)
+#define RV_FPREG_SIZE 0
+#elif defined(__riscv_float_abi_single)
+#define RV_OP_LOADFPREG flw
+#define RV_OP_STROEFPREG fsw
+#define RV_FPREG_SIZE 4
+#elif defined(__riscv_float_abi_double)
+#define RV_OP_LOADFPREG fld
+#define RV_OP_STROEFPREG fsd
+#define RV_FPREG_SIZE 8
+#endif
+
+#if __riscv_xlen == 32
+#define RV_OP_LOADREG lw
+#define RV_OP_STOREREG sw
+#define RV_REG_SIZE 4
+#define RV_REG_SHIFT 2
+#define RV_FP_OFFSET (8 * RV_REG_SIZE)
+#define RV_INT_OFFSET 0
+#else
+#define RV_OP_LOADREG ld
+#define RV_OP_STOREREG sd
+#define RV_REG_SIZE 8
+#define RV_REG_SHIFT 3
+#define RV_FP_OFFSET 0
+#define RV_INT_OFFSET (8 * RV_FPREG_SIZE)
+#endif
+
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * a0 function ptr
+ * a1 argv
+ * a2 nstacks
+ */
+
+/*
+ * sp (stack pointer)
+ * |- sd/sw to store 64/32-bit values from register to memory
+ * |- ld/lw to load from stack to register
+ * fp/s0 (frame pointer)
+ * a0-a7 (8 integer arguments)
+ * |- sd/sw to store
+ * |- ld/lw to load
+ * fa0-a7 (8 float arguments)
+ * |- fsd/fsw to store
+ * |- fld/fsw to load
+ * t0-t6 (temporaries regisgers)
+ * |- caller saved
+ */
+
+ /* reserve space on stack to save return address and frame pointer */
+ addi sp, sp, - 2 * RV_REG_SIZE
+ RV_OP_STOREREG fp, 0 * RV_REG_SIZE(sp) /* save frame pointer */
+ RV_OP_STOREREG ra, 1 * RV_REG_SIZE(sp) /* save return address */
+
+ mv fp, sp /* set frame pointer to bottom of fixed frame */
+
+ /* save function ptr, argv & nstacks */
+ mv t0, a0 /* t0 = function ptr */
+ mv t1, a1 /* t1 = argv array address */
+ mv t2, a2 /* t2 = nstack */
+
+#ifndef __riscv_float_abi_soft
+ /* fill in fa0-7 float-registers*/
+ RV_OP_LOADFPREG fa0, RV_FP_OFFSET + 0 * RV_FPREG_SIZE(t1) /* fa0 */
+ RV_OP_LOADFPREG fa1, RV_FP_OFFSET + 1 * RV_FPREG_SIZE(t1) /* fa1 */
+ RV_OP_LOADFPREG fa2, RV_FP_OFFSET + 2 * RV_FPREG_SIZE(t1) /* fa2 */
+ RV_OP_LOADFPREG fa3, RV_FP_OFFSET + 3 * RV_FPREG_SIZE(t1) /* fa3 */
+ RV_OP_LOADFPREG fa4, RV_FP_OFFSET + 4 * RV_FPREG_SIZE(t1) /* fa4 */
+ RV_OP_LOADFPREG fa5, RV_FP_OFFSET + 5 * RV_FPREG_SIZE(t1) /* fa5 */
+ RV_OP_LOADFPREG fa6, RV_FP_OFFSET + 6 * RV_FPREG_SIZE(t1) /* fa6 */
+ RV_OP_LOADFPREG fa7, RV_FP_OFFSET + 7 * RV_FPREG_SIZE(t1) /* fa7 */
+#endif
+
+ /* fill in a0-7 integer-registers*/
+ RV_OP_LOADREG a0, RV_INT_OFFSET + 0 * RV_REG_SIZE(t1) /* a0 */
+ RV_OP_LOADREG a1, RV_INT_OFFSET + 1 * RV_REG_SIZE(t1) /* a1 */
+ RV_OP_LOADREG a2, RV_INT_OFFSET + 2 * RV_REG_SIZE(t1) /* a2 */
+ RV_OP_LOADREG a3, RV_INT_OFFSET + 3 * RV_REG_SIZE(t1) /* a3 */
+ RV_OP_LOADREG a4, RV_INT_OFFSET + 4 * RV_REG_SIZE(t1) /* a4 */
+ RV_OP_LOADREG a5, RV_INT_OFFSET + 5 * RV_REG_SIZE(t1) /* a5 */
+ RV_OP_LOADREG a6, RV_INT_OFFSET + 6 * RV_REG_SIZE(t1) /* a6 */
+ RV_OP_LOADREG a7, RV_INT_OFFSET + 7 * RV_REG_SIZE(t1) /* a7 */
+
+ /* t1 points to stack args */
+
+ /* RV_FPREG_SIZE is zero when __riscv_float_abi_soft defined */
+ addi t1, t1, RV_REG_SIZE * 8 + RV_FPREG_SIZE * 8
+
+ /* directly call the function if no args in stack,
+ x0 always holds 0 */
+ beq t2, x0, call_func
+
+ /* reserve enough stack space for function arguments */
+ sll t3, t2, RV_REG_SHIFT /* shift left 3 bits. t3 = n_stacks * 8 */
+ sub sp, sp, t3
+
+ /* make 16-byte aligned */
+ li t3, 15
+ not t3, t3
+ and sp, sp, t3
+
+ /* save sp in t4 register */
+ mv t4, sp
+
+ /* copy left arguments from caller stack to own frame stack */
+loop_stack_args:
+ beq t2, x0, call_func
+ RV_OP_LOADREG t5, 0(t1) /* load stack argument, t5 = argv[i] */
+ RV_OP_STOREREG t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
+ addi t1, t1, RV_REG_SIZE /* move to next stack argument */
+ addi t4, t4, RV_REG_SIZE /* move to next stack pointer */
+ addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
+ j loop_stack_args
+
+call_func:
+ jalr t0
+
+ /* restore registers pushed in stack or saved in another register */
+return:
+ mv sp, fp /* restore sp saved in fp before function call */
+ RV_OP_LOADREG fp, 0 * RV_REG_SIZE(sp) /* load previous frame poniter to fp register */
+ RV_OP_LOADREG ra, 1 * RV_REG_SIZE(sp) /* load previous return address to ra register */
+ addi sp, sp, 2 * RV_REG_SIZE /* pop frame, restore sp */
+ jr ra
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb.s
new file mode 100644
index 000000000..3669fe77e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb.s
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * r0 function ptr
+ * r1 argv
+ * r2 argc
+ */
+
+ push {r4, r5, r6, r7}
+ push {lr}
+ sub sp, sp, #4 /* make sp 8 byte aligned */
+ mov ip, r0 /* ip = function ptr */
+ mov r4, r1 /* r4 = argv */
+ mov r5, r2 /* r5 = argc */
+
+ cmp r5, #1 /* at least one argument required: exec_env */
+ blt return
+
+ mov r6, #0 /* increased stack size */
+
+ ldr r0, [r4] /* r0 = argv[0] = exec_env */
+ add r4, r4, #4 /* r4 += 4 */
+ cmp r5, #1
+ beq call_func
+
+ ldr r1, [r4] /* r1 = argv[1] */
+ add r4, r4, #4
+ cmp r5, #2
+ beq call_func
+
+ ldr r2, [r4] /* r2 = argv[2] */
+ add r4, r4, #4
+ cmp r5, #3
+ beq call_func
+
+ ldr r3, [r4] /* r3 = argv[3] */
+ add r4, r4, #4
+ cmp r5, #4
+ beq call_func
+
+ sub r5, r5, #4 /* argc -= 4, now we have r0 ~ r3 */
+
+ /* Ensure address is 8 byte aligned */
+ lsl r6, r5, #2 /* r6 = argc * 4 */
+ mov r7, #7
+ add r6, r6, r7 /* r6 = (r6 + 7) & ~7 */
+ bic r6, r6, r7
+ add r6, r6, #4 /* +4 because odd(5) registers are in stack */
+ mov r7, sp
+ sub r7, r7, r6 /* reserved stack space for left arguments */
+ mov sp, r7
+
+ mov lr, r2 /* save r2 */
+loop_args: /* copy left arguments to stack */
+ cmp r5, #0
+ beq call_func1
+ ldr r2, [r4]
+ add r4, r4, #4
+ str r2, [r7]
+ add r7, r7, #4
+ sub r5, r5, #1
+ b loop_args
+
+call_func1:
+ mov r2, lr /* restore r2 */
+
+call_func:
+ blx ip
+ add sp, sp, r6 /* restore sp */
+
+return:
+ add sp, sp, #4 /* make sp 8 byte aligned */
+ pop {r3}
+ pop {r4, r5, r6, r7}
+ mov lr, r3
+ bx lr
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb_vfp.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb_vfp.s
new file mode 100644
index 000000000..218cd91e0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_thumb_vfp.s
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+ .text
+ .align 2
+#ifndef BH_PLATFORM_DARWIN
+ .globl invokeNative
+ .type invokeNative, function
+invokeNative:
+#else
+ .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * r0 function ptr
+ * r1 argv
+ * r2 nstacks
+ */
+
+ push {r4, r5, r6, r7}
+ push {lr}
+ sub sp, sp, #4 /* make sp 8 byte aligned */
+ 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:
+ add sp, sp, #4 /* make sp 8 byte aligned */
+ pop {r3}
+ pop {r4, r5, r6, r7}
+ mov lr, r3
+ bx lr
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_xtensa.s b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_xtensa.s
new file mode 100644
index 000000000..ce03f12c1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/arch/invokeNative_xtensa.s
@@ -0,0 +1,74 @@
+/*
+ * 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:
+ *
+ * a2 function pntr
+ * a3 argv
+ * a4 argc
+ */
+
+invokeNative:
+ entry a1, 256
+
+ blti a4, 1, return /* at least one argument required: exec_env */
+
+ /* register a10 ~ a15 are used to pass first 6 arguments */
+
+ l32i.n a10, a3, 0
+ beqi a4, 1, call_func
+
+ l32i.n a11, a3, 4
+ beqi a4, 2, call_func
+
+ l32i.n a12, a3, 8
+ beqi a4, 3, call_func
+
+ l32i.n a13, a3, 12
+ beqi a4, 4, call_func
+
+ l32i.n a14, a3, 16
+ beqi a4, 5, call_func
+
+ l32i.n a15, a3, 20
+ beqi a4, 6, call_func
+
+ /* left arguments are passed through stack */
+
+ addi a4, a4, -6
+ addi a3, a3, 24 /* move argv pointer */
+ mov.n a6, a1 /* store stack pointer */
+ addi a7, a1, 256 /* stack boundary */
+
+loop_args:
+ beqi a4, 0, call_func
+ bge a6, a7, call_func /* reach stack boundary */
+
+ l32i.n a5, a3, 0 /* load argument to a5 */
+ s32i.n a5, a6, 0 /* push data to stack */
+
+ addi a4, a4, -1 /* decrease argc */
+ addi a3, a3, 4 /* move argv pointer */
+ addi a6, a6, 4 /* move stack pointer */
+
+ j loop_args
+
+call_func:
+ mov.n a8, a2
+ callx8 a8
+
+ /* the result returned from callee is stored in a2
+ mov the result to a10 so the caller of this function
+ can receive the value */
+ mov.n a2, a10
+ mov.n a3, a11
+
+return:
+ retw.n
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/iwasm_common.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/iwasm_common.cmake
new file mode 100644
index 000000000..15895b8e5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/iwasm_common.cmake
@@ -0,0 +1,99 @@
+# 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})
+
+add_definitions(-DBH_MALLOC=wasm_runtime_malloc)
+add_definitions(-DBH_FREE=wasm_runtime_free)
+
+file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c)
+
+if (WAMR_DISABLE_APP_ENTRY EQUAL 1)
+ list(REMOVE_ITEM c_source_all "${IWASM_COMMON_DIR}/wasm_application.c")
+endif ()
+
+if (CMAKE_OSX_ARCHITECTURES)
+ string(TOLOWER "${CMAKE_OSX_ARCHITECTURES}" OSX_ARCHS)
+
+ list(FIND OSX_ARCHS arm64 OSX_AARCH64)
+ list(FIND OSX_ARCHS x86_64 OSX_X86_64)
+
+ if (NOT "${OSX_AARCH64}" STREQUAL "-1" AND NOT "${OSX_X86_64}" STREQUAL "-1")
+ set(OSX_UNIVERSAL_BUILD 1)
+ endif()
+endif()
+
+if (WAMR_BUILD_INVOKE_NATIVE_GENERAL EQUAL 1)
+ # Use invokeNative C version instead of asm code version
+ # if WAMR_BUILD_INVOKE_NATIVE_GENERAL is explicitly set.
+ # Note:
+ # 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)
+elseif (OSX_UNIVERSAL_BUILD EQUAL 1)
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_osx_universal.s)
+elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+ if (NOT WAMR_BUILD_SIMD EQUAL 1)
+ if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+ if (NOT MINGW)
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.asm)
+ else ()
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mingw_x64.s)
+ endif ()
+ else ()
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
+ endif ()
+ else ()
+ if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+ if (NOT MINGW)
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64_simd.asm)
+ else ()
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mingw_x64_simd.s)
+ endif ()
+ else()
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64_simd.s)
+ endif()
+ endif ()
+elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
+ if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.asm)
+ else ()
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
+ endif ()
+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 MATCHES "AARCH64.*")
+ if (NOT WAMR_BUILD_SIMD EQUAL 1)
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
+ else()
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64_simd.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 MATCHES "RISCV*")
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv.S)
+elseif (WAMR_BUILD_TARGET STREQUAL "ARC")
+ set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arc.s)
+else ()
+ message (FATAL_ERROR "Build target isn't set")
+endif ()
+
+set (IWASM_COMMON_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_application.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_application.c
new file mode 100644
index 000000000..2ed217e7a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_application.c
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.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);
+}
+
+static void *
+runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
+ char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ if (module_inst != NULL) {
+ wasm_runtime_set_exception(module_inst, "allocate memory failed");
+ }
+ else if (error_buf != NULL) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ }
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+static union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+/**
+ * Implementation of wasm_application_execute_main()
+ */
+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;
+}
+
+static bool
+execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
+{
+ WASMFunctionInstanceCommon *func;
+ WASMType *func_type = NULL;
+ WASMExecEnv *exec_env = NULL;
+ uint32 argc1 = 0, argv1[2] = { 0 };
+ uint32 total_argv_size = 0;
+ uint64 total_size;
+ uint32 argv_buf_offset = 0;
+ int32 i;
+ char *argv_buf, *p, *p_end;
+ uint32 *argv_offsets, module_type;
+ bool ret, is_import_func = true;
+
+ exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
+ if (!exec_env) {
+ wasm_runtime_set_exception(module_inst,
+ "create singleton exec_env failed");
+ return false;
+ }
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ /* In wasi mode, we should call the function named "_start"
+ which initializes the wasi envrionment and then calls
+ the actual main function. Directly calling main function
+ may cause exception thrown. */
+ if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
+ return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
+ }
+#endif /* end of WASM_ENABLE_LIBC_WASI */
+
+ if (!(func = wasm_runtime_lookup_function(module_inst, "main", NULL))
+ && !(func = wasm_runtime_lookup_function(module_inst,
+ "__main_argc_argv", NULL))
+ && !(func = wasm_runtime_lookup_function(module_inst, "_main", NULL))) {
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasm_runtime_set_exception(
+ module_inst, "lookup the entry point symbol (like _start, main, "
+ "_main, __main_argc_argv) failed");
+#else
+ wasm_runtime_set_exception(module_inst,
+ "lookup the entry point symbol (like main, "
+ "_main, __main_argc_argv) failed");
+#endif
+ return false;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ is_import_func = ((WASMFunctionInstance *)func)->is_import_func;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ is_import_func = ((AOTFunctionInstance *)func)->is_import_func;
+ }
+#endif
+
+ if (is_import_func) {
+ wasm_runtime_set_exception(module_inst, "lookup main function failed");
+ return false;
+ }
+
+ module_type = module_inst->module_type;
+ func_type = wasm_runtime_get_function_type(func, module_type);
+
+ if (!func_type) {
+ LOG_ERROR("invalid module instance type");
+ return false;
+ }
+
+ 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, (void **)&argv_buf))) {
+ wasm_runtime_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+
+ p = argv_buf;
+ argv_offsets = (uint32 *)(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 + (uint32)(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);
+ }
+
+ ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1);
+ if (ret && func_type->result_count > 0 && argc > 0 && argv)
+ /* copy the return value */
+ *(int *)argv = (int)argv1[0];
+
+ if (argv_buf_offset)
+ wasm_runtime_module_free(module_inst, argv_buf_offset);
+
+ return ret;
+}
+
+bool
+wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
+ char *argv[])
+{
+ bool ret;
+#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+ WASMExecEnv *exec_env;
+#endif
+
+ ret = execute_main(module_inst, argc, argv);
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
+ if (exec_env) {
+ wasm_runtime_dump_mem_consumption(exec_env);
+ }
+#endif
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ wasm_runtime_dump_perf_profiling(module_inst);
+#endif
+
+ if (ret)
+ ret = wasm_runtime_get_exception(module_inst) == NULL;
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (!ret) {
+ exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
+ if (exec_env)
+ wasm_runtime_dump_call_stack(exec_env);
+ }
+#endif
+
+ return ret;
+}
+
+/**
+ * Implementation of wasm_application_execute_func()
+ */
+
+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 bool
+execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
+ int32 argc, char *argv[])
+{
+ WASMFunctionInstanceCommon *target_func;
+ WASMType *type = NULL;
+ WASMExecEnv *exec_env = NULL;
+ uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
+#if WASM_ENABLE_REF_TYPES != 0
+ uint32 param_size_in_double_world = 0, result_size_in_double_world = 0;
+#endif
+ int32 i, p, module_type;
+ uint64 total_size;
+ const char *exception;
+ char buf[128];
+
+ bh_assert(argc >= 0);
+ LOG_DEBUG("call a function \"%s\" with %d arguments", name, argc);
+
+ if (!(target_func =
+ wasm_runtime_lookup_function(module_inst, name, NULL))) {
+ snprintf(buf, sizeof(buf), "lookup function %s failed", name);
+ wasm_runtime_set_exception(module_inst, buf);
+ goto fail;
+ }
+
+ module_type = module_inst->module_type;
+ type = wasm_runtime_get_function_type(target_func, module_type);
+
+ if (!type) {
+ LOG_ERROR("invalid module instance type");
+ return false;
+ }
+
+ if (type->param_count != (uint32)argc) {
+ wasm_runtime_set_exception(module_inst, "invalid input argument count");
+ goto fail;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ for (i = 0; i < type->param_count; i++) {
+ param_size_in_double_world +=
+ wasm_value_type_cell_num_outside(type->types[i]);
+ }
+ for (i = 0; i < type->result_count; i++) {
+ result_size_in_double_world += wasm_value_type_cell_num_outside(
+ type->types[type->param_count + i]);
+ }
+ argc1 = param_size_in_double_world;
+ cell_num = (param_size_in_double_world >= result_size_in_double_world)
+ ? param_size_in_double_world
+ : result_size_in_double_world;
+#else
+ argc1 = type->param_cell_num;
+ cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
+#endif
+
+ total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
+ if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst, NULL, 0)))) {
+ goto fail;
+ }
+
+ /* 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 %" PRId32, 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;
+ bh_memcpy_s(&f32, sizeof(float), &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;
+ bh_memcpy_s(&f32, sizeof(float), &u.f, sizeof(float));
+ }
+ }
+ bh_memcpy_s(&argv1[p], (uint32)total_size - p, &f32,
+ (uint32)sizeof(float));
+ p++;
+ 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;
+ bh_memcpy_s(&u.val, sizeof(double), &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;
+ }
+ bh_memcpy_s(&u.val, sizeof(double), &ud.d,
+ sizeof(double));
+ }
+ }
+ argv1[p++] = u.parts[0];
+ argv1[p++] = u.parts[1];
+ break;
+ }
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ {
+ /* it likes 0x123\0x234 or 123\234 */
+ /* retrive first i64 */
+ *(uint64 *)(argv1 + p) = strtoull(argv[i], &endptr, 0);
+ /* skip \ */
+ endptr++;
+ /* retrive second i64 */
+ *(uint64 *)(argv1 + p + 2) = strtoull(endptr, &endptr, 0);
+ p += 4;
+ break;
+ }
+#endif /* WASM_ENABLE_SIMD != 0 */
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ {
+ if (strncasecmp(argv[i], "null", 4) == 0) {
+ argv1[p++] = (uint32)-1;
+ }
+ else {
+ argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
+ }
+ break;
+ }
+ case VALUE_TYPE_EXTERNREF:
+ {
+#if UINTPTR_MAX == UINT32_MAX
+ if (strncasecmp(argv[i], "null", 4) == 0) {
+ argv1[p++] = (uint32)-1;
+ }
+ else {
+ argv1[p++] = strtoul(argv[i], &endptr, 0);
+ }
+#else
+ union {
+ uintptr_t val;
+ uint32 parts[2];
+ } u;
+ if (strncasecmp(argv[i], "null", 4) == 0) {
+ u.val = (uintptr_t)-1LL;
+ }
+ else {
+ u.val = strtoull(argv[i], &endptr, 0);
+ }
+ argv1[p++] = u.parts[0];
+ argv1[p++] = u.parts[1];
+#endif
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ bh_assert(0);
+ break;
+ }
+ if (endptr && *endptr != '\0' && *endptr != '_') {
+ snprintf(buf, sizeof(buf), "invalid input argument %" PRId32 ": %s",
+ i, argv[i]);
+ wasm_runtime_set_exception(module_inst, buf);
+ goto fail;
+ }
+ }
+
+ wasm_runtime_set_exception(module_inst, NULL);
+#if WASM_ENABLE_REF_TYPES == 0
+ bh_assert(p == (int32)argc1);
+#endif
+
+ exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
+ if (!exec_env) {
+ wasm_runtime_set_exception(module_inst,
+ "create singleton exec_env failed");
+ goto fail;
+ }
+
+ if (!wasm_runtime_call_wasm(exec_env, target_func, argc1, argv1)) {
+ goto fail;
+ }
+
+ /* print return value */
+ for (j = 0; j < type->result_count; j++) {
+ switch (type->types[type->param_count + j]) {
+ case VALUE_TYPE_I32:
+ {
+ os_printf("0x%" PRIx32 ":i32", argv1[k]);
+ k++;
+ break;
+ }
+ case VALUE_TYPE_I64:
+ {
+ union {
+ uint64 val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = argv1[k];
+ u.parts[1] = argv1[k + 1];
+ k += 2;
+ os_printf("0x%" PRIx64 ":i64", u.val);
+ break;
+ }
+ case VALUE_TYPE_F32:
+ {
+ os_printf("%.7g:f32", *(float32 *)(argv1 + k));
+ k++;
+ break;
+ }
+ case VALUE_TYPE_F64:
+ {
+ union {
+ float64 val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = argv1[k];
+ u.parts[1] = argv1[k + 1];
+ k += 2;
+ os_printf("%.7g:f64", u.val);
+ break;
+ }
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ {
+ if (argv1[k] != NULL_REF)
+ os_printf("%" PRIu32 ":ref.func", argv1[k]);
+ else
+ os_printf("func:ref.null");
+ k++;
+ break;
+ }
+ case VALUE_TYPE_EXTERNREF:
+ {
+#if UINTPTR_MAX == UINT32_MAX
+ if (argv1[k] != 0 && argv1[k] != (uint32)-1)
+ os_printf("%p:ref.extern", (void *)argv1[k]);
+ else
+ os_printf("extern:ref.null");
+ k++;
+#else
+ union {
+ uintptr_t val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = argv1[k];
+ u.parts[1] = argv1[k + 1];
+ k += 2;
+ if (u.val && u.val != (uintptr_t)-1LL)
+ os_printf("%p:ref.extern", (void *)u.val);
+ else
+ os_printf("extern:ref.null");
+#endif
+ break;
+ }
+#endif
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ {
+ uint64 *v = (uint64 *)(argv1 + k);
+ os_printf("<0x%016" PRIx64 " 0x%016" PRIx64 ">:v128", *v,
+ *(v + 1));
+ k += 4;
+ break;
+ }
+#endif /* WASM_ENABLE_SIMD != 0 */
+ default:
+ bh_assert(0);
+ break;
+ }
+ if (j < (uint32)(type->result_count - 1))
+ os_printf(",");
+ }
+ os_printf("\n");
+
+ wasm_runtime_free(argv1);
+ return true;
+
+fail:
+ if (argv1)
+ wasm_runtime_free(argv1);
+
+ exception = wasm_runtime_get_exception(module_inst);
+ bh_assert(exception);
+ os_printf("%s\n", exception);
+ return false;
+}
+
+bool
+wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
+ const char *name, int32 argc, char *argv[])
+{
+ bool ret;
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ WASMExecEnv *exec_env;
+#endif
+
+ ret = execute_func(module_inst, name, argc, argv);
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
+ if (exec_env) {
+ wasm_runtime_dump_mem_consumption(exec_env);
+ }
+#endif
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ wasm_runtime_dump_perf_profiling(module_inst);
+#endif
+
+ return (ret && !wasm_runtime_get_exception(module_inst)) ? true : false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api.c
new file mode 100644
index 000000000..7b8cf4779
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api.c
@@ -0,0 +1,5227 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "wasm_c_api_internal.h"
+
+#include "bh_assert.h"
+#include "wasm_export.h"
+#include "wasm_memory.h"
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
+#include "aot.h"
+#include "aot_llvm.h"
+#endif /*WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0*/
+#endif /*WASM_ENABLE_AOT != 0*/
+
+#if WASM_ENABLE_WASM_CACHE != 0
+#include <openssl/sha.h>
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "thread_manager.h"
+#endif
+
+/*
+ * Thread Model:
+ * - Only one wasm_engine_t in one process
+ * - One wasm_store_t is only accessed by one thread. wasm_store_t can't be
+ * shared in threads
+ * - wasm_module_t can be shared in threads
+ * - wasm_instance_t can not be shared in threads
+ */
+
+#define ASSERT_NOT_IMPLEMENTED() bh_assert(!"not implemented")
+#define UNREACHABLE() bh_assert(!"unreachable")
+
+typedef struct wasm_module_ex_t {
+ struct WASMModuleCommon *module_comm_rt;
+ wasm_byte_vec_t *binary;
+ korp_mutex lock;
+ uint32 ref_count;
+#if WASM_ENABLE_WASM_CACHE != 0
+ char hash[SHA256_DIGEST_LENGTH];
+#endif
+} wasm_module_ex_t;
+
+#ifndef os_thread_local_attribute
+typedef struct thread_local_stores {
+ korp_tid tid;
+ unsigned stores_num;
+} thread_local_stores;
+#endif
+
+static void
+wasm_module_delete_internal(wasm_module_t *);
+
+static void
+wasm_instance_delete_internal(wasm_instance_t *);
+
+/* temporarily put stubs here */
+static wasm_store_t *
+wasm_store_copy(const wasm_store_t *src)
+{
+ (void)src;
+ LOG_WARNING("in the stub of %s", __FUNCTION__);
+ return NULL;
+}
+
+wasm_module_t *
+wasm_module_copy(const wasm_module_t *src)
+{
+ (void)src;
+ LOG_WARNING("in the stub of %s", __FUNCTION__);
+ return NULL;
+}
+
+wasm_instance_t *
+wasm_instance_copy(const wasm_instance_t *src)
+{
+ (void)src;
+ LOG_WARNING("in the stub of %s", __FUNCTION__);
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+static inline void *
+malloc_internal(uint64 size)
+{
+ void *mem = NULL;
+
+ if (size < UINT32_MAX && (mem = wasm_runtime_malloc((uint32)size))) {
+ memset(mem, 0, size);
+ }
+
+ return mem;
+}
+
+/* clang-format off */
+#define RETURN_OBJ(obj, obj_del_func) \
+ return obj; \
+failed: \
+ obj_del_func(obj); \
+ return NULL;
+
+#define RETURN_VOID(obj, obj_del_func) \
+ return; \
+failed: \
+ obj_del_func(obj); \
+ return;
+/* clang-format on */
+
+/* Vectors */
+#define INIT_VEC(vector_p, init_func, ...) \
+ do { \
+ if (!(vector_p = malloc_internal(sizeof(*(vector_p))))) { \
+ goto failed; \
+ } \
+ \
+ init_func(vector_p, ##__VA_ARGS__); \
+ if (vector_p->size && !vector_p->data) { \
+ LOG_DEBUG("%s failed", #init_func); \
+ goto failed; \
+ } \
+ } while (false)
+
+#define DEINIT_VEC(vector_p, deinit_func) \
+ if ((vector_p)) { \
+ deinit_func(vector_p); \
+ wasm_runtime_free(vector_p); \
+ vector_p = NULL; \
+ }
+
+#define WASM_DEFINE_VEC(name) \
+ void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t *out) \
+ { \
+ wasm_##name##_vec_new_uninitialized(out, 0); \
+ } \
+ void wasm_##name##_vec_new_uninitialized(own wasm_##name##_vec_t *out, \
+ size_t size) \
+ { \
+ wasm_##name##_vec_new(out, size, NULL); \
+ }
+
+/* vectors with no ownership management of elements */
+#define WASM_DEFINE_VEC_PLAIN(name) \
+ WASM_DEFINE_VEC(name) \
+ void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \
+ own wasm_##name##_t const data[]) \
+ { \
+ if (!out) { \
+ return; \
+ } \
+ \
+ memset(out, 0, sizeof(wasm_##name##_vec_t)); \
+ \
+ if (!size) { \
+ return; \
+ } \
+ \
+ if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t), \
+ true)) { \
+ LOG_DEBUG("bh_vector_init failed"); \
+ goto failed; \
+ } \
+ \
+ if (data) { \
+ uint32 size_in_bytes = 0; \
+ size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t)); \
+ bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \
+ out->num_elems = size; \
+ } \
+ \
+ RETURN_VOID(out, wasm_##name##_vec_delete) \
+ } \
+ void wasm_##name##_vec_copy(wasm_##name##_vec_t *out, \
+ const wasm_##name##_vec_t *src) \
+ { \
+ if (!src) { \
+ return; \
+ } \
+ wasm_##name##_vec_new(out, src->size, src->data); \
+ } \
+ void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \
+ { \
+ if (v) { \
+ bh_vector_destroy((Vector *)v); \
+ } \
+ }
+
+/* vectors that own their elements */
+#define WASM_DEFINE_VEC_OWN(name, elem_destroy_func) \
+ WASM_DEFINE_VEC(name) \
+ void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \
+ own wasm_##name##_t *const data[]) \
+ { \
+ if (!out) { \
+ return; \
+ } \
+ \
+ memset(out, 0, sizeof(wasm_##name##_vec_t)); \
+ \
+ if (!size) { \
+ return; \
+ } \
+ \
+ if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t *), \
+ true)) { \
+ LOG_DEBUG("bh_vector_init failed"); \
+ goto failed; \
+ } \
+ \
+ if (data) { \
+ uint32 size_in_bytes = 0; \
+ size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t *)); \
+ bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \
+ out->num_elems = size; \
+ } \
+ \
+ RETURN_VOID(out, wasm_##name##_vec_delete) \
+ } \
+ void wasm_##name##_vec_copy(own wasm_##name##_vec_t *out, \
+ const wasm_##name##_vec_t *src) \
+ { \
+ size_t i = 0; \
+ \
+ if (!out) { \
+ return; \
+ } \
+ memset(out, 0, sizeof(Vector)); \
+ \
+ if (!src || !src->size) { \
+ return; \
+ } \
+ \
+ if (!bh_vector_init((Vector *)out, src->size, \
+ sizeof(wasm_##name##_t *), true)) { \
+ LOG_DEBUG("bh_vector_init failed"); \
+ goto failed; \
+ } \
+ \
+ for (i = 0; i != src->num_elems; ++i) { \
+ if (!(out->data[i] = wasm_##name##_copy(src->data[i]))) { \
+ LOG_DEBUG("wasm_%s_copy failed", #name); \
+ goto failed; \
+ } \
+ } \
+ out->num_elems = src->num_elems; \
+ \
+ RETURN_VOID(out, wasm_##name##_vec_delete) \
+ } \
+ void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \
+ { \
+ size_t i = 0; \
+ if (!v) { \
+ return; \
+ } \
+ for (i = 0; i != v->num_elems && v->data; ++i) { \
+ elem_destroy_func(*(v->data + i)); \
+ } \
+ bh_vector_destroy((Vector *)v); \
+ }
+
+WASM_DEFINE_VEC_PLAIN(byte)
+WASM_DEFINE_VEC_PLAIN(val)
+
+WASM_DEFINE_VEC_OWN(exporttype, wasm_exporttype_delete)
+WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete)
+WASM_DEFINE_VEC_OWN(frame, wasm_frame_delete)
+WASM_DEFINE_VEC_OWN(functype, wasm_functype_delete)
+WASM_DEFINE_VEC_OWN(importtype, wasm_importtype_delete)
+WASM_DEFINE_VEC_OWN(instance, wasm_instance_delete_internal)
+WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal)
+WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
+WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
+
+#ifndef NDEBUG
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
+#else
+#define WASM_C_DUMP_PROC_MEM() (void)0
+#endif
+#else
+#define WASM_C_DUMP_PROC_MEM() (void)0
+#endif
+
+/* Runtime Environment */
+own wasm_config_t *
+wasm_config_new(void)
+{
+ return NULL;
+}
+
+void
+wasm_config_delete(own wasm_config_t *config)
+{
+ (void)config;
+}
+
+static void
+wasm_engine_delete_internal(wasm_engine_t *engine)
+{
+ if (engine) {
+ /* clean all created wasm_module_t and their locks */
+ unsigned i;
+
+ for (i = 0; i < engine->modules.num_elems; i++) {
+ wasm_module_ex_t *module;
+ if (bh_vector_get(&engine->modules, i, &module)) {
+ os_mutex_destroy(&module->lock);
+ wasm_runtime_free(module);
+ }
+ }
+
+ bh_vector_destroy(&engine->modules);
+
+#ifndef os_thread_local_attribute
+ bh_vector_destroy(&engine->stores_by_tid);
+#endif
+
+ wasm_runtime_free(engine);
+ }
+
+ wasm_runtime_destroy();
+}
+
+static wasm_engine_t *
+wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
+{
+ wasm_engine_t *engine = NULL;
+ /* init runtime */
+ RuntimeInitArgs init_args = { 0 };
+ init_args.mem_alloc_type = type;
+
+#ifndef NDEBUG
+ bh_log_set_verbose_level(BH_LOG_LEVEL_VERBOSE);
+#else
+ bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING);
+#endif
+
+ WASM_C_DUMP_PROC_MEM();
+
+ if (type == Alloc_With_Pool) {
+ if (!opts) {
+ return NULL;
+ }
+
+ init_args.mem_alloc_option.pool.heap_buf = opts->pool.heap_buf;
+ init_args.mem_alloc_option.pool.heap_size = opts->pool.heap_size;
+ }
+ else if (type == Alloc_With_Allocator) {
+ if (!opts) {
+ return NULL;
+ }
+
+ init_args.mem_alloc_option.allocator.malloc_func =
+ opts->allocator.malloc_func;
+ init_args.mem_alloc_option.allocator.free_func =
+ opts->allocator.free_func;
+ init_args.mem_alloc_option.allocator.realloc_func =
+ opts->allocator.realloc_func;
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+ init_args.mem_alloc_option.allocator.user_data =
+ opts->allocator.user_data;
+#endif
+ }
+ else {
+ init_args.mem_alloc_option.pool.heap_buf = NULL;
+ init_args.mem_alloc_option.pool.heap_size = 0;
+ }
+
+ if (!wasm_runtime_full_init(&init_args)) {
+ LOG_DEBUG("wasm_runtime_full_init failed");
+ goto failed;
+ }
+
+ /* create wasm_engine_t */
+ if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
+ goto failed;
+ }
+
+ if (!bh_vector_init(&engine->modules, DEFAULT_VECTOR_INIT_SIZE,
+ sizeof(wasm_module_ex_t *), true))
+ goto failed;
+
+#ifndef os_thread_local_attribute
+ if (!bh_vector_init(&engine->stores_by_tid, DEFAULT_VECTOR_INIT_SIZE,
+ sizeof(thread_local_stores), true))
+ goto failed;
+#endif
+
+ engine->ref_count = 1;
+
+ WASM_C_DUMP_PROC_MEM();
+
+ RETURN_OBJ(engine, wasm_engine_delete_internal)
+}
+
+/* global engine instance */
+static wasm_engine_t *singleton_engine;
+#ifdef os_thread_local_attribute
+/* categorize wasm_store_t as threads*/
+static os_thread_local_attribute unsigned thread_local_stores_num = 0;
+#endif
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+/**
+ * lock for the singleton_engine
+ * Note: if the platform has mutex initializer, we use a global lock to
+ * lock the operations of the singleton_engine, otherwise when there are
+ * operations happening simultaneously in multiple threads, developer
+ * must create the lock by himself, and use it to lock the operations
+ */
+static korp_mutex engine_lock = OS_THREAD_MUTEX_INITIALIZER;
+#endif
+
+own wasm_engine_t *
+wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts)
+{
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_lock(&engine_lock);
+#endif
+
+ if (!singleton_engine)
+ singleton_engine = wasm_engine_new_internal(type, opts);
+ else
+ singleton_engine->ref_count++;
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_unlock(&engine_lock);
+#endif
+
+ return singleton_engine;
+}
+
+own wasm_engine_t *
+wasm_engine_new()
+{
+ return wasm_engine_new_with_args(Alloc_With_System_Allocator, NULL);
+}
+
+own wasm_engine_t *
+wasm_engine_new_with_config(own wasm_config_t *config)
+{
+ (void)config;
+ return wasm_engine_new_with_args(Alloc_With_System_Allocator, NULL);
+}
+
+void
+wasm_engine_delete(wasm_engine_t *engine)
+{
+ if (!engine)
+ return;
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_lock(&engine_lock);
+#endif
+
+ if (!singleton_engine) {
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_unlock(&engine_lock);
+#endif
+ return;
+ }
+
+ bh_assert(engine == singleton_engine);
+ bh_assert(singleton_engine->ref_count > 0);
+
+ singleton_engine->ref_count--;
+ if (singleton_engine->ref_count == 0) {
+ wasm_engine_delete_internal(engine);
+ singleton_engine = NULL;
+ }
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_unlock(&engine_lock);
+#endif
+}
+
+#ifndef os_thread_local_attribute
+static bool
+search_thread_local_store_num(Vector *stores_by_tid, korp_tid tid,
+ thread_local_stores *out_ts, unsigned *out_i)
+{
+ unsigned i;
+
+ for (i = 0; i < stores_by_tid->num_elems; i++) {
+ bool ret = bh_vector_get(stores_by_tid, i, out_ts);
+ bh_assert(ret);
+ (void)ret;
+
+ if (out_ts->tid == tid) {
+ *out_i = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
+static unsigned
+retrive_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
+{
+#ifndef os_thread_local_attribute
+ unsigned i = 0;
+ thread_local_stores ts = { 0 };
+ unsigned ret = 0;
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_lock(&engine_lock);
+#endif
+
+ if (search_thread_local_store_num(stores_by_tid, tid, &ts, &i))
+ ret = ts.stores_num;
+ else
+ ret = 0;
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_unlock(&engine_lock);
+#endif
+
+ return ret;
+#else
+ (void)stores_by_tid;
+ (void)tid;
+
+ return thread_local_stores_num;
+#endif
+}
+
+static bool
+increase_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
+{
+#ifndef os_thread_local_attribute
+ unsigned i = 0;
+ thread_local_stores ts = { 0 };
+ bool ret = false;
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_lock(&engine_lock);
+#endif
+
+ if (search_thread_local_store_num(stores_by_tid, tid, &ts, &i)) {
+ /* just in case if integer overflow */
+ if (ts.stores_num + 1 < ts.stores_num) {
+ ret = false;
+ }
+ else {
+ ts.stores_num++;
+ ret = bh_vector_set(stores_by_tid, i, &ts);
+ bh_assert(ret);
+ }
+ }
+ else {
+ ts.tid = tid;
+ ts.stores_num = 1;
+ ret = bh_vector_append(stores_by_tid, &ts);
+ }
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_unlock(&engine_lock);
+#endif
+ return ret;
+#else
+ (void)stores_by_tid;
+ (void)tid;
+
+ /* just in case if integer overflow */
+ if (thread_local_stores_num + 1 < thread_local_stores_num)
+ return false;
+
+ thread_local_stores_num++;
+ return true;
+#endif
+}
+
+static bool
+decrease_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
+{
+#ifndef os_thread_local_attribute
+ unsigned i = 0;
+ thread_local_stores ts = { 0 };
+ bool ret = false;
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_lock(&engine_lock);
+#endif
+
+ ret = search_thread_local_store_num(stores_by_tid, tid, &ts, &i);
+ bh_assert(ret);
+
+ /* just in case if integer overflow */
+ if (ts.stores_num - 1 > ts.stores_num) {
+ ret = false;
+ }
+ else {
+ ts.stores_num--;
+ ret = bh_vector_set(stores_by_tid, i, &ts);
+ bh_assert(ret);
+ }
+
+#if defined(OS_THREAD_MUTEX_INITIALIZER)
+ os_mutex_unlock(&engine_lock);
+#endif
+
+ return ret;
+#else
+ (void)stores_by_tid;
+ (void)tid;
+
+ /* just in case if integer overflow */
+ if (thread_local_stores_num - 1 > thread_local_stores_num)
+ return false;
+
+ thread_local_stores_num--;
+ return true;
+#endif
+}
+
+wasm_store_t *
+wasm_store_new(wasm_engine_t *engine)
+{
+ wasm_store_t *store = NULL;
+
+ WASM_C_DUMP_PROC_MEM();
+
+ if (!engine || singleton_engine != engine)
+ return NULL;
+
+ if (!retrive_thread_local_store_num(&engine->stores_by_tid,
+ os_self_thread())) {
+ if (!wasm_runtime_init_thread_env()) {
+ LOG_ERROR("init thread environment failed");
+ return NULL;
+ }
+
+ if (!increase_thread_local_store_num(&engine->stores_by_tid,
+ os_self_thread())) {
+ wasm_runtime_destroy_thread_env();
+ return NULL;
+ }
+
+ if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
+ decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
+ os_self_thread());
+ wasm_runtime_destroy_thread_env();
+ return NULL;
+ }
+ }
+ else {
+ if (!increase_thread_local_store_num(&engine->stores_by_tid,
+ os_self_thread()))
+ return NULL;
+
+ if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
+ decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
+ os_self_thread());
+ return NULL;
+ }
+ }
+
+ /* new a vector, and new its data */
+ INIT_VEC(store->modules, wasm_module_vec_new_uninitialized,
+ DEFAULT_VECTOR_INIT_LENGTH);
+ INIT_VEC(store->instances, wasm_instance_vec_new_uninitialized,
+ DEFAULT_VECTOR_INIT_LENGTH);
+
+ if (!(store->foreigns = malloc_internal(sizeof(Vector)))
+ || !(bh_vector_init(store->foreigns, 24, sizeof(wasm_foreign_t *),
+ true))) {
+ goto failed;
+ }
+
+ WASM_C_DUMP_PROC_MEM();
+
+ return store;
+failed:
+ wasm_store_delete(store);
+ return NULL;
+}
+
+void
+wasm_store_delete(wasm_store_t *store)
+{
+ if (!store) {
+ return;
+ }
+
+ DEINIT_VEC(store->instances, wasm_instance_vec_delete);
+ DEINIT_VEC(store->modules, wasm_module_vec_delete);
+ if (store->foreigns) {
+ bh_vector_destroy(store->foreigns);
+ wasm_runtime_free(store->foreigns);
+ }
+
+ wasm_runtime_free(store);
+
+ if (decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
+ os_self_thread())) {
+ if (!retrive_thread_local_store_num(&singleton_engine->stores_by_tid,
+ os_self_thread())) {
+ wasm_runtime_destroy_thread_env();
+ }
+ }
+}
+
+/* Type Representations */
+static inline wasm_valkind_t
+val_type_rt_2_valkind(uint8 val_type_rt)
+{
+ switch (val_type_rt) {
+#define WAMR_VAL_TYPE_2_WASM_VAL_KIND(name) \
+ case VALUE_TYPE_##name: \
+ return WASM_##name;
+
+ WAMR_VAL_TYPE_2_WASM_VAL_KIND(I32)
+ WAMR_VAL_TYPE_2_WASM_VAL_KIND(I64)
+ WAMR_VAL_TYPE_2_WASM_VAL_KIND(F32)
+ WAMR_VAL_TYPE_2_WASM_VAL_KIND(F64)
+ WAMR_VAL_TYPE_2_WASM_VAL_KIND(FUNCREF)
+#undef WAMR_VAL_TYPE_2_WASM_VAL_KIND
+
+ default:
+ return WASM_ANYREF;
+ }
+}
+
+static wasm_valtype_t *
+wasm_valtype_new_internal(uint8 val_type_rt)
+{
+ return wasm_valtype_new(val_type_rt_2_valkind(val_type_rt));
+}
+
+wasm_valtype_t *
+wasm_valtype_new(wasm_valkind_t kind)
+{
+ wasm_valtype_t *val_type;
+
+ if (kind > WASM_F64 && WASM_FUNCREF != kind
+#if WASM_ENABLE_REF_TYPES != 0
+ && WASM_ANYREF != kind
+#endif
+ ) {
+ return NULL;
+ }
+
+ if (!(val_type = malloc_internal(sizeof(wasm_valtype_t)))) {
+ return NULL;
+ }
+
+ val_type->kind = kind;
+
+ return val_type;
+}
+
+void
+wasm_valtype_delete(wasm_valtype_t *val_type)
+{
+ if (val_type) {
+ wasm_runtime_free(val_type);
+ }
+}
+
+wasm_valtype_t *
+wasm_valtype_copy(const wasm_valtype_t *src)
+{
+ return src ? wasm_valtype_new(src->kind) : NULL;
+}
+
+wasm_valkind_t
+wasm_valtype_kind(const wasm_valtype_t *val_type)
+{
+ return val_type ? val_type->kind : WASM_ANYREF;
+}
+
+static wasm_functype_t *
+wasm_functype_new_internal(WASMType *type_rt)
+{
+ wasm_functype_t *type = NULL;
+ wasm_valtype_t *param_type = NULL, *result_type = NULL;
+ uint32 i = 0;
+
+ if (!type_rt) {
+ return NULL;
+ }
+
+ if (!(type = malloc_internal(sizeof(wasm_functype_t)))) {
+ return NULL;
+ }
+
+ type->extern_kind = WASM_EXTERN_FUNC;
+
+ /* WASMType->types[0 : type_rt->param_count) -> type->params */
+ INIT_VEC(type->params, wasm_valtype_vec_new_uninitialized,
+ type_rt->param_count);
+ for (i = 0; i < type_rt->param_count; ++i) {
+ if (!(param_type = wasm_valtype_new_internal(*(type_rt->types + i)))) {
+ goto failed;
+ }
+
+ if (!bh_vector_append((Vector *)type->params, &param_type)) {
+ LOG_DEBUG("bh_vector_append failed");
+ goto failed;
+ }
+ }
+
+ /* WASMType->types[type_rt->param_count : type_rt->result_count) ->
+ * type->results */
+ INIT_VEC(type->results, wasm_valtype_vec_new_uninitialized,
+ type_rt->result_count);
+ for (i = 0; i < type_rt->result_count; ++i) {
+ if (!(result_type = wasm_valtype_new_internal(
+ *(type_rt->types + type_rt->param_count + i)))) {
+ goto failed;
+ }
+
+ if (!bh_vector_append((Vector *)type->results, &result_type)) {
+ LOG_DEBUG("bh_vector_append failed");
+ goto failed;
+ }
+ }
+
+ return type;
+
+failed:
+ wasm_valtype_delete(param_type);
+ wasm_valtype_delete(result_type);
+ wasm_functype_delete(type);
+ return NULL;
+}
+
+wasm_functype_t *
+wasm_functype_new(own wasm_valtype_vec_t *params,
+ own wasm_valtype_vec_t *results)
+{
+ wasm_functype_t *type = NULL;
+
+ if (!(type = malloc_internal(sizeof(wasm_functype_t)))) {
+ goto failed;
+ }
+
+ type->extern_kind = WASM_EXTERN_FUNC;
+
+ /* take ownership */
+ if (!(type->params = malloc_internal(sizeof(wasm_valtype_vec_t)))) {
+ goto failed;
+ }
+ if (params) {
+ bh_memcpy_s(type->params, sizeof(wasm_valtype_vec_t), params,
+ sizeof(wasm_valtype_vec_t));
+ }
+
+ if (!(type->results = malloc_internal(sizeof(wasm_valtype_vec_t)))) {
+ goto failed;
+ }
+ if (results) {
+ bh_memcpy_s(type->results, sizeof(wasm_valtype_vec_t), results,
+ sizeof(wasm_valtype_vec_t));
+ }
+
+ return type;
+
+failed:
+ wasm_functype_delete(type);
+ return NULL;
+}
+
+wasm_functype_t *
+wasm_functype_copy(const wasm_functype_t *src)
+{
+ wasm_functype_t *functype;
+ wasm_valtype_vec_t params = { 0 }, results = { 0 };
+
+ if (!src) {
+ return NULL;
+ }
+
+ wasm_valtype_vec_copy(&params, src->params);
+ if (src->params->size && !params.data) {
+ goto failed;
+ }
+
+ wasm_valtype_vec_copy(&results, src->results);
+ if (src->results->size && !results.data) {
+ goto failed;
+ }
+
+ if (!(functype = wasm_functype_new(&params, &results))) {
+ goto failed;
+ }
+
+ return functype;
+
+failed:
+ wasm_valtype_vec_delete(&params);
+ wasm_valtype_vec_delete(&results);
+ return NULL;
+}
+
+void
+wasm_functype_delete(wasm_functype_t *func_type)
+{
+ if (!func_type) {
+ return;
+ }
+
+ DEINIT_VEC(func_type->params, wasm_valtype_vec_delete);
+ DEINIT_VEC(func_type->results, wasm_valtype_vec_delete);
+
+ wasm_runtime_free(func_type);
+}
+
+const wasm_valtype_vec_t *
+wasm_functype_params(const wasm_functype_t *func_type)
+{
+ if (!func_type) {
+ return NULL;
+ }
+
+ return func_type->params;
+}
+
+const wasm_valtype_vec_t *
+wasm_functype_results(const wasm_functype_t *func_type)
+{
+ if (!func_type) {
+ return NULL;
+ }
+
+ return func_type->results;
+}
+
+static bool
+cmp_val_kind_with_val_type(wasm_valkind_t v_k, uint8 v_t)
+{
+ return (v_k == WASM_I32 && v_t == VALUE_TYPE_I32)
+ || (v_k == WASM_I64 && v_t == VALUE_TYPE_I64)
+ || (v_k == WASM_F32 && v_t == VALUE_TYPE_F32)
+ || (v_k == WASM_F64 && v_t == VALUE_TYPE_F64)
+ || (v_k == WASM_ANYREF && v_t == VALUE_TYPE_EXTERNREF)
+ || (v_k == WASM_FUNCREF && v_t == VALUE_TYPE_FUNCREF);
+}
+
+/*
+ *to compare a function type of wasm-c-api with a function type of wasm_runtime
+ */
+static bool
+wasm_functype_same_internal(const wasm_functype_t *type,
+ const WASMType *type_intl)
+{
+ uint32 i = 0;
+
+ if (!type || !type_intl || type->params->num_elems != type_intl->param_count
+ || type->results->num_elems != type_intl->result_count)
+ return false;
+
+ for (i = 0; i < type->params->num_elems; i++) {
+ wasm_valtype_t *v_t = type->params->data[i];
+ if (!cmp_val_kind_with_val_type(wasm_valtype_kind(v_t),
+ type_intl->types[i]))
+ return false;
+ }
+
+ for (i = 0; i < type->results->num_elems; i++) {
+ wasm_valtype_t *v_t = type->results->data[i];
+ if (!cmp_val_kind_with_val_type(
+ wasm_valtype_kind(v_t),
+ type_intl->types[i + type->params->num_elems]))
+ return false;
+ }
+
+ return true;
+}
+
+wasm_globaltype_t *
+wasm_globaltype_new(own wasm_valtype_t *val_type, wasm_mutability_t mut)
+{
+ wasm_globaltype_t *global_type = NULL;
+
+ if (!val_type) {
+ return NULL;
+ }
+
+ if (!(global_type = malloc_internal(sizeof(wasm_globaltype_t)))) {
+ return NULL;
+ }
+
+ global_type->extern_kind = WASM_EXTERN_GLOBAL;
+ global_type->val_type = val_type;
+ global_type->mutability = mut;
+
+ return global_type;
+}
+
+wasm_globaltype_t *
+wasm_globaltype_new_internal(uint8 val_type_rt, bool is_mutable)
+{
+ wasm_globaltype_t *globaltype;
+ wasm_valtype_t *val_type;
+
+ if (!(val_type = wasm_valtype_new(val_type_rt_2_valkind(val_type_rt)))) {
+ return NULL;
+ }
+
+ if (!(globaltype = wasm_globaltype_new(
+ val_type, is_mutable ? WASM_VAR : WASM_CONST))) {
+ wasm_valtype_delete(val_type);
+ }
+
+ return globaltype;
+}
+
+void
+wasm_globaltype_delete(wasm_globaltype_t *global_type)
+{
+ if (!global_type) {
+ return;
+ }
+
+ if (global_type->val_type) {
+ wasm_valtype_delete(global_type->val_type);
+ global_type->val_type = NULL;
+ }
+
+ wasm_runtime_free(global_type);
+}
+
+wasm_globaltype_t *
+wasm_globaltype_copy(const wasm_globaltype_t *src)
+{
+ wasm_globaltype_t *global_type;
+ wasm_valtype_t *val_type;
+
+ if (!src) {
+ return NULL;
+ }
+
+ if (!(val_type = wasm_valtype_copy(src->val_type))) {
+ return NULL;
+ }
+
+ if (!(global_type = wasm_globaltype_new(val_type, src->mutability))) {
+ wasm_valtype_delete(val_type);
+ }
+
+ return global_type;
+}
+
+const wasm_valtype_t *
+wasm_globaltype_content(const wasm_globaltype_t *global_type)
+{
+ if (!global_type) {
+ return NULL;
+ }
+
+ return global_type->val_type;
+}
+
+wasm_mutability_t
+wasm_globaltype_mutability(const wasm_globaltype_t *global_type)
+{
+ if (!global_type) {
+ return false;
+ }
+
+ return global_type->mutability;
+}
+
+static wasm_tabletype_t *
+wasm_tabletype_new_internal(uint8 val_type_rt, uint32 init_size,
+ uint32 max_size)
+{
+ wasm_tabletype_t *table_type;
+ wasm_limits_t limits = { init_size, max_size };
+ wasm_valtype_t *val_type;
+
+ if (!(val_type = wasm_valtype_new_internal(val_type_rt))) {
+ return NULL;
+ }
+
+ if (!(table_type = wasm_tabletype_new(val_type, &limits))) {
+ wasm_valtype_delete(val_type);
+ }
+
+ return table_type;
+}
+
+wasm_tabletype_t *
+wasm_tabletype_new(own wasm_valtype_t *val_type, const wasm_limits_t *limits)
+{
+ wasm_tabletype_t *table_type = NULL;
+
+ if (!val_type || !limits) {
+ return NULL;
+ }
+
+ if (wasm_valtype_kind(val_type) != WASM_FUNCREF
+#if WASM_ENABLE_REF_TYPES != 0
+ && wasm_valtype_kind(val_type) != WASM_ANYREF
+#endif
+ ) {
+ return NULL;
+ }
+
+ if (!(table_type = malloc_internal(sizeof(wasm_tabletype_t)))) {
+ return NULL;
+ }
+
+ table_type->extern_kind = WASM_EXTERN_TABLE;
+ table_type->val_type = val_type;
+ table_type->limits.min = limits->min;
+ table_type->limits.max = limits->max;
+
+ return table_type;
+}
+
+wasm_tabletype_t *
+wasm_tabletype_copy(const wasm_tabletype_t *src)
+{
+ wasm_tabletype_t *table_type;
+ wasm_valtype_t *val_type;
+
+ if (!src) {
+ return NULL;
+ }
+
+ if (!(val_type = wasm_valtype_copy(src->val_type))) {
+ return NULL;
+ }
+
+ if (!(table_type = wasm_tabletype_new(val_type, &src->limits))) {
+ wasm_valtype_delete(val_type);
+ }
+
+ return table_type;
+}
+
+void
+wasm_tabletype_delete(wasm_tabletype_t *table_type)
+{
+ if (!table_type) {
+ return;
+ }
+
+ if (table_type->val_type) {
+ wasm_valtype_delete(table_type->val_type);
+ table_type->val_type = NULL;
+ }
+
+ wasm_runtime_free(table_type);
+}
+
+const wasm_valtype_t *
+wasm_tabletype_element(const wasm_tabletype_t *table_type)
+{
+ if (!table_type) {
+ return NULL;
+ }
+
+ return table_type->val_type;
+}
+
+const wasm_limits_t *
+wasm_tabletype_limits(const wasm_tabletype_t *table_type)
+{
+ if (!table_type) {
+ return NULL;
+ }
+
+ return &(table_type->limits);
+}
+
+static wasm_memorytype_t *
+wasm_memorytype_new_internal(uint32 min_pages, uint32 max_pages)
+{
+ wasm_limits_t limits = { min_pages, max_pages };
+ return wasm_memorytype_new(&limits);
+}
+
+wasm_memorytype_t *
+wasm_memorytype_new(const wasm_limits_t *limits)
+{
+ wasm_memorytype_t *memory_type = NULL;
+
+ if (!limits) {
+ return NULL;
+ }
+
+ if (!(memory_type = malloc_internal(sizeof(wasm_memorytype_t)))) {
+ return NULL;
+ }
+
+ memory_type->extern_kind = WASM_EXTERN_MEMORY;
+ memory_type->limits.min = limits->min;
+ memory_type->limits.max = limits->max;
+
+ return memory_type;
+}
+
+wasm_memorytype_t *
+wasm_memorytype_copy(const wasm_memorytype_t *src)
+{
+ if (!src) {
+ return NULL;
+ }
+
+ return wasm_memorytype_new(&src->limits);
+}
+
+void
+wasm_memorytype_delete(wasm_memorytype_t *memory_type)
+{
+ if (memory_type) {
+ wasm_runtime_free(memory_type);
+ }
+}
+
+const wasm_limits_t *
+wasm_memorytype_limits(const wasm_memorytype_t *memory_type)
+{
+ if (!memory_type) {
+ return NULL;
+ }
+
+ return &(memory_type->limits);
+}
+
+wasm_externkind_t
+wasm_externtype_kind(const wasm_externtype_t *extern_type)
+{
+ if (!extern_type) {
+ return WASM_EXTERN_FUNC;
+ }
+
+ return extern_type->extern_kind;
+}
+
+#define BASIC_FOUR_TYPE_LIST(V) \
+ V(functype) \
+ V(globaltype) \
+ V(memorytype) \
+ V(tabletype)
+
+#define WASM_EXTERNTYPE_AS_OTHERTYPE(name) \
+ wasm_##name##_t *wasm_externtype_as_##name(wasm_externtype_t *extern_type) \
+ { \
+ return (wasm_##name##_t *)extern_type; \
+ }
+
+BASIC_FOUR_TYPE_LIST(WASM_EXTERNTYPE_AS_OTHERTYPE)
+#undef WASM_EXTERNTYPE_AS_OTHERTYPE
+
+#define WASM_OTHERTYPE_AS_EXTERNTYPE(name) \
+ wasm_externtype_t *wasm_##name##_as_externtype(wasm_##name##_t *other) \
+ { \
+ return (wasm_externtype_t *)other; \
+ }
+
+BASIC_FOUR_TYPE_LIST(WASM_OTHERTYPE_AS_EXTERNTYPE)
+#undef WASM_OTHERTYPE_AS_EXTERNTYPE
+
+#define WASM_EXTERNTYPE_AS_OTHERTYPE_CONST(name) \
+ const wasm_##name##_t *wasm_externtype_as_##name##_const( \
+ const wasm_externtype_t *extern_type) \
+ { \
+ return (const wasm_##name##_t *)extern_type; \
+ }
+
+BASIC_FOUR_TYPE_LIST(WASM_EXTERNTYPE_AS_OTHERTYPE_CONST)
+#undef WASM_EXTERNTYPE_AS_OTHERTYPE_CONST
+
+#define WASM_OTHERTYPE_AS_EXTERNTYPE_CONST(name) \
+ const wasm_externtype_t *wasm_##name##_as_externtype_const( \
+ const wasm_##name##_t *other) \
+ { \
+ return (const wasm_externtype_t *)other; \
+ }
+
+BASIC_FOUR_TYPE_LIST(WASM_OTHERTYPE_AS_EXTERNTYPE_CONST)
+#undef WASM_OTHERTYPE_AS_EXTERNTYPE_CONST
+
+wasm_externtype_t *
+wasm_externtype_copy(const wasm_externtype_t *src)
+{
+ wasm_externtype_t *extern_type = NULL;
+
+ if (!src) {
+ return NULL;
+ }
+
+ switch (src->extern_kind) {
+#define COPY_EXTERNTYPE(NAME, name) \
+ case WASM_EXTERN_##NAME: \
+ { \
+ extern_type = wasm_##name##_as_externtype( \
+ wasm_##name##_copy(wasm_externtype_as_##name##_const(src))); \
+ break; \
+ }
+ COPY_EXTERNTYPE(FUNC, functype)
+ COPY_EXTERNTYPE(GLOBAL, globaltype)
+ COPY_EXTERNTYPE(MEMORY, memorytype)
+ COPY_EXTERNTYPE(TABLE, tabletype)
+#undef COPY_EXTERNTYPE
+ default:
+ LOG_WARNING("%s meets unsupported kind %u", __FUNCTION__,
+ src->extern_kind);
+ break;
+ }
+ return extern_type;
+}
+
+void
+wasm_externtype_delete(wasm_externtype_t *extern_type)
+{
+ if (!extern_type) {
+ return;
+ }
+
+ switch (wasm_externtype_kind(extern_type)) {
+ case WASM_EXTERN_FUNC:
+ wasm_functype_delete(wasm_externtype_as_functype(extern_type));
+ break;
+ case WASM_EXTERN_GLOBAL:
+ wasm_globaltype_delete(wasm_externtype_as_globaltype(extern_type));
+ break;
+ case WASM_EXTERN_MEMORY:
+ wasm_memorytype_delete(wasm_externtype_as_memorytype(extern_type));
+ break;
+ case WASM_EXTERN_TABLE:
+ wasm_tabletype_delete(wasm_externtype_as_tabletype(extern_type));
+ break;
+ default:
+ LOG_WARNING("%s meets unsupported type %u", __FUNCTION__,
+ wasm_externtype_kind(extern_type));
+ break;
+ }
+}
+
+own wasm_importtype_t *
+wasm_importtype_new(own wasm_byte_vec_t *module_name,
+ own wasm_byte_vec_t *field_name,
+ own wasm_externtype_t *extern_type)
+{
+ wasm_importtype_t *import_type = NULL;
+
+ if (!module_name || !field_name || !extern_type) {
+ return NULL;
+ }
+
+ if (!(import_type = malloc_internal(sizeof(wasm_importtype_t)))) {
+ return NULL;
+ }
+
+ /* take ownership */
+ if (!(import_type->module_name =
+ malloc_internal(sizeof(wasm_byte_vec_t)))) {
+ goto failed;
+ }
+ bh_memcpy_s(import_type->module_name, sizeof(wasm_byte_vec_t), module_name,
+ sizeof(wasm_byte_vec_t));
+
+ if (!(import_type->name = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+ goto failed;
+ }
+ bh_memcpy_s(import_type->name, sizeof(wasm_byte_vec_t), field_name,
+ sizeof(wasm_byte_vec_t));
+
+ import_type->extern_type = extern_type;
+
+ return import_type;
+failed:
+ wasm_importtype_delete(import_type);
+ return NULL;
+}
+
+void
+wasm_importtype_delete(own wasm_importtype_t *import_type)
+{
+ if (!import_type) {
+ return;
+ }
+
+ DEINIT_VEC(import_type->module_name, wasm_byte_vec_delete);
+ DEINIT_VEC(import_type->name, wasm_byte_vec_delete);
+ wasm_externtype_delete(import_type->extern_type);
+ import_type->extern_type = NULL;
+ wasm_runtime_free(import_type);
+}
+
+own wasm_importtype_t *
+wasm_importtype_copy(const wasm_importtype_t *src)
+{
+ wasm_byte_vec_t module_name = { 0 }, name = { 0 };
+ wasm_externtype_t *extern_type = NULL;
+ wasm_importtype_t *import_type = NULL;
+
+ if (!src) {
+ return NULL;
+ }
+
+ wasm_byte_vec_copy(&module_name, src->module_name);
+ if (src->module_name->size && !module_name.data) {
+ goto failed;
+ }
+
+ wasm_byte_vec_copy(&name, src->name);
+ if (src->name->size && !name.data) {
+ goto failed;
+ }
+
+ if (!(extern_type = wasm_externtype_copy(src->extern_type))) {
+ goto failed;
+ }
+
+ if (!(import_type =
+ wasm_importtype_new(&module_name, &name, extern_type))) {
+ goto failed;
+ }
+
+ return import_type;
+
+failed:
+ wasm_byte_vec_delete(&module_name);
+ wasm_byte_vec_delete(&name);
+ wasm_externtype_delete(extern_type);
+ wasm_importtype_delete(import_type);
+ return NULL;
+}
+
+const wasm_byte_vec_t *
+wasm_importtype_module(const wasm_importtype_t *import_type)
+{
+ if (!import_type) {
+ return NULL;
+ }
+
+ return import_type->module_name;
+}
+
+const wasm_byte_vec_t *
+wasm_importtype_name(const wasm_importtype_t *import_type)
+{
+ if (!import_type) {
+ return NULL;
+ }
+
+ return import_type->name;
+}
+
+const wasm_externtype_t *
+wasm_importtype_type(const wasm_importtype_t *import_type)
+{
+ if (!import_type) {
+ return NULL;
+ }
+
+ return import_type->extern_type;
+}
+
+bool
+wasm_importtype_is_linked(const wasm_importtype_t *import_type)
+{
+ if (!import_type)
+ return false;
+
+ const wasm_name_t *module_name = wasm_importtype_module(import_type);
+ const wasm_name_t *field_name = wasm_importtype_name(import_type);
+
+ switch (wasm_externtype_kind(wasm_importtype_type(import_type))) {
+ case WASM_EXTERN_FUNC:
+ return wasm_runtime_is_import_func_linked(module_name->data,
+ field_name->data);
+ case WASM_EXTERN_GLOBAL:
+ return wasm_runtime_is_import_global_linked(module_name->data,
+ field_name->data);
+ case WASM_EXTERN_MEMORY:
+ case WASM_EXTERN_TABLE:
+ default:
+ break;
+ }
+ return false;
+}
+
+own wasm_exporttype_t *
+wasm_exporttype_new(own wasm_byte_vec_t *name,
+ own wasm_externtype_t *extern_type)
+{
+ wasm_exporttype_t *export_type = NULL;
+
+ if (!name || !extern_type) {
+ return NULL;
+ }
+
+ if (!(export_type = malloc_internal(sizeof(wasm_exporttype_t)))) {
+ return NULL;
+ }
+
+ if (!(export_type->name = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+ wasm_exporttype_delete(export_type);
+ return NULL;
+ }
+ bh_memcpy_s(export_type->name, sizeof(wasm_byte_vec_t), name,
+ sizeof(wasm_byte_vec_t));
+
+ export_type->extern_type = extern_type;
+
+ return export_type;
+}
+
+wasm_exporttype_t *
+wasm_exporttype_copy(const wasm_exporttype_t *src)
+{
+ wasm_exporttype_t *export_type;
+ wasm_byte_vec_t name = { 0 };
+ wasm_externtype_t *extern_type = NULL;
+
+ if (!src) {
+ return NULL;
+ }
+
+ wasm_byte_vec_copy(&name, src->name);
+ if (src->name->size && !name.data) {
+ goto failed;
+ }
+
+ if (!(extern_type = wasm_externtype_copy(src->extern_type))) {
+ goto failed;
+ }
+
+ if (!(export_type = wasm_exporttype_new(&name, extern_type))) {
+ goto failed;
+ }
+
+ return export_type;
+failed:
+ wasm_byte_vec_delete(&name);
+ wasm_externtype_delete(extern_type);
+ return NULL;
+}
+
+void
+wasm_exporttype_delete(wasm_exporttype_t *export_type)
+{
+ if (!export_type) {
+ return;
+ }
+
+ DEINIT_VEC(export_type->name, wasm_byte_vec_delete);
+
+ wasm_externtype_delete(export_type->extern_type);
+
+ wasm_runtime_free(export_type);
+}
+
+const wasm_byte_vec_t *
+wasm_exporttype_name(const wasm_exporttype_t *export_type)
+{
+ if (!export_type) {
+ return NULL;
+ }
+ return export_type->name;
+}
+
+const wasm_externtype_t *
+wasm_exporttype_type(const wasm_exporttype_t *export_type)
+{
+ if (!export_type) {
+ return NULL;
+ }
+ return export_type->extern_type;
+}
+
+/* Runtime Objects */
+void
+wasm_val_delete(wasm_val_t *v)
+{
+ if (v)
+ wasm_runtime_free(v);
+}
+
+void
+wasm_val_copy(wasm_val_t *out, const wasm_val_t *src)
+{
+ if (!out || !src) {
+ return;
+ }
+
+ bh_memcpy_s(out, sizeof(wasm_val_t), src, sizeof(wasm_val_t));
+}
+
+bool
+rt_val_to_wasm_val(const uint8 *data, uint8 val_type_rt, wasm_val_t *out)
+{
+ bool ret = true;
+ switch (val_type_rt) {
+ case VALUE_TYPE_I32:
+ out->kind = WASM_I32;
+ out->of.i32 = *((int32 *)data);
+ break;
+ case VALUE_TYPE_F32:
+ out->kind = WASM_F32;
+ out->of.f32 = *((float32 *)data);
+ break;
+ case VALUE_TYPE_I64:
+ out->kind = WASM_I64;
+ out->of.i64 = *((int64 *)data);
+ break;
+ case VALUE_TYPE_F64:
+ out->kind = WASM_F64;
+ out->of.f64 = *((float64 *)data);
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ out->kind = WASM_ANYREF;
+ if (NULL_REF == *(uint32 *)data) {
+ out->of.ref = NULL;
+ }
+ else {
+ ret = wasm_externref_ref2obj(*(uint32 *)data,
+ (void **)&out->of.ref);
+ }
+ break;
+#endif
+ default:
+ LOG_WARNING("unexpected value type %d", val_type_rt);
+ ret = false;
+ }
+ return ret;
+}
+
+bool
+wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt,
+ const wasm_val_t *v, uint8 *data)
+{
+ bool ret = true;
+ switch (val_type_rt) {
+ case VALUE_TYPE_I32:
+ bh_assert(WASM_I32 == v->kind);
+ *((int32 *)data) = v->of.i32;
+ break;
+ case VALUE_TYPE_F32:
+ bh_assert(WASM_F32 == v->kind);
+ *((float32 *)data) = v->of.f32;
+ break;
+ case VALUE_TYPE_I64:
+ bh_assert(WASM_I64 == v->kind);
+ *((int64 *)data) = v->of.i64;
+ break;
+ case VALUE_TYPE_F64:
+ bh_assert(WASM_F64 == v->kind);
+ *((float64 *)data) = v->of.f64;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ bh_assert(WASM_ANYREF == v->kind);
+ ret =
+ wasm_externref_obj2ref(inst_comm_rt, v->of.ref, (uint32 *)data);
+ break;
+#endif
+ default:
+ LOG_WARNING("unexpected value type %d", val_type_rt);
+ ret = false;
+ break;
+ }
+
+ (void)inst_comm_rt;
+ return ret;
+}
+
+wasm_ref_t *
+wasm_ref_new_internal(wasm_store_t *store, enum wasm_reference_kind kind,
+ uint32 ref_idx_rt, WASMModuleInstanceCommon *inst_comm_rt)
+{
+ wasm_ref_t *ref;
+
+ if (!store) {
+ return NULL;
+ }
+
+ if (!(ref = malloc_internal(sizeof(wasm_ref_t)))) {
+ return NULL;
+ }
+
+ ref->store = store;
+ ref->kind = kind;
+ ref->ref_idx_rt = ref_idx_rt;
+ ref->inst_comm_rt = inst_comm_rt;
+
+ /* workaround */
+ if (WASM_REF_foreign == kind) {
+ wasm_foreign_t *foreign;
+
+ if (!(bh_vector_get(ref->store->foreigns, ref->ref_idx_rt, &foreign))
+ || !foreign) {
+ wasm_runtime_free(ref);
+ return NULL;
+ }
+
+ foreign->ref_cnt++;
+ }
+ /* others doesn't include ref counters */
+
+ return ref;
+}
+
+own wasm_ref_t *
+wasm_ref_copy(const wasm_ref_t *src)
+{
+ if (!src)
+ return NULL;
+
+ /* host_info are different in wasm_ref_t(s) */
+ return wasm_ref_new_internal(src->store, src->kind, src->ref_idx_rt,
+ src->inst_comm_rt);
+}
+
+#define DELETE_HOST_INFO(obj) \
+ if (obj->host_info.info) { \
+ if (obj->host_info.finalizer) { \
+ obj->host_info.finalizer(obj->host_info.info); \
+ } \
+ }
+
+void
+wasm_ref_delete(own wasm_ref_t *ref)
+{
+ if (!ref || !ref->store)
+ return;
+
+ DELETE_HOST_INFO(ref);
+
+ if (WASM_REF_foreign == ref->kind) {
+ wasm_foreign_t *foreign = NULL;
+
+ if (bh_vector_get(ref->store->foreigns, ref->ref_idx_rt, &foreign)
+ && foreign) {
+ wasm_foreign_delete(foreign);
+ }
+ }
+
+ wasm_runtime_free(ref);
+}
+
+#define WASM_DEFINE_REF_BASE(name) \
+ bool wasm_##name##_same(const wasm_##name##_t *o1, \
+ const wasm_##name##_t *o2) \
+ { \
+ return (!o1 && !o2) ? true \
+ : (!o1 || !o2) ? false \
+ : (o1->kind != o2->kind) \
+ ? false \
+ : o1->name##_idx_rt == o2->name##_idx_rt; \
+ } \
+ \
+ void *wasm_##name##_get_host_info(const wasm_##name##_t *obj) \
+ { \
+ return obj ? obj->host_info.info : NULL; \
+ } \
+ \
+ void wasm_##name##_set_host_info(wasm_##name##_t *obj, void *host_info) \
+ { \
+ if (obj) { \
+ obj->host_info.info = host_info; \
+ obj->host_info.finalizer = NULL; \
+ } \
+ } \
+ \
+ void wasm_##name##_set_host_info_with_finalizer( \
+ wasm_##name##_t *obj, void *host_info, void (*finalizer)(void *)) \
+ { \
+ if (obj) { \
+ obj->host_info.info = host_info; \
+ obj->host_info.finalizer = finalizer; \
+ } \
+ }
+
+#define WASM_DEFINE_REF(name) \
+ WASM_DEFINE_REF_BASE(name) \
+ \
+ wasm_ref_t *wasm_##name##_as_ref(wasm_##name##_t *name) \
+ { \
+ if (!name) { \
+ return NULL; \
+ } \
+ \
+ return wasm_ref_new_internal(name->store, WASM_REF_##name, \
+ name->name##_idx_rt, name->inst_comm_rt); \
+ } \
+ \
+ const wasm_ref_t *wasm_##name##_as_ref_const(const wasm_##name##_t *name) \
+ { \
+ if (!name) { \
+ return NULL; \
+ } \
+ \
+ return wasm_ref_new_internal(name->store, WASM_REF_##name, \
+ name->name##_idx_rt, name->inst_comm_rt); \
+ } \
+ \
+ wasm_##name##_t *wasm_ref_as_##name(wasm_ref_t *ref) \
+ { \
+ if (!ref || WASM_REF_##name != ref->kind) { \
+ return NULL; \
+ } \
+ \
+ return wasm_##name##_new_internal(ref->store, ref->ref_idx_rt, \
+ ref->inst_comm_rt); \
+ } \
+ \
+ const wasm_##name##_t *wasm_ref_as_##name##_const(const wasm_ref_t *ref) \
+ { \
+ if (!ref || WASM_REF_##name != ref->kind) { \
+ return NULL; \
+ } \
+ \
+ return wasm_##name##_new_internal(ref->store, ref->ref_idx_rt, \
+ ref->inst_comm_rt); \
+ }
+
+WASM_DEFINE_REF_BASE(ref)
+WASM_DEFINE_REF(foreign)
+WASM_DEFINE_REF(func)
+WASM_DEFINE_REF(global)
+WASM_DEFINE_REF(memory)
+WASM_DEFINE_REF(table)
+
+static wasm_frame_t *
+wasm_frame_new(wasm_instance_t *instance, size_t module_offset,
+ uint32 func_index, size_t func_offset)
+{
+ wasm_frame_t *frame;
+
+ if (!(frame = malloc_internal(sizeof(wasm_frame_t)))) {
+ return NULL;
+ }
+
+ frame->instance = instance;
+ frame->module_offset = (uint32)module_offset;
+ frame->func_index = func_index;
+ frame->func_offset = (uint32)func_offset;
+ return frame;
+}
+
+own wasm_frame_t *
+wasm_frame_copy(const wasm_frame_t *src)
+{
+ if (!src) {
+ return NULL;
+ }
+
+ return wasm_frame_new(src->instance, src->module_offset, src->func_index,
+ src->func_offset);
+}
+
+void
+wasm_frame_delete(own wasm_frame_t *frame)
+{
+ if (frame) {
+ wasm_runtime_free(frame);
+ }
+}
+
+struct wasm_instance_t *
+wasm_frame_instance(const wasm_frame_t *frame)
+{
+ return frame ? frame->instance : NULL;
+}
+
+size_t
+wasm_frame_module_offset(const wasm_frame_t *frame)
+{
+ return frame ? frame->module_offset : 0;
+}
+
+uint32_t
+wasm_frame_func_index(const wasm_frame_t *frame)
+{
+ return frame ? frame->func_index : 0;
+}
+
+size_t
+wasm_frame_func_offset(const wasm_frame_t *frame)
+{
+ return frame ? frame->func_offset : 0;
+}
+
+static wasm_trap_t *
+wasm_trap_new_internal(wasm_store_t *store,
+ WASMModuleInstanceCommon *inst_comm_rt,
+ const char *error_info)
+{
+ wasm_trap_t *trap;
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ wasm_instance_vec_t *instances;
+ wasm_instance_t *frame_instance = NULL;
+ uint32 i;
+#endif
+
+ if (!singleton_engine)
+ return NULL;
+
+ if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
+ return NULL;
+ }
+
+ /* fill in message */
+ if (error_info && strlen(error_info) > 0) {
+ if (!(trap->message = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+ goto failed;
+ }
+
+ wasm_name_new_from_string_nt(trap->message, error_info);
+ if (!trap->message->data) {
+ goto failed;
+ }
+ }
+
+ /* fill in frames */
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ trap->frames = ((WASMModuleInstance *)inst_comm_rt)->frames;
+
+ if (trap->frames) {
+ /* fill in instances */
+ instances = store->instances;
+ bh_assert(instances != NULL);
+
+ for (i = 0; i < instances->num_elems; i++) {
+ if (instances->data[i]->inst_comm_rt == inst_comm_rt) {
+ frame_instance = instances->data[i];
+ break;
+ }
+ }
+
+ for (i = 0; i < trap->frames->num_elems; i++) {
+ (((wasm_frame_t *)trap->frames->data) + i)->instance =
+ frame_instance;
+ }
+ }
+#else
+ (void)store;
+ (void)inst_comm_rt;
+#endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */
+
+ return trap;
+failed:
+ wasm_trap_delete(trap);
+ return NULL;
+}
+
+wasm_trap_t *
+wasm_trap_new(wasm_store_t *store, const wasm_message_t *message)
+{
+ wasm_trap_t *trap;
+
+ if (!store) {
+ return NULL;
+ }
+
+ if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
+ return NULL;
+ }
+
+ if (message) {
+ INIT_VEC(trap->message, wasm_byte_vec_new, message->size,
+ message->data);
+ }
+
+ return trap;
+failed:
+ wasm_trap_delete(trap);
+ return NULL;
+}
+
+void
+wasm_trap_delete(wasm_trap_t *trap)
+{
+ if (!trap) {
+ return;
+ }
+
+ DEINIT_VEC(trap->message, wasm_byte_vec_delete);
+ /* reuse frames of WASMModuleInstance, do not free it here */
+
+ wasm_runtime_free(trap);
+}
+
+void
+wasm_trap_message(const wasm_trap_t *trap, own wasm_message_t *out)
+{
+ if (!trap || !out) {
+ return;
+ }
+
+ wasm_byte_vec_copy(out, trap->message);
+}
+
+own wasm_frame_t *
+wasm_trap_origin(const wasm_trap_t *trap)
+{
+ wasm_frame_t *latest_frame;
+
+ if (!trap || !trap->frames || !trap->frames->num_elems) {
+ return NULL;
+ }
+
+ /* first frame is the latest frame */
+ latest_frame = (wasm_frame_t *)trap->frames->data;
+ return wasm_frame_copy(latest_frame);
+}
+
+void
+wasm_trap_trace(const wasm_trap_t *trap, own wasm_frame_vec_t *out)
+{
+ uint32 i;
+
+ if (!trap || !out) {
+ return;
+ }
+
+ if (!trap->frames || !trap->frames->num_elems) {
+ wasm_frame_vec_new_empty(out);
+ return;
+ }
+
+ wasm_frame_vec_new_uninitialized(out, trap->frames->num_elems);
+ if (out->size == 0 || !out->data) {
+ return;
+ }
+
+ for (i = 0; i < trap->frames->num_elems; i++) {
+ wasm_frame_t *frame;
+
+ frame = ((wasm_frame_t *)trap->frames->data) + i;
+
+ if (!(out->data[i] =
+ wasm_frame_new(frame->instance, frame->module_offset,
+ frame->func_index, frame->func_offset))) {
+ goto failed;
+ }
+ out->num_elems++;
+ }
+
+ return;
+failed:
+ for (i = 0; i < out->num_elems; i++) {
+ if (out->data[i]) {
+ wasm_runtime_free(out->data[i]);
+ }
+ }
+
+ wasm_runtime_free(out->data);
+}
+
+wasm_foreign_t *
+wasm_foreign_new_internal(wasm_store_t *store, uint32 foreign_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt)
+{
+ wasm_foreign_t *foreign = NULL;
+
+ if (!store || !store->foreigns)
+ return NULL;
+
+ if (!(bh_vector_get(store->foreigns, foreign_idx_rt, &foreign))
+ || !foreign) {
+ return NULL;
+ }
+
+ foreign->ref_cnt++;
+ (void)inst_comm_rt;
+ return foreign;
+}
+
+own wasm_foreign_t *
+wasm_foreign_new(wasm_store_t *store)
+{
+ wasm_foreign_t *foreign;
+
+ if (!store)
+ return NULL;
+
+ if (!(foreign = malloc_internal(sizeof(wasm_foreign_t))))
+ return NULL;
+
+ foreign->store = store;
+ foreign->kind = WASM_REF_foreign;
+ foreign->foreign_idx_rt = (uint32)bh_vector_size(store->foreigns);
+ if (!(bh_vector_append(store->foreigns, &foreign))) {
+ wasm_runtime_free(foreign);
+ return NULL;
+ }
+
+ return foreign;
+}
+
+void
+wasm_foreign_delete(wasm_foreign_t *foreign)
+{
+ if (!foreign)
+ return;
+
+ if (foreign->ref_cnt < 1) {
+ return;
+ }
+
+ foreign->ref_cnt--;
+ if (!foreign->ref_cnt) {
+ wasm_runtime_free(foreign);
+ }
+}
+
+static inline wasm_module_t *
+module_ext_to_module(wasm_module_ex_t *module_ex)
+{
+ return (wasm_module_t *)module_ex;
+}
+
+static inline wasm_module_ex_t *
+module_to_module_ext(wasm_module_t *module)
+{
+ return (wasm_module_ex_t *)module;
+}
+
+#if WASM_ENABLE_INTERP != 0
+#define MODULE_INTERP(module_comm) ((WASMModule *)(*module_comm))
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#define MODULE_AOT(module_comm) ((AOTModule *)(*module_comm))
+#endif
+
+#if WASM_ENABLE_WASM_CACHE != 0
+static wasm_module_ex_t *
+check_loaded_module(Vector *modules, char *binary_hash)
+{
+ unsigned i;
+ wasm_module_ex_t *module = NULL;
+
+ for (i = 0; i < modules->num_elems; i++) {
+ bh_vector_get(modules, i, &module);
+ if (!module) {
+ LOG_ERROR("Unexpected failure at %d\n", __LINE__);
+ return NULL;
+ }
+
+ if (!module->ref_count)
+ /* deleted */
+ continue;
+
+ if (memcmp(module->hash, binary_hash, SHA256_DIGEST_LENGTH) == 0)
+ return module;
+ }
+ return NULL;
+}
+
+static wasm_module_ex_t *
+try_reuse_loaded_module(wasm_store_t *store, char *binary_hash)
+{
+ wasm_module_ex_t *cached = NULL;
+ wasm_module_ex_t *ret = NULL;
+
+ cached = check_loaded_module(&singleton_engine->modules, binary_hash);
+ if (!cached)
+ goto quit;
+
+ os_mutex_lock(&cached->lock);
+ if (!cached->ref_count)
+ goto unlock;
+
+ if (!bh_vector_append((Vector *)store->modules, &cached))
+ goto unlock;
+
+ cached->ref_count += 1;
+ ret = cached;
+
+unlock:
+ os_mutex_unlock(&cached->lock);
+quit:
+ return ret;
+}
+#endif /* WASM_ENABLE_WASM_CACHE != 0 */
+
+wasm_module_t *
+wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
+{
+ char error_buf[128] = { 0 };
+ wasm_module_ex_t *module_ex = NULL;
+#if WASM_ENABLE_WASM_CACHE != 0
+ char binary_hash[SHA256_DIGEST_LENGTH] = { 0 };
+#endif
+
+ bh_assert(singleton_engine);
+
+ if (!store || !binary || binary->size == 0 || binary->size > UINT32_MAX)
+ goto quit;
+
+ /* whether the combination of compilation flags are compatable with the
+ * package type */
+ {
+ PackageType pkg_type;
+ pkg_type =
+ get_package_type((uint8 *)binary->data, (uint32)binary->size);
+ bool result = false;
+#if WASM_ENABLE_INTERP != 0
+ result = (pkg_type == Wasm_Module_Bytecode);
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ result = result || (pkg_type == Wasm_Module_AoT);
+#endif
+ if (!result) {
+ LOG_VERBOSE("current building isn't compatiable with the module,"
+ "may need recompile");
+ goto quit;
+ }
+ }
+
+#if WASM_ENABLE_WASM_CACHE != 0
+ /* if cached */
+ SHA256((void *)binary->data, binary->num_elems, (uint8_t *)binary_hash);
+ module_ex = try_reuse_loaded_module(store, binary_hash);
+ if (module_ex)
+ return module_ext_to_module(module_ex);
+#endif
+
+ WASM_C_DUMP_PROC_MEM();
+
+ module_ex = malloc_internal(sizeof(wasm_module_ex_t));
+ if (!module_ex)
+ goto quit;
+
+ module_ex->binary = malloc_internal(sizeof(wasm_byte_vec_t));
+ if (!module_ex->binary)
+ goto free_module;
+
+ wasm_byte_vec_copy(module_ex->binary, binary);
+ if (!module_ex->binary->data)
+ goto free_binary;
+
+ module_ex->module_comm_rt = wasm_runtime_load(
+ (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
+ error_buf, (uint32)sizeof(error_buf));
+ if (!(module_ex->module_comm_rt)) {
+ LOG_ERROR(error_buf);
+ goto free_vec;
+ }
+
+ /* append it to a watching list in store */
+ if (!bh_vector_append((Vector *)store->modules, &module_ex))
+ goto unload;
+
+ if (os_mutex_init(&module_ex->lock) != BHT_OK)
+ goto remove_last;
+
+ if (!bh_vector_append(&singleton_engine->modules, &module_ex))
+ goto destroy_lock;
+
+#if WASM_ENABLE_WASM_CACHE != 0
+ bh_memcpy_s(module_ex->hash, sizeof(module_ex->hash), binary_hash,
+ sizeof(binary_hash));
+#endif
+
+ module_ex->ref_count = 1;
+
+ WASM_C_DUMP_PROC_MEM();
+
+ return module_ext_to_module(module_ex);
+
+destroy_lock:
+ os_mutex_destroy(&module_ex->lock);
+remove_last:
+ bh_vector_remove((Vector *)store->modules,
+ (uint32)(store->modules->num_elems - 1), NULL);
+unload:
+ wasm_runtime_unload(module_ex->module_comm_rt);
+free_vec:
+ wasm_byte_vec_delete(module_ex->binary);
+free_binary:
+ wasm_runtime_free(module_ex->binary);
+free_module:
+ wasm_runtime_free(module_ex);
+quit:
+ LOG_ERROR("%s failed", __FUNCTION__);
+ return NULL;
+}
+
+bool
+wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary)
+{
+ struct WASMModuleCommon *module_rt;
+ char error_buf[128] = { 0 };
+
+ bh_assert(singleton_engine);
+
+ if (!store || !binary || binary->size > UINT32_MAX) {
+ LOG_ERROR("%s failed", __FUNCTION__);
+ return false;
+ }
+
+ if ((module_rt = wasm_runtime_load((uint8 *)binary->data,
+ (uint32)binary->size, error_buf, 128))) {
+ wasm_runtime_unload(module_rt);
+ return true;
+ }
+ else {
+ LOG_VERBOSE(error_buf);
+ return false;
+ }
+}
+
+static void
+wasm_module_delete_internal(wasm_module_t *module)
+{
+ wasm_module_ex_t *module_ex;
+
+ if (!module) {
+ return;
+ }
+
+ module_ex = module_to_module_ext(module);
+
+ os_mutex_lock(&module_ex->lock);
+
+ /* N -> N-1 -> 0 -> UINT32_MAX */
+ module_ex->ref_count--;
+ if (module_ex->ref_count > 0) {
+ os_mutex_unlock(&module_ex->lock);
+ return;
+ }
+
+ DEINIT_VEC(module_ex->binary, wasm_byte_vec_delete);
+
+ if (module_ex->module_comm_rt) {
+ wasm_runtime_unload(module_ex->module_comm_rt);
+ module_ex->module_comm_rt = NULL;
+ }
+
+#if WASM_ENABLE_WASM_CACHE != 0
+ memset(module_ex->hash, 0, sizeof(module_ex->hash));
+#endif
+
+ os_mutex_unlock(&module_ex->lock);
+}
+
+void
+wasm_module_delete(wasm_module_t *module)
+{
+ /* the module will be released when releasing the store */
+ (void)module;
+}
+
+void
+wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
+{
+ uint32 i, import_func_count = 0, import_memory_count = 0,
+ import_global_count = 0, import_table_count = 0, import_count = 0;
+ wasm_byte_vec_t module_name = { 0 }, name = { 0 };
+ wasm_externtype_t *extern_type = NULL;
+ wasm_importtype_t *import_type = NULL;
+
+ if (!module || !out) {
+ return;
+ }
+
+ if (((const wasm_module_ex_t *)(module))->ref_count == 0)
+ return;
+
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ import_func_count = MODULE_INTERP(module)->import_function_count;
+ import_global_count = MODULE_INTERP(module)->import_global_count;
+ import_memory_count = MODULE_INTERP(module)->import_memory_count;
+ import_table_count = MODULE_INTERP(module)->import_table_count;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ import_func_count = MODULE_AOT(module)->import_func_count;
+ import_global_count = MODULE_AOT(module)->import_global_count;
+ import_memory_count = MODULE_AOT(module)->import_memory_count;
+ import_table_count = MODULE_AOT(module)->import_table_count;
+ }
+#endif
+
+ import_count = import_func_count + import_global_count + import_table_count
+ + import_memory_count;
+
+ wasm_importtype_vec_new_uninitialized(out, import_count);
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * also leads to below branch
+ */
+ if (!out->data) {
+ return;
+ }
+
+ for (i = 0; i != import_count; ++i) {
+ char *module_name_rt = NULL, *field_name_rt = NULL;
+
+ memset(&module_name, 0, sizeof(wasm_val_vec_t));
+ memset(&name, 0, sizeof(wasm_val_vec_t));
+ extern_type = NULL;
+ import_type = NULL;
+
+ if (i < import_func_count) {
+ wasm_functype_t *type = NULL;
+ WASMType *type_rt = NULL;
+
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ WASMImport *import =
+ MODULE_INTERP(module)->import_functions + i;
+ module_name_rt = import->u.names.module_name;
+ field_name_rt = import->u.names.field_name;
+ type_rt = import->u.function.func_type;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ AOTImportFunc *import = MODULE_AOT(module)->import_funcs + i;
+ module_name_rt = import->module_name;
+ field_name_rt = import->func_name;
+ type_rt = import->func_type;
+ }
+#endif
+
+ if (!module_name_rt || !field_name_rt || !type_rt) {
+ continue;
+ }
+
+ if (!(type = wasm_functype_new_internal(type_rt))) {
+ goto failed;
+ }
+
+ extern_type = wasm_functype_as_externtype(type);
+ }
+ else if (i < import_func_count + import_global_count) {
+ wasm_globaltype_t *type = NULL;
+ uint8 val_type_rt = 0;
+ bool mutability_rt = 0;
+
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ WASMImport *import = MODULE_INTERP(module)->import_globals
+ + (i - import_func_count);
+ module_name_rt = import->u.names.module_name;
+ field_name_rt = import->u.names.field_name;
+ val_type_rt = import->u.global.type;
+ mutability_rt = import->u.global.is_mutable;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ AOTImportGlobal *import = MODULE_AOT(module)->import_globals
+ + (i - import_func_count);
+ module_name_rt = import->module_name;
+ field_name_rt = import->global_name;
+ val_type_rt = import->type;
+ mutability_rt = import->is_mutable;
+ }
+#endif
+
+ if (!module_name_rt || !field_name_rt) {
+ continue;
+ }
+
+ if (!(type = wasm_globaltype_new_internal(val_type_rt,
+ mutability_rt))) {
+ goto failed;
+ }
+
+ extern_type = wasm_globaltype_as_externtype(type);
+ }
+ else if (i < import_func_count + import_global_count
+ + import_memory_count) {
+ wasm_memorytype_t *type = NULL;
+ uint32 min_page = 0, max_page = 0;
+
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ WASMImport *import =
+ MODULE_INTERP(module)->import_memories
+ + (i - import_func_count - import_global_count);
+ module_name_rt = import->u.names.module_name;
+ field_name_rt = import->u.names.field_name;
+ min_page = import->u.memory.init_page_count;
+ max_page = import->u.memory.max_page_count;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ AOTImportMemory *import =
+ MODULE_AOT(module)->import_memories
+ + (i - import_func_count - import_global_count);
+ module_name_rt = import->module_name;
+ field_name_rt = import->memory_name;
+ min_page = import->mem_init_page_count;
+ max_page = import->mem_max_page_count;
+ }
+#endif
+
+ if (!module_name_rt || !field_name_rt) {
+ continue;
+ }
+
+ if (!(type = wasm_memorytype_new_internal(min_page, max_page))) {
+ goto failed;
+ }
+
+ extern_type = wasm_memorytype_as_externtype(type);
+ }
+ else {
+ wasm_tabletype_t *type = NULL;
+ uint8 elem_type_rt = 0;
+ uint32 min_size = 0, max_size = 0;
+
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ WASMImport *import =
+ MODULE_INTERP(module)->import_tables
+ + (i - import_func_count - import_global_count
+ - import_memory_count);
+ module_name_rt = import->u.names.module_name;
+ field_name_rt = import->u.names.field_name;
+ elem_type_rt = import->u.table.elem_type;
+ min_size = import->u.table.init_size;
+ max_size = import->u.table.max_size;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ AOTImportTable *import =
+ MODULE_AOT(module)->import_tables
+ + (i - import_func_count - import_global_count
+ - import_memory_count);
+ module_name_rt = import->module_name;
+ field_name_rt = import->table_name;
+ elem_type_rt = import->elem_type;
+ min_size = import->table_init_size;
+ max_size = import->table_max_size;
+ }
+#endif
+
+ if (!module_name_rt || !field_name_rt) {
+ continue;
+ }
+
+ if (!(type = wasm_tabletype_new_internal(elem_type_rt, min_size,
+ max_size))) {
+ goto failed;
+ }
+
+ extern_type = wasm_tabletype_as_externtype(type);
+ }
+
+ bh_assert(extern_type);
+
+ wasm_name_new_from_string_nt(&module_name, module_name_rt);
+ if (strlen(module_name_rt) && !module_name.data) {
+ goto failed;
+ }
+
+ wasm_name_new_from_string_nt(&name, field_name_rt);
+ if (strlen(field_name_rt) && !name.data) {
+ goto failed;
+ }
+
+ if (!(import_type =
+ wasm_importtype_new(&module_name, &name, extern_type))) {
+ goto failed;
+ }
+
+ if (!bh_vector_append((Vector *)out, &import_type)) {
+ goto failed_importtype_new;
+ }
+
+ continue;
+
+ failed:
+ wasm_byte_vec_delete(&module_name);
+ wasm_byte_vec_delete(&name);
+ wasm_externtype_delete(extern_type);
+ failed_importtype_new:
+ wasm_importtype_delete(import_type);
+ }
+}
+
+void
+wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
+{
+ uint32 i, export_count = 0;
+ wasm_byte_vec_t name = { 0 };
+ wasm_externtype_t *extern_type = NULL;
+ wasm_exporttype_t *export_type = NULL;
+
+ if (!module || !out) {
+ return;
+ }
+
+ if (((const wasm_module_ex_t *)(module))->ref_count == 0)
+ return;
+
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ export_count = MODULE_INTERP(module)->export_count;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ export_count = MODULE_AOT(module)->export_count;
+ }
+#endif
+
+ wasm_exporttype_vec_new_uninitialized(out, export_count);
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * also leads to below branch
+ */
+ if (!out->data) {
+ return;
+ }
+
+ for (i = 0; i != export_count; i++) {
+ WASMExport *export = NULL;
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ export = MODULE_INTERP(module)->exports + i;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ export = MODULE_AOT(module)->exports + i;
+ }
+#endif
+
+ if (!export) {
+ continue;
+ }
+
+ /* byte* -> wasm_byte_vec_t */
+ wasm_name_new_from_string_nt(&name, export->name);
+ if (strlen(export->name) && !name.data) {
+ goto failed;
+ }
+
+ /* WASMExport -> (WASMType, (uint8, bool)) -> (wasm_functype_t,
+ * wasm_globaltype_t) -> wasm_externtype_t*/
+ switch (export->kind) {
+ case EXPORT_KIND_FUNC:
+ {
+ wasm_functype_t *type = NULL;
+ WASMType *type_rt;
+
+ if (!wasm_runtime_get_export_func_type(*module, export,
+ &type_rt)) {
+ goto failed;
+ }
+
+ if (!(type = wasm_functype_new_internal(type_rt))) {
+ goto failed;
+ }
+
+ extern_type = wasm_functype_as_externtype(type);
+ break;
+ }
+ case EXPORT_KIND_GLOBAL:
+ {
+ wasm_globaltype_t *type = NULL;
+ uint8 val_type_rt = 0;
+ bool mutability_rt = 0;
+
+ if (!wasm_runtime_get_export_global_type(
+ *module, export, &val_type_rt, &mutability_rt)) {
+ goto failed;
+ }
+
+ if (!(type = wasm_globaltype_new_internal(val_type_rt,
+ mutability_rt))) {
+ goto failed;
+ }
+
+ extern_type = wasm_globaltype_as_externtype(type);
+ break;
+ }
+ case EXPORT_KIND_MEMORY:
+ {
+ wasm_memorytype_t *type = NULL;
+ uint32 min_page = 0, max_page = 0;
+
+ if (!wasm_runtime_get_export_memory_type(
+ *module, export, &min_page, &max_page)) {
+ goto failed;
+ }
+
+ if (!(type =
+ wasm_memorytype_new_internal(min_page, max_page))) {
+ goto failed;
+ }
+
+ extern_type = wasm_memorytype_as_externtype(type);
+ break;
+ }
+ case EXPORT_KIND_TABLE:
+ {
+ wasm_tabletype_t *type = NULL;
+ uint8 elem_type_rt = 0;
+ uint32 min_size = 0, max_size = 0;
+
+ if (!wasm_runtime_get_export_table_type(
+ *module, export, &elem_type_rt, &min_size, &max_size)) {
+ goto failed;
+ }
+
+ if (!(type = wasm_tabletype_new_internal(elem_type_rt, min_size,
+ max_size))) {
+ goto failed;
+ }
+
+ extern_type = wasm_tabletype_as_externtype(type);
+ break;
+ }
+ default:
+ {
+ LOG_WARNING("%s meets unsupported type %u", __FUNCTION__,
+ export->kind);
+ break;
+ }
+ }
+
+ if (!(export_type = wasm_exporttype_new(&name, extern_type))) {
+ goto failed;
+ }
+
+ if (!(bh_vector_append((Vector *)out, &export_type))) {
+ goto failed_exporttype_new;
+ }
+ }
+
+ return;
+
+failed:
+ wasm_byte_vec_delete(&name);
+ wasm_externtype_delete(extern_type);
+failed_exporttype_new:
+ wasm_exporttype_delete(export_type);
+ wasm_exporttype_vec_delete(out);
+}
+
+#if WASM_ENABLE_JIT == 0 || WASM_ENABLE_LAZY_JIT != 0
+void
+wasm_module_serialize(wasm_module_t *module, own wasm_byte_vec_t *out)
+{
+ (void)module;
+ (void)out;
+ LOG_ERROR("only supported serialization in JIT with eager compilation");
+}
+
+own wasm_module_t *
+wasm_module_deserialize(wasm_store_t *module, const wasm_byte_vec_t *binary)
+{
+ (void)module;
+ (void)binary;
+ LOG_ERROR("only supported deserialization in JIT with eager compilation");
+ return NULL;
+}
+#else
+
+extern uint8 *
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ uint32 *p_aot_file_size);
+void
+wasm_module_serialize(wasm_module_t *module, own wasm_byte_vec_t *out)
+{
+ wasm_module_ex_t *module_ex;
+ AOTCompContext *comp_ctx;
+ AOTCompData *comp_data;
+ uint8 *aot_file_buf = NULL;
+ uint32 aot_file_size = 0;
+
+ if (!module || !out)
+ return;
+
+ if (((const wasm_module_ex_t *)(module))->ref_count == 0)
+ return;
+
+ module_ex = module_to_module_ext(module);
+ comp_ctx = ((WASMModule *)(module_ex->module_comm_rt))->comp_ctx;
+ comp_data = ((WASMModule *)(module_ex->module_comm_rt))->comp_data;
+ bh_assert(comp_ctx != NULL && comp_data != NULL);
+
+ aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size);
+ if (!aot_file_buf)
+ return;
+
+ wasm_byte_vec_new(out, aot_file_size, (wasm_byte_t *)aot_file_buf);
+ wasm_runtime_free(aot_file_buf);
+ return;
+}
+
+own wasm_module_t *
+wasm_module_deserialize(wasm_store_t *store, const wasm_byte_vec_t *binary)
+{
+ return wasm_module_new(store, binary);
+}
+#endif
+
+wasm_module_t *
+wasm_module_obtain(wasm_store_t *store, wasm_shared_module_t *shared_module)
+{
+ wasm_module_ex_t *module_ex = NULL;
+
+ if (!store || !shared_module)
+ return NULL;
+
+ module_ex = (wasm_module_ex_t *)shared_module;
+
+ os_mutex_lock(&module_ex->lock);
+
+ /* deleting the module... */
+ if (module_ex->ref_count == 0) {
+ LOG_WARNING("wasm_module_obtain re-enter a module under deleting.");
+ os_mutex_unlock(&module_ex->lock);
+ return NULL;
+ }
+
+ /* add it to a watching list in store */
+ if (!bh_vector_append((Vector *)store->modules, &module_ex)) {
+ os_mutex_unlock(&module_ex->lock);
+ return NULL;
+ }
+
+ module_ex->ref_count++;
+ os_mutex_unlock(&module_ex->lock);
+
+ return (wasm_module_t *)shared_module;
+}
+
+wasm_shared_module_t *
+wasm_module_share(wasm_module_t *module)
+{
+ wasm_module_ex_t *module_ex = NULL;
+
+ if (!module)
+ return NULL;
+
+ module_ex = (wasm_module_ex_t *)module;
+
+ os_mutex_lock(&module_ex->lock);
+
+ /* deleting the module... */
+ if (module_ex->ref_count == 0) {
+ LOG_WARNING("wasm_module_share re-enter a module under deleting.");
+ os_mutex_unlock(&module_ex->lock);
+ return NULL;
+ }
+
+ module_ex->ref_count++;
+
+ os_mutex_unlock(&module_ex->lock);
+
+ return (wasm_shared_module_t *)module;
+}
+
+void
+wasm_shared_module_delete(own wasm_shared_module_t *shared_module)
+{
+ wasm_module_delete_internal((wasm_module_t *)shared_module);
+}
+
+static wasm_func_t *
+wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type,
+ wasm_func_callback_t func_callback)
+{
+ wasm_func_t *func = NULL;
+
+ if (!type) {
+ goto failed;
+ }
+
+ if (!(func = malloc_internal(sizeof(wasm_func_t)))) {
+ goto failed;
+ }
+
+ func->store = store;
+ func->kind = WASM_EXTERN_FUNC;
+ func->func_idx_rt = (uint16)-1;
+ func->with_env = false;
+ func->u.cb = func_callback;
+
+ if (!(func->type = wasm_functype_copy(type))) {
+ goto failed;
+ }
+
+ RETURN_OBJ(func, wasm_func_delete)
+}
+
+static wasm_func_t *
+wasm_func_new_with_env_basic(wasm_store_t *store, const wasm_functype_t *type,
+ wasm_func_callback_with_env_t callback, void *env,
+ void (*finalizer)(void *))
+{
+ wasm_func_t *func = NULL;
+
+ if (!type) {
+ goto failed;
+ }
+
+ if (!(func = malloc_internal(sizeof(wasm_func_t)))) {
+ goto failed;
+ }
+
+ func->store = store;
+ func->kind = WASM_EXTERN_FUNC;
+ func->func_idx_rt = (uint16)-1;
+ func->with_env = true;
+ func->u.cb_env.cb = callback;
+ func->u.cb_env.env = env;
+ func->u.cb_env.finalizer = finalizer;
+
+ if (!(func->type = wasm_functype_copy(type))) {
+ goto failed;
+ }
+
+ RETURN_OBJ(func, wasm_func_delete)
+}
+
+wasm_func_t *
+wasm_func_new(wasm_store_t *store, const wasm_functype_t *type,
+ wasm_func_callback_t callback)
+{
+ bh_assert(singleton_engine);
+ if (!callback) {
+ return NULL;
+ }
+ return wasm_func_new_basic(store, type, callback);
+}
+
+wasm_func_t *
+wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *type,
+ wasm_func_callback_with_env_t callback, void *env,
+ void (*finalizer)(void *))
+{
+ bh_assert(singleton_engine);
+ if (!callback) {
+ return NULL;
+ }
+ return wasm_func_new_with_env_basic(store, type, callback, env, finalizer);
+}
+
+wasm_func_t *
+wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt)
+{
+ wasm_func_t *func = NULL;
+ WASMType *type_rt = NULL;
+
+ bh_assert(singleton_engine);
+
+ if (!inst_comm_rt) {
+ return NULL;
+ }
+
+ func = malloc_internal(sizeof(wasm_func_t));
+ if (!func) {
+ goto failed;
+ }
+
+ func->kind = WASM_EXTERN_FUNC;
+
+#if WASM_ENABLE_INTERP != 0
+ if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ bh_assert(func_idx_rt
+ < ((WASMModuleInstance *)inst_comm_rt)->e->function_count);
+ WASMFunctionInstance *func_interp =
+ ((WASMModuleInstance *)inst_comm_rt)->e->functions + func_idx_rt;
+ type_rt = func_interp->is_import_func
+ ? func_interp->u.func_import->func_type
+ : func_interp->u.func->func_type;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+ /* use same index to trace the function type in AOTFuncType **func_types
+ */
+ AOTModule *module_aot =
+ (AOTModule *)((AOTModuleInstance *)inst_comm_rt)->module;
+ if (func_idx_rt < module_aot->import_func_count) {
+ type_rt = (module_aot->import_funcs + func_idx_rt)->func_type;
+ }
+ else {
+ type_rt =
+ module_aot->func_types[module_aot->func_type_indexes
+ [func_idx_rt
+ - module_aot->import_func_count]];
+ }
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * also leads to below branch
+ */
+ if (!type_rt) {
+ goto failed;
+ }
+
+ func->type = wasm_functype_new_internal(type_rt);
+ if (!func->type) {
+ goto failed;
+ }
+
+ /* will add name information when processing "exports" */
+ func->store = store;
+ func->module_name = NULL;
+ func->name = NULL;
+ func->func_idx_rt = func_idx_rt;
+ func->inst_comm_rt = inst_comm_rt;
+ return func;
+
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ wasm_func_delete(func);
+ return NULL;
+}
+
+static wasm_func_t *
+wasm_func_new_empty(wasm_store_t *store)
+{
+ wasm_func_t *func = NULL;
+
+ if (!(func = malloc_internal(sizeof(wasm_func_t))))
+ goto failed;
+
+ func->store = store;
+ func->kind = WASM_EXTERN_FUNC;
+
+ RETURN_OBJ(func, wasm_func_delete)
+}
+
+void
+wasm_func_delete(wasm_func_t *func)
+{
+ if (!func) {
+ return;
+ }
+
+ if (func->type) {
+ wasm_functype_delete(func->type);
+ func->type = NULL;
+ }
+
+ if (func->with_env) {
+ if (func->u.cb_env.finalizer) {
+ func->u.cb_env.finalizer(func->u.cb_env.env);
+ func->u.cb_env.finalizer = NULL;
+ func->u.cb_env.env = NULL;
+ }
+ }
+
+ DELETE_HOST_INFO(func)
+
+ wasm_runtime_free(func);
+}
+
+own wasm_func_t *
+wasm_func_copy(const wasm_func_t *func)
+{
+ wasm_func_t *cloned = NULL;
+
+ if (!func) {
+ return NULL;
+ }
+
+ if (!(cloned = func->with_env ? wasm_func_new_with_env_basic(
+ func->store, func->type, func->u.cb_env.cb,
+ func->u.cb_env.env, func->u.cb_env.finalizer)
+ : wasm_func_new_basic(func->store, func->type,
+ func->u.cb))) {
+ goto failed;
+ }
+
+ cloned->func_idx_rt = func->func_idx_rt;
+ cloned->inst_comm_rt = func->inst_comm_rt;
+
+ RETURN_OBJ(cloned, wasm_func_delete)
+}
+
+own wasm_functype_t *
+wasm_func_type(const wasm_func_t *func)
+{
+ if (!func) {
+ return NULL;
+ }
+ return wasm_functype_copy(func->type);
+}
+
+static bool
+params_to_argv(const wasm_val_vec_t *params,
+ const wasm_valtype_vec_t *param_defs, uint32 *argv,
+ uint32 *ptr_argc)
+{
+ size_t i = 0;
+
+ if (!param_defs->num_elems) {
+ return true;
+ }
+
+ if (!params || !params->num_elems || !params->size || !params->data) {
+ LOG_ERROR("the parameter params is invalid");
+ return false;
+ }
+
+ *ptr_argc = 0;
+ for (i = 0; i < param_defs->num_elems; ++i) {
+ const wasm_val_t *param = params->data + i;
+ bh_assert((*(param_defs->data + i))->kind == param->kind);
+
+ switch (param->kind) {
+ case WASM_I32:
+ *(int32 *)argv = param->of.i32;
+ argv += 1;
+ *ptr_argc += 1;
+ break;
+ case WASM_I64:
+ *(int64 *)argv = param->of.i64;
+ argv += 2;
+ *ptr_argc += 2;
+ break;
+ case WASM_F32:
+ *(float32 *)argv = param->of.f32;
+ argv += 1;
+ *ptr_argc += 1;
+ break;
+ case WASM_F64:
+ *(float64 *)argv = param->of.f64;
+ argv += 2;
+ *ptr_argc += 2;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_ANYREF:
+ *(uintptr_t *)argv = (uintptr_t)param->of.ref;
+ argv += sizeof(uintptr_t) / sizeof(uint32);
+ *ptr_argc += 1;
+ break;
+#endif
+ default:
+ LOG_WARNING("unexpected parameter val type %d", param->kind);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
+ wasm_val_vec_t *results)
+{
+ size_t i = 0, argv_i = 0;
+ wasm_val_t *result;
+
+ if (!result_defs->num_elems) {
+ return true;
+ }
+
+ if (!results || !results->size || !results->data) {
+ LOG_ERROR("the parameter results is invalid");
+ return false;
+ }
+
+ for (i = 0, result = results->data, argv_i = 0; i < result_defs->num_elems;
+ i++, result++) {
+ switch (result_defs->data[i]->kind) {
+ case WASM_I32:
+ {
+ result->kind = WASM_I32;
+ result->of.i32 = *(int32 *)(argv + argv_i);
+ argv_i += 1;
+ break;
+ }
+ case WASM_I64:
+ {
+ result->kind = WASM_I64;
+ result->of.i64 = *(int64 *)(argv + argv_i);
+ argv_i += 2;
+ break;
+ }
+ case WASM_F32:
+ {
+ result->kind = WASM_F32;
+ result->of.f32 = *(float32 *)(argv + argv_i);
+ argv_i += 1;
+ break;
+ }
+ case WASM_F64:
+ {
+ result->kind = WASM_F64;
+ result->of.f64 = *(float64 *)(argv + argv_i);
+ argv_i += 2;
+ break;
+ }
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_ANYREF:
+ {
+ result->kind = WASM_ANYREF;
+ result->of.ref =
+ (struct wasm_ref_t *)(*(uintptr_t *)(argv + argv_i));
+ argv_i += sizeof(uintptr_t) / sizeof(uint32);
+ break;
+ }
+#endif
+ default:
+ LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
+ result_defs->data[i]->kind);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+wasm_trap_t *
+wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
+ wasm_val_vec_t *results)
+{
+ /* parameters count as if all are uint32 */
+ /* a int64 or float64 parameter means 2 */
+ uint32 argc = 0;
+ /* a parameter list and a return value list */
+ uint32 argv_buf[32] = { 0 }, *argv = argv_buf;
+ WASMFunctionInstanceCommon *func_comm_rt = NULL;
+ WASMExecEnv *exec_env = NULL;
+ size_t param_count, result_count, alloc_count;
+
+ if (!func) {
+ return NULL;
+ }
+
+ if (!func->inst_comm_rt) {
+ wasm_name_t message = { 0 };
+ wasm_trap_t *trap;
+
+ wasm_name_new_from_string_nt(&message,
+ "failed to call unlinked function");
+ trap = wasm_trap_new(func->store, &message);
+ wasm_byte_vec_delete(&message);
+
+ return trap;
+ }
+
+ bh_assert(func->type);
+
+#if WASM_ENABLE_INTERP != 0
+ if (func->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->e->functions
+ + func->func_idx_rt;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (func->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ if (!(func_comm_rt = func->func_comm_rt)) {
+ AOTModuleInstance *inst_aot =
+ (AOTModuleInstance *)func->inst_comm_rt;
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+ uint32 export_i = 0, export_func_j = 0;
+
+ for (; export_i < module_aot->export_count; ++export_i) {
+ AOTExport *export = module_aot->exports + export_i;
+ if (export->kind == EXPORT_KIND_FUNC) {
+ if (export->index == func->func_idx_rt) {
+ func_comm_rt =
+ (AOTFunctionInstance *)inst_aot->export_functions
+ + export_func_j;
+ ((wasm_func_t *)func)->func_comm_rt = func_comm_rt;
+ break;
+ }
+ export_func_j++;
+ }
+ }
+ }
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * also leads to below branch
+ */
+ if (!func_comm_rt) {
+ goto failed;
+ }
+
+ param_count = wasm_func_param_arity(func);
+ result_count = wasm_func_result_arity(func);
+
+ alloc_count = (param_count > result_count) ? param_count : result_count;
+ if (alloc_count > (size_t)sizeof(argv_buf) / sizeof(uint64)) {
+ if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) {
+ goto failed;
+ }
+ }
+
+ /* copy parametes */
+ if (param_count
+ && !params_to_argv(params, wasm_functype_params(func->type), argv,
+ &argc)) {
+ goto failed;
+ }
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = wasm_runtime_get_exec_env_tls();
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env) {
+ exec_env = wasm_clusters_search_exec_env(func->inst_comm_rt);
+ }
+#endif
+ if (!exec_env) {
+ exec_env = wasm_runtime_get_exec_env_singleton(func->inst_comm_rt);
+ }
+ if (!exec_env) {
+ goto failed;
+ }
+
+ wasm_runtime_set_exception(func->inst_comm_rt, NULL);
+ if (!wasm_runtime_call_wasm(exec_env, func_comm_rt, argc, argv)) {
+ if (wasm_runtime_get_exception(func->inst_comm_rt)) {
+ LOG_DEBUG(wasm_runtime_get_exception(func->inst_comm_rt));
+ goto failed;
+ }
+ }
+
+ /* copy results */
+ if (result_count) {
+ if (!argv_to_results(argv, wasm_functype_results(func->type),
+ results)) {
+ goto failed;
+ }
+ results->num_elems = result_count;
+ results->size = result_count;
+ }
+
+ if (argv != argv_buf)
+ wasm_runtime_free(argv);
+ return NULL;
+
+failed:
+ if (argv != argv_buf)
+ wasm_runtime_free(argv);
+
+ return wasm_trap_new_internal(
+ func->store, func->inst_comm_rt,
+ wasm_runtime_get_exception(func->inst_comm_rt));
+}
+
+size_t
+wasm_func_param_arity(const wasm_func_t *func)
+{
+ if (!func || !func->type || !func->type->params) {
+ return 0;
+ }
+ return func->type->params->num_elems;
+}
+
+size_t
+wasm_func_result_arity(const wasm_func_t *func)
+{
+ if (!func || !func->type || !func->type->results) {
+ return 0;
+ }
+ return func->type->results->num_elems;
+}
+
+wasm_global_t *
+wasm_global_new(wasm_store_t *store, const wasm_globaltype_t *global_type,
+ const wasm_val_t *init)
+{
+ wasm_global_t *global = NULL;
+
+ bh_assert(singleton_engine);
+
+ if (!global_type || !init) {
+ goto failed;
+ }
+
+ global = malloc_internal(sizeof(wasm_global_t));
+ if (!global) {
+ goto failed;
+ }
+
+ global->store = store;
+ global->kind = WASM_EXTERN_GLOBAL;
+ global->type = wasm_globaltype_copy(global_type);
+ if (!global->type) {
+ goto failed;
+ }
+
+ global->init = malloc_internal(sizeof(wasm_val_t));
+ if (!global->init) {
+ goto failed;
+ }
+
+ wasm_val_copy(global->init, init);
+ /* TODO: how to check if above is failed */
+
+ return global;
+
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ wasm_global_delete(global);
+ return NULL;
+}
+
+static wasm_global_t *
+wasm_global_new_empty(wasm_store_t *store)
+{
+ wasm_global_t *global = NULL;
+
+ global = malloc_internal(sizeof(wasm_global_t));
+ if (!global)
+ goto failed;
+
+ global->store = store;
+ global->kind = WASM_EXTERN_GLOBAL;
+
+ return global;
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ wasm_global_delete(global);
+ return NULL;
+}
+
+/* almost same with wasm_global_new */
+wasm_global_t *
+wasm_global_copy(const wasm_global_t *src)
+{
+ wasm_global_t *global = NULL;
+
+ if (!src) {
+ return NULL;
+ }
+
+ global = malloc_internal(sizeof(wasm_global_t));
+ if (!global) {
+ goto failed;
+ }
+
+ global->kind = WASM_EXTERN_GLOBAL;
+ global->type = wasm_globaltype_copy(src->type);
+ if (!global->type) {
+ goto failed;
+ }
+
+ global->init = malloc_internal(sizeof(wasm_val_t));
+ if (!global->init) {
+ goto failed;
+ }
+
+ wasm_val_copy(global->init, src->init);
+
+ global->global_idx_rt = src->global_idx_rt;
+ global->inst_comm_rt = src->inst_comm_rt;
+
+ return global;
+
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ wasm_global_delete(global);
+ return NULL;
+}
+
+void
+wasm_global_delete(wasm_global_t *global)
+{
+ if (!global) {
+ return;
+ }
+
+ if (global->init) {
+ wasm_val_delete(global->init);
+ global->init = NULL;
+ }
+
+ if (global->type) {
+ wasm_globaltype_delete(global->type);
+ global->type = NULL;
+ }
+
+ DELETE_HOST_INFO(global)
+
+ wasm_runtime_free(global);
+}
+
+#if WASM_ENABLE_INTERP != 0
+static bool
+interp_global_set(const WASMModuleInstance *inst_interp, uint16 global_idx_rt,
+ const wasm_val_t *v)
+{
+ const WASMGlobalInstance *global_interp =
+ inst_interp->e->globals + global_idx_rt;
+ uint8 val_type_rt = global_interp->type;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ uint8 *data = global_interp->import_global_inst
+ ? global_interp->import_module_inst->global_data
+ + global_interp->import_global_inst->data_offset
+ : inst_interp->global_data + global_interp->data_offset;
+#else
+ uint8 *data = inst_interp->global_data + global_interp->data_offset;
+#endif
+
+ return wasm_val_to_rt_val((WASMModuleInstanceCommon *)inst_interp,
+ val_type_rt, v, data);
+}
+
+static bool
+interp_global_get(const WASMModuleInstance *inst_interp, uint16 global_idx_rt,
+ wasm_val_t *out)
+{
+ WASMGlobalInstance *global_interp = inst_interp->e->globals + global_idx_rt;
+ uint8 val_type_rt = global_interp->type;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ uint8 *data = global_interp->import_global_inst
+ ? global_interp->import_module_inst->global_data
+ + global_interp->import_global_inst->data_offset
+ : inst_interp->global_data + global_interp->data_offset;
+#else
+ uint8 *data = inst_interp->global_data + global_interp->data_offset;
+#endif
+
+ return rt_val_to_wasm_val(data, val_type_rt, out);
+}
+#endif
+
+#if WASM_ENABLE_AOT != 0
+static bool
+aot_global_set(const AOTModuleInstance *inst_aot, uint16 global_idx_rt,
+ const wasm_val_t *v)
+{
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+ uint8 val_type_rt = 0;
+ uint32 data_offset = 0;
+ void *data = NULL;
+
+ if (global_idx_rt < module_aot->import_global_count) {
+ data_offset = module_aot->import_globals[global_idx_rt].data_offset;
+ val_type_rt = module_aot->import_globals[global_idx_rt].type;
+ }
+ else {
+ data_offset =
+ module_aot->globals[global_idx_rt - module_aot->import_global_count]
+ .data_offset;
+ val_type_rt =
+ module_aot->globals[global_idx_rt - module_aot->import_global_count]
+ .type;
+ }
+
+ data = (void *)(inst_aot->global_data + data_offset);
+ return wasm_val_to_rt_val((WASMModuleInstanceCommon *)inst_aot, val_type_rt,
+ v, data);
+}
+
+static bool
+aot_global_get(const AOTModuleInstance *inst_aot, uint16 global_idx_rt,
+ wasm_val_t *out)
+{
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+ uint8 val_type_rt = 0;
+ uint32 data_offset = 0;
+ uint8 *data = NULL;
+
+ if (global_idx_rt < module_aot->import_global_count) {
+ data_offset = module_aot->import_globals[global_idx_rt].data_offset;
+ val_type_rt = module_aot->import_globals[global_idx_rt].type;
+ }
+ else {
+ data_offset =
+ module_aot->globals[global_idx_rt - module_aot->import_global_count]
+ .data_offset;
+ val_type_rt =
+ module_aot->globals[global_idx_rt - module_aot->import_global_count]
+ .type;
+ }
+
+ data = inst_aot->global_data + data_offset;
+ return rt_val_to_wasm_val(data, val_type_rt, out);
+}
+#endif
+
+void
+wasm_global_set(wasm_global_t *global, const wasm_val_t *v)
+{
+ if (!global || !v || !global->inst_comm_rt) {
+ return;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (global->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ (void)interp_global_set((WASMModuleInstance *)global->inst_comm_rt,
+ global->global_idx_rt, v);
+ return;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (global->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ (void)aot_global_set((AOTModuleInstance *)global->inst_comm_rt,
+ global->global_idx_rt, v);
+ return;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ UNREACHABLE();
+}
+
+void
+wasm_global_get(const wasm_global_t *global, wasm_val_t *out)
+{
+ if (!global || !out) {
+ return;
+ }
+
+ if (!global->inst_comm_rt) {
+ return;
+ }
+
+ memset(out, 0, sizeof(wasm_val_t));
+
+#if WASM_ENABLE_INTERP != 0
+ if (global->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ (void)interp_global_get((WASMModuleInstance *)global->inst_comm_rt,
+ global->global_idx_rt, out);
+ return;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (global->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ (void)aot_global_get((AOTModuleInstance *)global->inst_comm_rt,
+ global->global_idx_rt, out);
+ return;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ UNREACHABLE();
+}
+
+wasm_global_t *
+wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt)
+{
+ wasm_global_t *global = NULL;
+ uint8 val_type_rt = 0;
+ bool is_mutable = 0;
+ bool init = false;
+
+ bh_assert(singleton_engine);
+
+ if (!inst_comm_rt) {
+ return NULL;
+ }
+
+ global = malloc_internal(sizeof(wasm_global_t));
+ if (!global) {
+ goto failed;
+ }
+
+ global->store = store;
+ global->kind = WASM_EXTERN_GLOBAL;
+
+#if WASM_ENABLE_INTERP != 0
+ if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ WASMGlobalInstance *global_interp =
+ ((WASMModuleInstance *)inst_comm_rt)->e->globals + global_idx_rt;
+ val_type_rt = global_interp->type;
+ is_mutable = global_interp->is_mutable;
+ init = true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+
+ init = true;
+
+ if (global_idx_rt < module_aot->import_global_count) {
+ AOTImportGlobal *global_import_aot =
+ module_aot->import_globals + global_idx_rt;
+ val_type_rt = global_import_aot->type;
+ is_mutable = global_import_aot->is_mutable;
+ }
+ else {
+ AOTGlobal *global_aot =
+ module_aot->globals
+ + (global_idx_rt - module_aot->import_global_count);
+ val_type_rt = global_aot->type;
+ is_mutable = global_aot->is_mutable;
+ }
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ if (!init) {
+ goto failed;
+ }
+
+ global->type = wasm_globaltype_new_internal(val_type_rt, is_mutable);
+ if (!global->type) {
+ goto failed;
+ }
+
+ global->init = malloc_internal(sizeof(wasm_val_t));
+ if (!global->init) {
+ goto failed;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ interp_global_get((WASMModuleInstance *)inst_comm_rt, global_idx_rt,
+ global->init);
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+ aot_global_get((AOTModuleInstance *)inst_comm_rt, global_idx_rt,
+ global->init);
+ }
+#endif
+
+ global->inst_comm_rt = inst_comm_rt;
+ global->global_idx_rt = global_idx_rt;
+
+ return global;
+
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ wasm_global_delete(global);
+ return NULL;
+}
+
+wasm_globaltype_t *
+wasm_global_type(const wasm_global_t *global)
+{
+ if (!global) {
+ return NULL;
+ }
+ return wasm_globaltype_copy(global->type);
+}
+
+static wasm_table_t *
+wasm_table_new_basic(wasm_store_t *store, const wasm_tabletype_t *type)
+{
+ wasm_table_t *table = NULL;
+
+ if (!(table = malloc_internal(sizeof(wasm_table_t)))) {
+ goto failed;
+ }
+
+ table->store = store;
+ table->kind = WASM_EXTERN_TABLE;
+
+ if (!(table->type = wasm_tabletype_copy(type))) {
+ goto failed;
+ }
+
+ RETURN_OBJ(table, wasm_table_delete);
+}
+
+wasm_table_t *
+wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt)
+{
+ wasm_table_t *table = NULL;
+ uint8 val_type_rt = 0;
+ uint32 init_size = 0, max_size = 0;
+
+ bh_assert(singleton_engine);
+
+ if (!inst_comm_rt) {
+ return NULL;
+ }
+
+ if (!(table = malloc_internal(sizeof(wasm_table_t)))) {
+ goto failed;
+ }
+
+ table->store = store;
+ table->kind = WASM_EXTERN_TABLE;
+
+ if (!wasm_runtime_get_table_inst_elem_type(
+ inst_comm_rt, table_idx_rt, &val_type_rt, &init_size, &max_size)) {
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ goto failed;
+ }
+
+ if (!(table->type =
+ wasm_tabletype_new_internal(val_type_rt, init_size, max_size))) {
+ goto failed;
+ }
+
+ table->inst_comm_rt = inst_comm_rt;
+ table->table_idx_rt = table_idx_rt;
+
+ RETURN_OBJ(table, wasm_table_delete);
+}
+
+/* will not actually apply this new table into the runtime */
+wasm_table_t *
+wasm_table_new(wasm_store_t *store, const wasm_tabletype_t *table_type,
+ wasm_ref_t *init)
+{
+ wasm_table_t *table;
+ (void)init;
+
+ bh_assert(singleton_engine);
+
+ if ((table = wasm_table_new_basic(store, table_type))) {
+ table->store = store;
+ }
+
+ return table;
+}
+
+wasm_table_t *
+wasm_table_copy(const wasm_table_t *src)
+{
+ wasm_table_t *table;
+
+ if (!(table = wasm_table_new_basic(src->store, src->type))) {
+ return NULL;
+ }
+
+ table->table_idx_rt = src->table_idx_rt;
+ table->inst_comm_rt = src->inst_comm_rt;
+ return table;
+}
+
+void
+wasm_table_delete(wasm_table_t *table)
+{
+ if (!table) {
+ return;
+ }
+
+ if (table->type) {
+ wasm_tabletype_delete(table->type);
+ table->type = NULL;
+ }
+
+ DELETE_HOST_INFO(table)
+
+ wasm_runtime_free(table);
+}
+
+wasm_tabletype_t *
+wasm_table_type(const wasm_table_t *table)
+{
+ if (!table) {
+ return NULL;
+ }
+ return wasm_tabletype_copy(table->type);
+}
+
+own wasm_ref_t *
+wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
+{
+ uint32 ref_idx = NULL_REF;
+
+ if (!table || !table->inst_comm_rt) {
+ return NULL;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ WASMTableInstance *table_interp =
+ ((WASMModuleInstance *)table->inst_comm_rt)
+ ->tables[table->table_idx_rt];
+ if (index >= table_interp->cur_size) {
+ return NULL;
+ }
+ ref_idx = table_interp->elems[index];
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
+ AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt];
+ if (index >= table_aot->cur_size) {
+ return NULL;
+ }
+ ref_idx = table_aot->elems[index];
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * also leads to below branch
+ */
+ if (ref_idx == NULL_REF) {
+ return NULL;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (table->type->val_type->kind == WASM_ANYREF) {
+ void *externref_obj;
+ if (!wasm_externref_ref2obj(ref_idx, &externref_obj)) {
+ return NULL;
+ }
+
+ return externref_obj;
+ }
+ else
+#endif
+ {
+ return wasm_ref_new_internal(table->store, WASM_REF_func, ref_idx,
+ table->inst_comm_rt);
+ }
+}
+
+bool
+wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
+ own wasm_ref_t *ref)
+{
+ uint32 *p_ref_idx = NULL;
+ uint32 function_count = 0;
+
+ if (!table || !table->inst_comm_rt) {
+ return false;
+ }
+
+ if (ref
+#if WASM_ENABLE_REF_TYPES != 0
+ && !(WASM_REF_foreign == ref->kind
+ && WASM_ANYREF == table->type->val_type->kind)
+#endif
+ && !(WASM_REF_func == ref->kind
+ && WASM_FUNCREF == table->type->val_type->kind)) {
+ return false;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ WASMTableInstance *table_interp =
+ ((WASMModuleInstance *)table->inst_comm_rt)
+ ->tables[table->table_idx_rt];
+
+ if (index >= table_interp->cur_size) {
+ return false;
+ }
+
+ p_ref_idx = table_interp->elems + index;
+ function_count =
+ ((WASMModuleInstance *)table->inst_comm_rt)->e->function_count;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+ AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt];
+
+ if (index >= table_aot->cur_size) {
+ return false;
+ }
+
+ p_ref_idx = table_aot->elems + index;
+ function_count = module_aot->func_count;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ if (!p_ref_idx) {
+ return false;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (table->type->val_type->kind == WASM_ANYREF) {
+ return wasm_externref_obj2ref(table->inst_comm_rt, ref, p_ref_idx);
+ }
+ else
+#endif
+ {
+ if (ref) {
+ if (NULL_REF != ref->ref_idx_rt) {
+ if (ref->ref_idx_rt >= function_count) {
+ return false;
+ }
+ }
+ *p_ref_idx = ref->ref_idx_rt;
+ wasm_ref_delete(ref);
+ }
+ else {
+ *p_ref_idx = NULL_REF;
+ }
+ }
+
+ return true;
+}
+
+wasm_table_size_t
+wasm_table_size(const wasm_table_t *table)
+{
+ if (!table || !table->inst_comm_rt) {
+ return 0;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ WASMTableInstance *table_interp =
+ ((WASMModuleInstance *)table->inst_comm_rt)
+ ->tables[table->table_idx_rt];
+ return table_interp->cur_size;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+
+ if (table->table_idx_rt < module_aot->import_table_count) {
+ AOTImportTable *table_aot =
+ module_aot->import_tables + table->table_idx_rt;
+ return table_aot->table_init_size;
+ }
+ else {
+ AOTTable *table_aot =
+ module_aot->tables
+ + (table->table_idx_rt - module_aot->import_table_count);
+ return table_aot->table_init_size;
+ }
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ return 0;
+}
+
+bool
+wasm_table_grow(wasm_table_t *table, wasm_table_size_t delta,
+ own wasm_ref_t *init)
+{
+ (void)table;
+ (void)delta;
+ (void)init;
+ LOG_WARNING("Calling wasm_table_grow() by host is not supported."
+ "Only allow growing a table via the opcode table.grow");
+ return false;
+}
+
+static wasm_memory_t *
+wasm_memory_new_basic(wasm_store_t *store, const wasm_memorytype_t *type)
+{
+ wasm_memory_t *memory = NULL;
+
+ if (!type) {
+ goto failed;
+ }
+
+ if (!(memory = malloc_internal(sizeof(wasm_memory_t)))) {
+ goto failed;
+ }
+
+ memory->store = store;
+ memory->kind = WASM_EXTERN_MEMORY;
+ memory->type = wasm_memorytype_copy(type);
+
+ RETURN_OBJ(memory, wasm_memory_delete)
+}
+
+wasm_memory_t *
+wasm_memory_new(wasm_store_t *store, const wasm_memorytype_t *type)
+{
+ bh_assert(singleton_engine);
+ return wasm_memory_new_basic(store, type);
+}
+
+wasm_memory_t *
+wasm_memory_copy(const wasm_memory_t *src)
+{
+ wasm_memory_t *dst = NULL;
+
+ if (!src) {
+ return NULL;
+ }
+
+ if (!(dst = wasm_memory_new_basic(src->store, src->type))) {
+ goto failed;
+ }
+
+ dst->memory_idx_rt = src->memory_idx_rt;
+ dst->inst_comm_rt = src->inst_comm_rt;
+
+ RETURN_OBJ(dst, wasm_memory_delete)
+}
+
+wasm_memory_t *
+wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt)
+{
+ wasm_memory_t *memory = NULL;
+ uint32 min_pages = 0, max_pages = 0;
+ bool init_flag = false;
+
+ bh_assert(singleton_engine);
+
+ if (!inst_comm_rt) {
+ return NULL;
+ }
+
+ if (!(memory = malloc_internal(sizeof(wasm_memory_t)))) {
+ goto failed;
+ }
+
+ memory->store = store;
+ memory->kind = WASM_EXTERN_MEMORY;
+
+#if WASM_ENABLE_INTERP != 0
+ if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ WASMMemoryInstance *memory_interp =
+ ((WASMModuleInstance *)inst_comm_rt)->memories[memory_idx_rt];
+ min_pages = memory_interp->cur_page_count;
+ max_pages = memory_interp->max_page_count;
+ init_flag = true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+ AOTModule *module_aot = (AOTModule *)inst_aot->module;
+
+ if (memory_idx_rt < module_aot->import_memory_count) {
+ min_pages = module_aot->import_memories->mem_init_page_count;
+ max_pages = module_aot->import_memories->mem_max_page_count;
+ }
+ else {
+ min_pages = module_aot->memories->mem_init_page_count;
+ max_pages = module_aot->memories->mem_max_page_count;
+ }
+ init_flag = true;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ if (!init_flag) {
+ goto failed;
+ }
+
+ if (!(memory->type = wasm_memorytype_new_internal(min_pages, max_pages))) {
+ goto failed;
+ }
+
+ memory->inst_comm_rt = inst_comm_rt;
+ memory->memory_idx_rt = memory_idx_rt;
+
+ RETURN_OBJ(memory, wasm_memory_delete);
+}
+
+void
+wasm_memory_delete(wasm_memory_t *memory)
+{
+ if (!memory) {
+ return;
+ }
+
+ if (memory->type) {
+ wasm_memorytype_delete(memory->type);
+ memory->type = NULL;
+ }
+
+ DELETE_HOST_INFO(memory)
+
+ wasm_runtime_free(memory);
+}
+
+wasm_memorytype_t *
+wasm_memory_type(const wasm_memory_t *memory)
+{
+ if (!memory) {
+ return NULL;
+ }
+
+ return wasm_memorytype_copy(memory->type);
+}
+
+byte_t *
+wasm_memory_data(wasm_memory_t *memory)
+{
+ WASMModuleInstanceCommon *module_inst_comm;
+
+ if (!memory || !memory->inst_comm_rt) {
+ return NULL;
+ }
+
+ module_inst_comm = memory->inst_comm_rt;
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst =
+ module_inst->memories[memory->memory_idx_rt];
+ return (byte_t *)memory_inst->memory_data;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_comm->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
+ AOTMemoryInstance *memory_inst =
+ ((AOTMemoryInstance **)
+ module_inst->memories)[memory->memory_idx_rt];
+ return (byte_t *)memory_inst->memory_data;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ return NULL;
+}
+
+size_t
+wasm_memory_data_size(const wasm_memory_t *memory)
+{
+ WASMModuleInstanceCommon *module_inst_comm;
+
+ if (!memory || !memory->inst_comm_rt) {
+ return 0;
+ }
+
+ module_inst_comm = memory->inst_comm_rt;
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst =
+ module_inst->memories[memory->memory_idx_rt];
+ return (size_t)memory_inst->cur_page_count
+ * memory_inst->num_bytes_per_page;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_comm->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
+ AOTMemoryInstance *memory_inst =
+ ((AOTMemoryInstance **)
+ module_inst->memories)[memory->memory_idx_rt];
+ return (size_t)memory_inst->cur_page_count
+ * memory_inst->num_bytes_per_page;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ return 0;
+}
+
+wasm_memory_pages_t
+wasm_memory_size(const wasm_memory_t *memory)
+{
+ WASMModuleInstanceCommon *module_inst_comm;
+
+ if (!memory || !memory->inst_comm_rt) {
+ return 0;
+ }
+
+ module_inst_comm = memory->inst_comm_rt;
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst =
+ module_inst->memories[memory->memory_idx_rt];
+ return memory_inst->cur_page_count;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_comm->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
+ AOTMemoryInstance *memory_inst =
+ ((AOTMemoryInstance **)
+ module_inst->memories)[memory->memory_idx_rt];
+ return memory_inst->cur_page_count;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ return 0;
+}
+
+bool
+wasm_memory_grow(wasm_memory_t *memory, wasm_memory_pages_t delta)
+{
+ (void)memory;
+ (void)delta;
+ LOG_WARNING("Calling wasm_memory_grow() by host is not supported."
+ "Only allow growing a memory via the opcode memory.grow");
+ return false;
+}
+
+#if WASM_ENABLE_INTERP != 0
+static bool
+interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
+ uint16 func_idx_rt, wasm_func_t *import)
+{
+ WASMImport *imported_func_interp = NULL;
+
+ bh_assert(inst && module_interp && import);
+ bh_assert(func_idx_rt < module_interp->import_function_count);
+ bh_assert(WASM_EXTERN_FUNC == import->kind);
+
+ imported_func_interp = module_interp->import_functions + func_idx_rt;
+ bh_assert(imported_func_interp);
+ bh_assert(imported_func_interp->kind == IMPORT_KIND_FUNC);
+
+ /* it is a placeholder and let's skip it*/
+ if (!import->type)
+ return true;
+
+ /* type comparison */
+ if (!wasm_functype_same_internal(
+ import->type, imported_func_interp->u.function.func_type))
+ return false;
+
+ imported_func_interp->u.function.call_conv_wasm_c_api = true;
+ /* only set func_ptr_linked to avoid unlink warning during instantiation,
+ func_ptr_linked, with_env and env will be stored in module instance's
+ c_api_func_imports later and used when calling import function */
+ if (import->with_env)
+ imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
+ else
+ imported_func_interp->u.function.func_ptr_linked = import->u.cb;
+ bh_assert(imported_func_interp->u.function.func_ptr_linked);
+
+ import->func_idx_rt = func_idx_rt;
+
+ (void)inst;
+ return true;
+}
+
+static bool
+interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
+ wasm_global_t *import)
+{
+ WASMImport *imported_global_interp = NULL;
+
+ bh_assert(module_interp && import);
+ bh_assert(global_idx_rt < module_interp->import_global_count);
+ bh_assert(WASM_EXTERN_GLOBAL == import->kind);
+
+ imported_global_interp = module_interp->import_globals + global_idx_rt;
+ bh_assert(imported_global_interp);
+ bh_assert(imported_global_interp->kind == IMPORT_KIND_GLOBAL);
+
+ /* it is a placeholder and let's skip it*/
+ if (!import->type)
+ return true;
+
+ /* type comparison */
+ if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
+ imported_global_interp->u.global.type))
+ return false;
+
+ /* set init value */
+ bh_assert(import->init);
+ switch (wasm_valtype_kind(import->type->val_type)) {
+ case WASM_I32:
+ imported_global_interp->u.global.global_data_linked.i32 =
+ import->init->of.i32;
+ break;
+ case WASM_I64:
+ imported_global_interp->u.global.global_data_linked.i64 =
+ import->init->of.i64;
+ break;
+ case WASM_F32:
+ imported_global_interp->u.global.global_data_linked.f32 =
+ import->init->of.f32;
+ break;
+ case WASM_F64:
+ imported_global_interp->u.global.global_data_linked.f64 =
+ import->init->of.f64;
+ break;
+ default:
+ return false;
+ }
+
+ import->global_idx_rt = global_idx_rt;
+ imported_global_interp->u.global.is_linked = true;
+ return true;
+}
+
+static bool
+interp_process_export(wasm_store_t *store,
+ const WASMModuleInstance *inst_interp,
+ wasm_extern_vec_t *externals)
+{
+ WASMExport *exports = NULL;
+ WASMExport *export = NULL;
+ wasm_extern_t *external = NULL;
+ uint32 export_cnt = 0;
+ uint32 i = 0;
+
+ bh_assert(store && inst_interp && inst_interp->module && externals);
+
+ exports = inst_interp->module->exports;
+ export_cnt = inst_interp->module->export_count;
+
+ for (i = 0; i < export_cnt; ++i) {
+ export = exports + i;
+
+ switch (export->kind) {
+ case EXPORT_KIND_FUNC:
+ {
+ wasm_func_t *func;
+ if (!(func = wasm_func_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_interp))) {
+ goto failed;
+ }
+
+ external = wasm_func_as_extern(func);
+ break;
+ }
+ case EXPORT_KIND_GLOBAL:
+ {
+ wasm_global_t *global;
+ if (!(global = wasm_global_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_interp))) {
+ goto failed;
+ }
+
+ external = wasm_global_as_extern(global);
+ break;
+ }
+ case EXPORT_KIND_TABLE:
+ {
+ wasm_table_t *table;
+ if (!(table = wasm_table_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_interp))) {
+ goto failed;
+ }
+
+ external = wasm_table_as_extern(table);
+ break;
+ }
+ case EXPORT_KIND_MEMORY:
+ {
+ wasm_memory_t *memory;
+ if (!(memory = wasm_memory_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_interp))) {
+ goto failed;
+ }
+
+ external = wasm_memory_as_extern(memory);
+ break;
+ }
+ default:
+ LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+ export->kind);
+ goto failed;
+ }
+
+ if (!bh_vector_append((Vector *)externals, &external)) {
+ goto failed;
+ }
+ }
+
+ return true;
+
+failed:
+ wasm_extern_delete(external);
+ return false;
+}
+#endif /* WASM_ENABLE_INTERP */
+
+#if WASM_ENABLE_AOT != 0
+static bool
+aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
+ uint32 import_func_idx_rt, wasm_func_t *import)
+{
+ AOTImportFunc *import_aot_func = NULL;
+
+ bh_assert(inst && module_aot && import);
+
+ import_aot_func = module_aot->import_funcs + import_func_idx_rt;
+ bh_assert(import_aot_func);
+
+ /* it is a placeholder and let's skip it*/
+ if (!import->type)
+ return true;
+
+ /* type comparison */
+ if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
+ return false;
+
+ import_aot_func->call_conv_wasm_c_api = true;
+ /* only set func_ptr_linked to avoid unlink warning during instantiation,
+ func_ptr_linked, with_env and env will be stored in module instance's
+ c_api_func_imports later and used when calling import function */
+ if (import->with_env)
+ import_aot_func->func_ptr_linked = import->u.cb_env.cb;
+ else
+ import_aot_func->func_ptr_linked = import->u.cb;
+ bh_assert(import_aot_func->func_ptr_linked);
+
+ import->func_idx_rt = import_func_idx_rt;
+
+ return true;
+}
+
+static bool
+aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
+ wasm_global_t *import)
+{
+ AOTImportGlobal *import_aot_global = NULL;
+ const wasm_valtype_t *val_type = NULL;
+
+ bh_assert(module_aot && import);
+
+ import_aot_global = module_aot->import_globals + global_idx_rt;
+ bh_assert(import_aot_global);
+
+ /* it is a placeholder and let's skip it*/
+ if (!import->type)
+ return true;
+
+ val_type = wasm_globaltype_content(import->type);
+ bh_assert(val_type);
+
+ if (!cmp_val_kind_with_val_type(wasm_valtype_kind(val_type),
+ import_aot_global->type))
+ return false;
+
+ bh_assert(import->init);
+ switch (wasm_valtype_kind(val_type)) {
+ case WASM_I32:
+ import_aot_global->global_data_linked.i32 = import->init->of.i32;
+ break;
+ case WASM_I64:
+ import_aot_global->global_data_linked.i64 = import->init->of.i64;
+ break;
+ case WASM_F32:
+ import_aot_global->global_data_linked.f32 = import->init->of.f32;
+ break;
+ case WASM_F64:
+ import_aot_global->global_data_linked.f64 = import->init->of.f64;
+ break;
+ default:
+ goto failed;
+ }
+
+ import->global_idx_rt = global_idx_rt;
+ import_aot_global->is_linked = true;
+ return true;
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ return false;
+}
+
+static bool
+aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
+ wasm_extern_vec_t *externals)
+{
+ uint32 i;
+ wasm_extern_t *external = NULL;
+ AOTModule *module_aot = NULL;
+
+ bh_assert(store && inst_aot && externals);
+
+ module_aot = (AOTModule *)inst_aot->module;
+ bh_assert(module_aot);
+
+ for (i = 0; i < module_aot->export_count; ++i) {
+ AOTExport *export = module_aot->exports + i;
+
+ switch (export->kind) {
+ case EXPORT_KIND_FUNC:
+ {
+ wasm_func_t *func = NULL;
+ if (!(func = wasm_func_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_aot))) {
+ goto failed;
+ }
+
+ external = wasm_func_as_extern(func);
+ break;
+ }
+ case EXPORT_KIND_GLOBAL:
+ {
+ wasm_global_t *global = NULL;
+ if (!(global = wasm_global_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_aot))) {
+ goto failed;
+ }
+
+ external = wasm_global_as_extern(global);
+ break;
+ }
+ case EXPORT_KIND_TABLE:
+ {
+ wasm_table_t *table;
+ if (!(table = wasm_table_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_aot))) {
+ goto failed;
+ }
+
+ external = wasm_table_as_extern(table);
+ break;
+ }
+ case EXPORT_KIND_MEMORY:
+ {
+ wasm_memory_t *memory;
+ if (!(memory = wasm_memory_new_internal(
+ store, export->index,
+ (WASMModuleInstanceCommon *)inst_aot))) {
+ goto failed;
+ }
+
+ external = wasm_memory_as_extern(memory);
+ break;
+ }
+ default:
+ LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+ export->kind);
+ goto failed;
+ }
+
+ if (!(external->name = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+ goto failed;
+ }
+
+ wasm_name_new_from_string_nt(external->name, export->name);
+ if (strlen(export->name) && !external->name->data) {
+ goto failed;
+ }
+
+ if (!bh_vector_append((Vector *)externals, &external)) {
+ goto failed;
+ }
+ }
+
+ return true;
+
+failed:
+ wasm_extern_delete(external);
+ return false;
+}
+#endif /* WASM_ENABLE_AOT */
+
+static bool
+do_link(const wasm_instance_t *inst, const wasm_module_t *module,
+ const wasm_extern_vec_t *imports)
+{
+ uint32 i, import_func_i, import_global_i;
+
+ bh_assert(inst && module);
+
+ /* we have run a module_type check before. */
+
+ for (i = 0, import_func_i = 0, import_global_i = 0; i < imports->num_elems;
+ i++) {
+ wasm_extern_t *import = imports->data[i];
+
+ if (!import) {
+ LOG_ERROR("imports[%d] is NULL and it is fatal\n", i);
+ goto failed;
+ }
+
+ switch (wasm_extern_kind(import)) {
+ case WASM_EXTERN_FUNC:
+ {
+ bool ret = false;
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ ret = interp_link_func(inst, MODULE_INTERP(module),
+ import_func_i,
+ wasm_extern_as_func(import));
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ ret = aot_link_func(inst, MODULE_AOT(module), import_func_i,
+ wasm_extern_as_func(import));
+ }
+#endif
+ if (!ret) {
+ LOG_WARNING("link function #%d failed", import_func_i);
+ goto failed;
+ }
+
+ import_func_i++;
+ break;
+ }
+ case WASM_EXTERN_GLOBAL:
+ {
+ bool ret = false;
+#if WASM_ENABLE_INTERP != 0
+ if ((*module)->module_type == Wasm_Module_Bytecode) {
+ ret = interp_link_global(MODULE_INTERP(module),
+ import_global_i,
+ wasm_extern_as_global(import));
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if ((*module)->module_type == Wasm_Module_AoT) {
+ ret = aot_link_global(MODULE_AOT(module), import_global_i,
+ wasm_extern_as_global(import));
+ }
+#endif
+ if (!ret) {
+ LOG_WARNING("link global #%d failed", import_global_i);
+ goto failed;
+ }
+
+ import_global_i++;
+ break;
+ }
+ case WASM_EXTERN_MEMORY:
+ case WASM_EXTERN_TABLE:
+ {
+ LOG_WARNING("doesn't support import memories and tables for "
+ "now, ignore them");
+ break;
+ }
+ default:
+ {
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+
+ return true;
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ return false;
+}
+
+wasm_instance_t *
+wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
+ const wasm_extern_vec_t *imports, own wasm_trap_t **trap)
+{
+ return wasm_instance_new_with_args(store, module, imports, trap,
+ KILOBYTE(32), KILOBYTE(32));
+}
+
+wasm_instance_t *
+wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
+ const wasm_extern_vec_t *imports,
+ own wasm_trap_t **trap, const uint32 stack_size,
+ const uint32 heap_size)
+{
+ char sub_error_buf[128] = { 0 };
+ char error_buf[256] = { 0 };
+ wasm_instance_t *instance = NULL;
+ CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
+ uint32 i = 0, import_func_count = 0;
+ uint64 total_size;
+ bool build_exported = false;
+
+ bh_assert(singleton_engine);
+
+ if (!module)
+ return NULL;
+
+ /*
+ * will do the check at the end of wasm_runtime_instantiate
+ */
+
+ WASM_C_DUMP_PROC_MEM();
+
+ instance = malloc_internal(sizeof(wasm_instance_t));
+ if (!instance) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Failed to malloc instance");
+ goto failed;
+ }
+
+ /* executes the instantiate-time linking if provided */
+ if (imports) {
+ if (!do_link(instance, module, imports)) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Failed to validate imports");
+ goto failed;
+ }
+ }
+ /*
+ * will do the linking result check at the end of wasm_runtime_instantiate
+ */
+
+ instance->inst_comm_rt = wasm_runtime_instantiate(
+ *module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf));
+ if (!instance->inst_comm_rt) {
+ goto failed;
+ }
+
+ if (!wasm_runtime_create_exec_env_singleton(instance->inst_comm_rt)) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Failed to create exec env singleton");
+ goto failed;
+ }
+
+ /* create the c-api func import list */
+#if WASM_ENABLE_INTERP != 0
+ if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstanceExtra *e =
+ ((WASMModuleInstance *)instance->inst_comm_rt)->e;
+ p_func_imports = &(e->c_api_func_imports);
+ import_func_count = MODULE_INTERP(module)->import_function_count;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ AOTModuleInstanceExtra *e =
+ (AOTModuleInstanceExtra *)((AOTModuleInstance *)
+ instance->inst_comm_rt)
+ ->e;
+ p_func_imports = &(e->c_api_func_imports);
+ import_func_count = MODULE_AOT(module)->import_func_count;
+ }
+#endif
+ bh_assert(p_func_imports);
+
+ total_size = (uint64)sizeof(CApiFuncImport) * import_func_count;
+ if (total_size > 0
+ && !(*p_func_imports = func_import = malloc_internal(total_size))) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Failed to create wasm-c-api func imports");
+ goto failed;
+ }
+
+ /* fill in module_inst->e->c_api_func_imports */
+ for (i = 0; imports && i < imports->num_elems; i++) {
+ wasm_func_t *func_host = NULL;
+ wasm_extern_t *in = imports->data[i];
+ bh_assert(in);
+
+ if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
+ continue;
+
+ func_host = wasm_extern_as_func(in);
+ /* it is a placeholder and let's skip it*/
+ if (!func_host->type) {
+ func_import++;
+ continue;
+ }
+
+ func_import->with_env_arg = func_host->with_env;
+ if (func_host->with_env) {
+ func_import->func_ptr_linked = func_host->u.cb_env.cb;
+ func_import->env_arg = func_host->u.cb_env.env;
+ }
+ else {
+ func_import->func_ptr_linked = func_host->u.cb;
+ func_import->env_arg = NULL;
+ }
+ bh_assert(func_import->func_ptr_linked);
+
+ func_import++;
+ }
+
+ /* fill with inst */
+ for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
+ wasm_extern_t *import = imports->data[i];
+ bh_assert(import);
+
+ switch (import->kind) {
+ case WASM_EXTERN_FUNC:
+ wasm_extern_as_func(import)->inst_comm_rt =
+ instance->inst_comm_rt;
+ break;
+ case WASM_EXTERN_GLOBAL:
+ wasm_extern_as_global(import)->inst_comm_rt =
+ instance->inst_comm_rt;
+ break;
+ case WASM_EXTERN_MEMORY:
+ wasm_extern_as_memory(import)->inst_comm_rt =
+ instance->inst_comm_rt;
+ break;
+ case WASM_EXTERN_TABLE:
+ wasm_extern_as_table(import)->inst_comm_rt =
+ instance->inst_comm_rt;
+ break;
+ default:
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Unknown import kind");
+ goto failed;
+ }
+ }
+
+ /* build the exports list */
+#if WASM_ENABLE_INTERP != 0
+ if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+ uint32 export_cnt = ((WASMModuleInstance *)instance->inst_comm_rt)
+ ->module->export_count;
+
+ INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized,
+ export_cnt);
+
+ if (!interp_process_export(store,
+ (WASMModuleInstance *)instance->inst_comm_rt,
+ instance->exports)) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Interpreter failed to process exports");
+ goto failed;
+ }
+
+ build_exported = true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
+ uint32 export_cnt =
+ ((AOTModuleInstance *)instance->inst_comm_rt)->export_func_count
+ + ((AOTModuleInstance *)instance->inst_comm_rt)->export_global_count
+ + ((AOTModuleInstance *)instance->inst_comm_rt)->export_table_count
+ + ((AOTModuleInstance *)instance->inst_comm_rt)
+ ->export_memory_count;
+
+ INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized,
+ export_cnt);
+
+ if (!aot_process_export(store,
+ (AOTModuleInstance *)instance->inst_comm_rt,
+ instance->exports)) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "AOT failed to process exports");
+ goto failed;
+ }
+
+ build_exported = true;
+ }
+#endif
+
+ /*
+ * a wrong combination of module filetype and compilation flags
+ * leads to below branch
+ */
+ if (!build_exported) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Incorrect filetype and compilation flags");
+ goto failed;
+ }
+
+ /* add it to a watching list in store */
+ if (!bh_vector_append((Vector *)store->instances, &instance)) {
+ snprintf(sub_error_buf, sizeof(sub_error_buf),
+ "Failed to add to store instances");
+ goto failed;
+ }
+
+ WASM_C_DUMP_PROC_MEM();
+
+ return instance;
+
+failed:
+ snprintf(error_buf, sizeof(error_buf), "%s failed: %s", __FUNCTION__,
+ sub_error_buf);
+ if (trap != NULL) {
+ wasm_message_t message = { 0 };
+ wasm_name_new_from_string_nt(&message, error_buf);
+ *trap = wasm_trap_new(store, &message);
+ wasm_byte_vec_delete(&message);
+ }
+ LOG_DEBUG(error_buf);
+ wasm_instance_delete_internal(instance);
+ return NULL;
+}
+
+static void
+wasm_instance_delete_internal(wasm_instance_t *instance)
+{
+ if (!instance) {
+ return;
+ }
+
+ DEINIT_VEC(instance->exports, wasm_extern_vec_delete);
+
+ if (instance->inst_comm_rt) {
+ wasm_runtime_deinstantiate(instance->inst_comm_rt);
+ instance->inst_comm_rt = NULL;
+ }
+ wasm_runtime_free(instance);
+}
+
+void
+wasm_instance_delete(wasm_instance_t *inst)
+{
+ DELETE_HOST_INFO(inst)
+ /* will release instance when releasing the store */
+}
+
+void
+wasm_instance_exports(const wasm_instance_t *instance,
+ own wasm_extern_vec_t *out)
+{
+ if (!instance || !out) {
+ return;
+ }
+ wasm_extern_vec_copy(out, instance->exports);
+}
+
+wasm_extern_t *
+wasm_extern_copy(const wasm_extern_t *src)
+{
+ wasm_extern_t *dst = NULL;
+
+ if (!src) {
+ return NULL;
+ }
+
+ switch (wasm_extern_kind(src)) {
+ case WASM_EXTERN_FUNC:
+ dst = wasm_func_as_extern(
+ wasm_func_copy(wasm_extern_as_func_const(src)));
+ break;
+ case WASM_EXTERN_GLOBAL:
+ dst = wasm_global_as_extern(
+ wasm_global_copy(wasm_extern_as_global_const(src)));
+ break;
+ case WASM_EXTERN_MEMORY:
+ dst = wasm_memory_as_extern(
+ wasm_memory_copy(wasm_extern_as_memory_const(src)));
+ break;
+ case WASM_EXTERN_TABLE:
+ dst = wasm_table_as_extern(
+ wasm_table_copy(wasm_extern_as_table_const(src)));
+ break;
+ default:
+ LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+ src->kind);
+ break;
+ }
+
+ if (!dst) {
+ goto failed;
+ }
+
+ return dst;
+
+failed:
+ LOG_DEBUG("%s failed", __FUNCTION__);
+ wasm_extern_delete(dst);
+ return NULL;
+}
+
+void
+wasm_extern_delete(wasm_extern_t *external)
+{
+ if (!external) {
+ return;
+ }
+
+ if (external->name) {
+ wasm_byte_vec_delete(external->name);
+ wasm_runtime_free(external->name);
+ external->name = NULL;
+ }
+
+ switch (wasm_extern_kind(external)) {
+ case WASM_EXTERN_FUNC:
+ wasm_func_delete(wasm_extern_as_func(external));
+ break;
+ case WASM_EXTERN_GLOBAL:
+ wasm_global_delete(wasm_extern_as_global(external));
+ break;
+ case WASM_EXTERN_MEMORY:
+ wasm_memory_delete(wasm_extern_as_memory(external));
+ break;
+ case WASM_EXTERN_TABLE:
+ wasm_table_delete(wasm_extern_as_table(external));
+ break;
+ default:
+ LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+ external->kind);
+ break;
+ }
+}
+
+wasm_externkind_t
+wasm_extern_kind(const wasm_extern_t *external)
+{
+ if (!external) {
+ return WASM_ANYREF;
+ }
+
+ return external->kind;
+}
+
+own wasm_externtype_t *
+wasm_extern_type(const wasm_extern_t *external)
+{
+ if (!external) {
+ return NULL;
+ }
+
+ switch (wasm_extern_kind(external)) {
+ case WASM_EXTERN_FUNC:
+ return wasm_functype_as_externtype(
+ wasm_func_type(wasm_extern_as_func_const(external)));
+ case WASM_EXTERN_GLOBAL:
+ return wasm_globaltype_as_externtype(
+ wasm_global_type(wasm_extern_as_global_const(external)));
+ case WASM_EXTERN_MEMORY:
+ return wasm_memorytype_as_externtype(
+ wasm_memory_type(wasm_extern_as_memory_const(external)));
+ case WASM_EXTERN_TABLE:
+ return wasm_tabletype_as_externtype(
+ wasm_table_type(wasm_extern_as_table_const(external)));
+ default:
+ LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+ external->kind);
+ break;
+ }
+ return NULL;
+}
+
+#define BASIC_FOUR_LIST(V) \
+ V(func) \
+ V(global) \
+ V(memory) \
+ V(table)
+
+#define WASM_EXTERN_AS_OTHER(name) \
+ wasm_##name##_t *wasm_extern_as_##name(wasm_extern_t *external) \
+ { \
+ return (wasm_##name##_t *)external; \
+ }
+
+BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER)
+#undef WASM_EXTERN_AS_OTHER
+
+#define WASM_OTHER_AS_EXTERN(name) \
+ wasm_extern_t *wasm_##name##_as_extern(wasm_##name##_t *other) \
+ { \
+ return (wasm_extern_t *)other; \
+ }
+
+BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN)
+#undef WASM_OTHER_AS_EXTERN
+
+#define WASM_EXTERN_AS_OTHER_CONST(name) \
+ const wasm_##name##_t *wasm_extern_as_##name##_const( \
+ const wasm_extern_t *external) \
+ { \
+ return (const wasm_##name##_t *)external; \
+ }
+
+BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST)
+#undef WASM_EXTERN_AS_OTHER_CONST
+
+#define WASM_OTHER_AS_EXTERN_CONST(name) \
+ const wasm_extern_t *wasm_##name##_as_extern_const( \
+ const wasm_##name##_t *other) \
+ { \
+ return (const wasm_extern_t *)other; \
+ }
+
+BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
+#undef WASM_OTHER_AS_EXTERN_CONST
+
+wasm_extern_t *
+wasm_extern_new_empty(wasm_store_t *store, wasm_externkind_t extern_kind)
+{
+ if (extern_kind == WASM_EXTERN_FUNC)
+ return wasm_func_as_extern(wasm_func_new_empty(store));
+
+ if (extern_kind == WASM_EXTERN_GLOBAL)
+ return wasm_global_as_extern(wasm_global_new_empty(store));
+
+ LOG_ERROR("Don't support linking table and memory for now");
+ return NULL;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api_internal.h
new file mode 100644
index 000000000..6e05eea74
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_c_api_internal.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_C_API_INTERNAL_H
+#define _WASM_C_API_INTERNAL_H
+
+#include "../include/wasm_c_api.h"
+#include "wasm_runtime_common.h"
+
+#ifndef own
+#define own
+#endif
+
+/* Vectors */
+/* we will malloc resource for the vector's data field */
+/* we will release resource of data */
+/* caller needs to take care resource for the vector itself */
+#define DEFAULT_VECTOR_INIT_LENGTH (64)
+
+WASM_DECLARE_VEC(instance, *)
+WASM_DECLARE_VEC(module, *)
+WASM_DECLARE_VEC(store, *)
+
+/* Runtime Environment */
+struct wasm_engine_t {
+ uint32 ref_count;
+ /* list of wasm_module_ex_t */
+ Vector modules;
+ /* list of stores which are classified according to tids */
+ Vector stores_by_tid;
+};
+
+struct wasm_store_t {
+ /* maybe should remove the list */
+ wasm_module_vec_t *modules;
+ wasm_instance_vec_t *instances;
+ Vector *foreigns;
+};
+
+/* Type Representations */
+struct wasm_valtype_t {
+ wasm_valkind_t kind;
+};
+
+struct wasm_functype_t {
+ uint32 extern_kind;
+ /* gona to new and delete own */
+ wasm_valtype_vec_t *params;
+ wasm_valtype_vec_t *results;
+};
+
+struct wasm_globaltype_t {
+ uint32 extern_kind;
+ /* gona to new and delete own */
+ wasm_valtype_t *val_type;
+ wasm_mutability_t mutability;
+};
+
+struct wasm_tabletype_t {
+ uint32 extern_kind;
+ wasm_valtype_t *val_type;
+ wasm_limits_t limits;
+};
+
+struct wasm_memorytype_t {
+ uint32 extern_kind;
+ wasm_limits_t limits;
+};
+
+struct wasm_externtype_t {
+ uint32 extern_kind;
+ /* reservered space */
+ uint8 data[1];
+};
+
+struct wasm_importtype_t {
+ wasm_name_t *module_name;
+ wasm_name_t *name;
+ wasm_externtype_t *extern_type;
+};
+
+struct wasm_exporttype_t {
+ wasm_name_t *name;
+ wasm_externtype_t *extern_type;
+};
+
+/* Runtime Objects */
+enum wasm_reference_kind {
+ WASM_REF_foreign,
+ WASM_REF_func,
+ WASM_REF_global,
+ WASM_REF_memory,
+ WASM_REF_table,
+};
+
+struct wasm_host_info {
+ void *info;
+ void (*finalizer)(void *);
+};
+
+struct wasm_ref_t {
+ wasm_store_t *store;
+ enum wasm_reference_kind kind;
+ struct wasm_host_info host_info;
+ uint32 ref_idx_rt;
+ WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_trap_t {
+ wasm_byte_vec_t *message;
+ Vector *frames;
+};
+
+struct wasm_foreign_t {
+ wasm_store_t *store;
+ enum wasm_reference_kind kind;
+ struct wasm_host_info host_info;
+ int32 ref_cnt;
+ uint32 foreign_idx_rt;
+ WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_func_t {
+ wasm_store_t *store;
+ wasm_name_t *module_name;
+ wasm_name_t *name;
+ uint16 kind;
+
+ struct wasm_host_info host_info;
+ wasm_functype_t *type;
+
+ bool with_env;
+ union {
+ wasm_func_callback_t cb;
+ struct callback_ext {
+ void *env;
+ wasm_func_callback_with_env_t cb;
+ void (*finalizer)(void *);
+ } cb_env;
+ } u;
+ /*
+ * an index in both functions runtime instance lists
+ * of interpreter mode and aot mode
+ */
+ uint16 func_idx_rt;
+ WASMModuleInstanceCommon *inst_comm_rt;
+ WASMFunctionInstanceCommon *func_comm_rt;
+};
+
+struct wasm_global_t {
+ wasm_store_t *store;
+ wasm_name_t *module_name;
+ wasm_name_t *name;
+ uint16 kind;
+
+ struct wasm_host_info host_info;
+ wasm_globaltype_t *type;
+ wasm_val_t *init;
+ /*
+ * an index in both global runtime instance lists
+ * of interpreter mode and aot mode
+ */
+ uint16 global_idx_rt;
+ WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_memory_t {
+ wasm_store_t *store;
+ wasm_name_t *module_name;
+ wasm_name_t *name;
+ uint16 kind;
+
+ struct wasm_host_info host_info;
+ wasm_memorytype_t *type;
+ /*
+ * an index in both memory runtime instance lists
+ * of interpreter mode and aot mode
+ */
+ uint16 memory_idx_rt;
+ WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_table_t {
+ wasm_store_t *store;
+ wasm_name_t *module_name;
+ wasm_name_t *name;
+ uint16 kind;
+
+ struct wasm_host_info host_info;
+ wasm_tabletype_t *type;
+ /*
+ * an index in both table runtime instance lists
+ * of interpreter mode and aot mode
+ */
+ uint16 table_idx_rt;
+ WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_extern_t {
+ wasm_store_t *store;
+ wasm_name_t *module_name;
+ wasm_name_t *name;
+ wasm_externkind_t kind;
+ /* reservered space */
+ uint8 data[1];
+};
+
+struct wasm_instance_t {
+ wasm_store_t *store;
+ wasm_extern_vec_t *exports;
+ struct wasm_host_info host_info;
+ WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+wasm_ref_t *
+wasm_ref_new_internal(wasm_store_t *store, enum wasm_reference_kind kind,
+ uint32 obj_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt);
+
+wasm_foreign_t *
+wasm_foreign_new_internal(wasm_store_t *store, uint32 foreign_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt);
+
+wasm_func_t *
+wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt);
+
+wasm_global_t *
+wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt);
+
+wasm_memory_t *
+wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt);
+
+wasm_table_t *
+wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
+ WASMModuleInstanceCommon *inst_comm_rt);
+#endif /* _WASM_C_API_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.c
new file mode 100644
index 000000000..622bcd71e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_exec_env.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
+
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#include "../libraries/debug-engine/debug_engine.h"
+#endif
+#endif
+
+WASMExecEnv *
+wasm_exec_env_create_internal(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_runtime_malloc((uint32)total_size)))
+ return NULL;
+
+ memset(exec_env, 0, (uint32)total_size);
+
+#if WASM_ENABLE_AOT != 0
+ if (!(exec_env->argv_buf = wasm_runtime_malloc(sizeof(uint32) * 64))) {
+ goto fail1;
+ }
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (os_mutex_init(&exec_env->wait_lock) != 0)
+ goto fail2;
+
+ if (os_cond_init(&exec_env->wait_cond) != 0)
+ goto fail3;
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!(exec_env->current_status = wasm_cluster_create_exenv_status()))
+ goto fail4;
+#endif
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!(exec_env->exce_check_guard_page =
+ os_mmap(NULL, os_getpagesize(), MMAP_PROT_NONE, MMAP_MAP_NONE)))
+ goto fail5;
+#endif
+
+ 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;
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *i = (AOTModuleInstance *)module_inst;
+ AOTModule *m = (AOTModule *)i->module;
+ exec_env->native_symbol = m->native_symbol_list;
+ }
+#endif
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ wasm_runtime_dump_exec_env_mem_consumption(exec_env);
+#endif
+
+ return exec_env;
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+fail5:
+#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_destroy_exenv_status(exec_env->current_status);
+#endif
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#if WASM_ENABLE_DEBUG_INTERP != 0
+fail4:
+ os_cond_destroy(&exec_env->wait_cond);
+#endif
+fail3:
+ os_mutex_destroy(&exec_env->wait_lock);
+fail2:
+#endif
+#if WASM_ENABLE_AOT != 0
+ wasm_runtime_free(exec_env->argv_buf);
+fail1:
+#endif
+ wasm_runtime_free(exec_env);
+ return NULL;
+}
+
+void
+wasm_exec_env_destroy_internal(WASMExecEnv *exec_env)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_munmap(exec_env->exce_check_guard_page, os_getpagesize());
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ os_mutex_destroy(&exec_env->wait_lock);
+ os_cond_destroy(&exec_env->wait_cond);
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_destroy_exenv_status(exec_env->current_status);
+#endif
+#endif
+#if WASM_ENABLE_AOT != 0
+ wasm_runtime_free(exec_env->argv_buf);
+#endif
+ wasm_runtime_free(exec_env);
+}
+
+WASMExecEnv *
+wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
+ uint32 stack_size)
+{
+#if WASM_ENABLE_THREAD_MGR != 0
+ WASMCluster *cluster;
+#endif
+ WASMExecEnv *exec_env =
+ wasm_exec_env_create_internal(module_inst, stack_size);
+
+ if (!exec_env)
+ return NULL;
+
+#if WASM_ENABLE_INTERP != 0
+ /* Set the aux_stack_boundary and aux_stack_bottom */
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
+ exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
+ exec_env->aux_stack_boundary.boundary =
+ module->aux_stack_bottom - module->aux_stack_size;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ /* Set the aux_stack_boundary and aux_stack_bottom */
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ AOTModule *module =
+ (AOTModule *)((AOTModuleInstance *)module_inst)->module;
+ exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
+ exec_env->aux_stack_boundary.boundary =
+ module->aux_stack_bottom - module->aux_stack_size;
+ }
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Create a new cluster for this exec_env */
+ if (!(cluster = wasm_cluster_create(exec_env))) {
+ wasm_exec_env_destroy_internal(exec_env);
+ return NULL;
+ }
+#endif /* end of WASM_ENABLE_THREAD_MGR */
+
+ return exec_env;
+}
+
+void
+wasm_exec_env_destroy(WASMExecEnv *exec_env)
+{
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Wait for all sub-threads */
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ if (cluster) {
+ wasm_cluster_wait_for_all_except_self(cluster, exec_env);
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ /* Must fire exit event after other threads exits, otherwise
+ the stopped thread will be overrided by other threads */
+ wasm_cluster_thread_exited(exec_env);
+#endif
+ /* We have waited for other threads, this is the only alive thread, so
+ * we don't acquire cluster->lock because the cluster will be destroyed
+ * inside this function */
+ wasm_cluster_del_exec_env(cluster, exec_env);
+ }
+#endif /* end of WASM_ENABLE_THREAD_MGR */
+
+ wasm_exec_env_destroy_internal(exec_env);
+}
+
+WASMModuleInstanceCommon *
+wasm_exec_env_get_module_inst(WASMExecEnv *exec_env)
+{
+ return exec_env->module_inst;
+}
+
+void
+wasm_exec_env_set_module_inst(WASMExecEnv *exec_env,
+ WASMModuleInstanceCommon *const module_inst)
+{
+ exec_env->module_inst = module_inst;
+}
+
+void
+wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
+{
+ uint8 *stack_boundary = os_thread_get_stack_boundary();
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ os_mutex_lock(&exec_env->wait_lock);
+#endif
+ exec_env->handle = os_self_thread();
+ exec_env->native_stack_boundary =
+ stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
+ exec_env->native_stack_top_min = (void *)UINTPTR_MAX;
+#if WASM_ENABLE_THREAD_MGR != 0
+ os_mutex_unlock(&exec_env->wait_lock);
+#endif
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+void *
+wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env)
+{
+ return exec_env->thread_arg;
+}
+
+void
+wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
+{
+ exec_env->thread_arg = thread_arg;
+}
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+void
+wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
+{
+ jmpbuf->prev = exec_env->jmpbuf_stack_top;
+ exec_env->jmpbuf_stack_top = jmpbuf;
+}
+
+WASMJmpBuf *
+wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env)
+{
+ WASMJmpBuf *stack_top = exec_env->jmpbuf_stack_top;
+
+ if (stack_top) {
+ exec_env->jmpbuf_stack_top = stack_top->prev;
+ return stack_top;
+ }
+
+ return NULL;
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.h
new file mode 100644
index 000000000..29b28a159
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_exec_env.h
@@ -0,0 +1,323 @@
+/*
+ * 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_assert.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct WASMModuleInstanceCommon;
+struct WASMInterpFrame;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+typedef struct WASMCluster WASMCluster;
+#if WASM_ENABLE_DEBUG_INTERP != 0
+typedef struct WASMCurrentEnvStatus WASMCurrentEnvStatus;
+#endif
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+typedef struct WASMJmpBuf {
+ struct WASMJmpBuf *prev;
+ korp_jmpbuf jmpbuf;
+} WASMJmpBuf;
+#endif
+
+/* 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;
+
+ /* Note: field module_inst, argv_buf, native_stack_boundary,
+ suspend_flags, aux_stack_boundary, aux_stack_bottom, and
+ native_symbol are used by AOTed code, don't change the
+ places of them */
+
+ /* The WASM module instance of current thread */
+ struct WASMModuleInstanceCommon *module_inst;
+
+#if WASM_ENABLE_AOT != 0
+ uint32 *argv_buf;
+#endif
+
+ /* The boundary of native stack. When runtime detects that native
+ frame may overrun this boundary, it throws stack overflow
+ exception. */
+ uint8 *native_stack_boundary;
+
+ /* Used to terminate or suspend current thread
+ bit 0: need to terminate
+ bit 1: need to suspend
+ bit 2: need to go into breakpoint
+ bit 3: return from pthread_exit */
+ union {
+ uint32 flags;
+ uintptr_t __padding__;
+ } suspend_flags;
+
+ /* Auxiliary stack boundary */
+ union {
+ uint32 boundary;
+ uintptr_t __padding__;
+ } aux_stack_boundary;
+
+ /* Auxiliary stack bottom */
+ union {
+ uint32 bottom;
+ uintptr_t __padding__;
+ } aux_stack_bottom;
+
+#if WASM_ENABLE_AOT != 0
+ /* Native symbol list, reserved */
+ void **native_symbol;
+#endif
+
+ /*
+ * The lowest stack pointer value observed.
+ * Assumption: native stack grows to the lower address.
+ */
+ uint8 *native_stack_top_min;
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /**
+ * Cache for
+ * - jit native operations in 32-bit target which hasn't 64-bit
+ * int/float registers, mainly for the operations of double and int64,
+ * such as F64TOI64, F32TOI64, I64 MUL/REM, and so on.
+ * - SSE instructions.
+ **/
+ uint64 jit_cache[2];
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* thread return value */
+ void *thread_ret_value;
+
+ /* Must be provided by thread library */
+ void *(*thread_start_routine)(void *);
+ void *thread_arg;
+
+ /* pointer to the cluster */
+ WASMCluster *cluster;
+
+ /* used to support debugger */
+ korp_mutex wait_lock;
+ korp_cond wait_cond;
+ /* the count of threads which are joining current thread */
+ uint32 wait_count;
+
+ /* whether current thread is detached */
+ bool thread_is_detached;
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ WASMCurrentEnvStatus *current_status;
+#endif
+
+ /* attachment for native function */
+ void *attachment;
+
+ void *user_data;
+
+ /* Current interpreter frame of current thread */
+ struct WASMInterpFrame *cur_frame;
+
+ /* The native thread handle of current thread */
+ korp_tid handle;
+
+#if WASM_ENABLE_INTERP != 0 && WASM_ENABLE_FAST_INTERP == 0
+ BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMJmpBuf *jmpbuf_stack_top;
+ /* One guard page for the exception check */
+ uint8 *exce_check_guard_page;
+#endif
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ uint32 max_wasm_stack_used;
+#endif
+
+ /* 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 WASM stack. */
+ uint8 bottom[1];
+ } s;
+ } wasm_stack;
+} WASMExecEnv;
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+#define RECORD_STACK_USAGE(e, p) \
+ do { \
+ if ((e)->native_stack_top_min > (p)) { \
+ (e)->native_stack_top_min = (p); \
+ } \
+ } while (0)
+#else
+#define RECORD_STACK_USAGE(e, p) (void)0
+#endif
+
+WASMExecEnv *
+wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
+ uint32 stack_size);
+
+void
+wasm_exec_env_destroy_internal(WASMExecEnv *exec_env);
+
+WASMExecEnv *
+wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
+ uint32 stack_size);
+
+void
+wasm_exec_env_destroy(WASMExecEnv *exec_env);
+
+static inline bool
+wasm_exec_env_is_aux_stack_managed_by_runtime(WASMExecEnv *exec_env)
+{
+ return exec_env->aux_stack_boundary.boundary != 0
+ || exec_env->aux_stack_bottom.bottom != 0;
+}
+
+/**
+ * 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));
+
+ /* For classic interpreter, the outs area doesn't contain the const cells,
+ its size cannot be larger than the frame size, so here checking stack
+ overflow with multiplying by 2 is enough. For fast interpreter, since
+ the outs area contains const cells, its size may be larger than current
+ frame size, we should check again before putting the function arguments
+ into the outs area. */
+ if (size * 2
+ > (uint32)(uintptr_t)(exec_env->wasm_stack.s.top_boundary - addr)) {
+ /* WASM stack overflow. */
+ return NULL;
+ }
+
+ exec_env->wasm_stack.s.top += size;
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ {
+ uint32 wasm_stack_used =
+ exec_env->wasm_stack.s.top - exec_env->wasm_stack.s.bottom;
+ if (wasm_stack_used > exec_env->max_wasm_stack_used)
+ exec_env->max_wasm_stack_used = wasm_stack_used;
+ }
+#endif
+ 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);
+
+void
+wasm_exec_env_set_module_inst(
+ WASMExecEnv *exec_env, struct WASMModuleInstanceCommon *const module_inst);
+
+void
+wasm_exec_env_set_thread_info(WASMExecEnv *exec_env);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+void *
+wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env);
+
+void
+wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+void
+wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
+
+WASMJmpBuf *
+wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_EXEC_ENV_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.c
new file mode 100644
index 000000000..82676ae27
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.c
@@ -0,0 +1,759 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_runtime_common.h"
+#include "../interpreter/wasm_runtime.h"
+#include "bh_platform.h"
+#include "mem_alloc.h"
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "../common/wasm_shared_memory.h"
+#endif
+
+typedef enum Memory_Mode {
+ MEMORY_MODE_UNKNOWN = 0,
+ MEMORY_MODE_POOL,
+ MEMORY_MODE_ALLOCATOR,
+ MEMORY_MODE_SYSTEM_ALLOCATOR
+} Memory_Mode;
+
+static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
+
+static mem_allocator_t pool_allocator = NULL;
+
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+static void *allocator_user_data = NULL;
+static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
+static void *(*realloc_func)(void *user_data, void *ptr,
+ unsigned int size) = NULL;
+static void (*free_func)(void *user_data, void *ptr) = NULL;
+#else
+static void *(*malloc_func)(unsigned int size) = NULL;
+static void *(*realloc_func)(void *ptr, unsigned int size) = NULL;
+static void (*free_func)(void *ptr) = NULL;
+#endif
+
+static unsigned int global_pool_size;
+
+static bool
+wasm_memory_init_with_pool(void *mem, unsigned int bytes)
+{
+ mem_allocator_t _allocator = mem_allocator_create(mem, bytes);
+
+ if (_allocator) {
+ memory_mode = MEMORY_MODE_POOL;
+ pool_allocator = _allocator;
+ global_pool_size = bytes;
+ return true;
+ }
+ LOG_ERROR("Init memory with pool (%p, %u) failed.\n", mem, bytes);
+ return false;
+}
+
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+static bool
+wasm_memory_init_with_allocator(void *_user_data, void *_malloc_func,
+ void *_realloc_func, void *_free_func)
+{
+ if (_malloc_func && _free_func && _malloc_func != _free_func) {
+ memory_mode = MEMORY_MODE_ALLOCATOR;
+ allocator_user_data = _user_data;
+ malloc_func = _malloc_func;
+ realloc_func = _realloc_func;
+ free_func = _free_func;
+ return true;
+ }
+ LOG_ERROR("Init memory with allocator (%p, %p, %p, %p) failed.\n",
+ _user_data, _malloc_func, _realloc_func, _free_func);
+ return false;
+}
+#else
+static bool
+wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func,
+ void *_free_func)
+{
+ if (_malloc_func && _free_func && _malloc_func != _free_func) {
+ memory_mode = MEMORY_MODE_ALLOCATOR;
+ malloc_func = _malloc_func;
+ realloc_func = _realloc_func;
+ free_func = _free_func;
+ return true;
+ }
+ LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n", _malloc_func,
+ _realloc_func, _free_func);
+ return false;
+}
+#endif
+
+bool
+wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
+ const MemAllocOption *alloc_option)
+{
+ if (mem_alloc_type == Alloc_With_Pool) {
+ return wasm_memory_init_with_pool(alloc_option->pool.heap_buf,
+ alloc_option->pool.heap_size);
+ }
+ else if (mem_alloc_type == Alloc_With_Allocator) {
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+ return wasm_memory_init_with_allocator(
+ alloc_option->allocator.user_data,
+ alloc_option->allocator.malloc_func,
+ alloc_option->allocator.realloc_func,
+ alloc_option->allocator.free_func);
+#else
+ return wasm_memory_init_with_allocator(
+ alloc_option->allocator.malloc_func,
+ alloc_option->allocator.realloc_func,
+ alloc_option->allocator.free_func);
+#endif
+ }
+ else if (mem_alloc_type == Alloc_With_System_Allocator) {
+ memory_mode = MEMORY_MODE_SYSTEM_ALLOCATOR;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+void
+wasm_runtime_memory_destroy()
+{
+ if (memory_mode == MEMORY_MODE_POOL) {
+#if BH_ENABLE_GC_VERIFY == 0
+ (void)mem_allocator_destroy(pool_allocator);
+#else
+ int ret = mem_allocator_destroy(pool_allocator);
+ if (ret != 0) {
+ /* Memory leak detected */
+ exit(-1);
+ }
+#endif
+ }
+ memory_mode = MEMORY_MODE_UNKNOWN;
+}
+
+unsigned
+wasm_runtime_memory_pool_size()
+{
+ if (memory_mode == MEMORY_MODE_POOL)
+ return global_pool_size;
+ else
+ return UINT32_MAX;
+}
+
+static inline void *
+wasm_runtime_malloc_internal(unsigned int size)
+{
+ if (memory_mode == MEMORY_MODE_UNKNOWN) {
+ LOG_WARNING(
+ "wasm_runtime_malloc failed: memory hasn't been initialize.\n");
+ return NULL;
+ }
+ else if (memory_mode == MEMORY_MODE_POOL) {
+ return mem_allocator_malloc(pool_allocator, size);
+ }
+ else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+ return malloc_func(allocator_user_data, size);
+#else
+ return malloc_func(size);
+#endif
+ }
+ else {
+ return os_malloc(size);
+ }
+}
+
+static inline void *
+wasm_runtime_realloc_internal(void *ptr, unsigned int size)
+{
+ if (memory_mode == MEMORY_MODE_UNKNOWN) {
+ LOG_WARNING(
+ "wasm_runtime_realloc failed: memory hasn't been initialize.\n");
+ return NULL;
+ }
+ else if (memory_mode == MEMORY_MODE_POOL) {
+ return mem_allocator_realloc(pool_allocator, ptr, size);
+ }
+ else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
+ if (realloc_func)
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+ return realloc_func(allocator_user_data, ptr, size);
+#else
+ return realloc_func(ptr, size);
+#endif
+ else
+ return NULL;
+ }
+ else {
+ return os_realloc(ptr, size);
+ }
+}
+
+static inline void
+wasm_runtime_free_internal(void *ptr)
+{
+ if (!ptr) {
+ LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
+#if BH_ENABLE_GC_VERIFY != 0
+ exit(-1);
+#endif
+ return;
+ }
+
+ if (memory_mode == MEMORY_MODE_UNKNOWN) {
+ LOG_WARNING("warning: wasm_runtime_free failed: "
+ "memory hasn't been initialize.\n");
+ }
+ else if (memory_mode == MEMORY_MODE_POOL) {
+ mem_allocator_free(pool_allocator, ptr);
+ }
+ else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
+#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
+ free_func(allocator_user_data, ptr);
+#else
+ free_func(ptr);
+#endif
+ }
+ else {
+ os_free(ptr);
+ }
+}
+
+void *
+wasm_runtime_malloc(unsigned int size)
+{
+ if (size == 0) {
+ LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
+ /* At lease alloc 1 byte to avoid malloc failed */
+ size = 1;
+#if BH_ENABLE_GC_VERIFY != 0
+ exit(-1);
+#endif
+ }
+
+ return wasm_runtime_malloc_internal(size);
+}
+
+void *
+wasm_runtime_realloc(void *ptr, unsigned int size)
+{
+ return wasm_runtime_realloc_internal(ptr, size);
+}
+
+void
+wasm_runtime_free(void *ptr)
+{
+ wasm_runtime_free_internal(ptr);
+}
+
+bool
+wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info)
+{
+ if (memory_mode == MEMORY_MODE_POOL) {
+ return mem_allocator_get_alloc_info(pool_allocator, mem_alloc_info);
+ }
+ return false;
+}
+
+bool
+wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
+ uint32 app_offset, uint32 size)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (!memory_inst) {
+ goto fail;
+ }
+
+ /* integer overflow check */
+ if (app_offset > UINT32_MAX - size) {
+ goto fail;
+ }
+
+ if (app_offset + size <= memory_inst->memory_data_size) {
+ return true;
+ }
+
+fail:
+ wasm_set_exception(module_inst, "out of bounds memory access");
+ return false;
+}
+
+bool
+wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
+ uint32 app_str_offset)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ uint32 app_end_offset;
+ char *str, *str_end;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
+ &app_end_offset))
+ goto fail;
+
+ str = wasm_runtime_addr_app_to_native(module_inst_comm, 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_set_exception(module_inst, "out of bounds memory access");
+ return false;
+}
+
+bool
+wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
+ void *native_ptr, uint32 size)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst;
+ uint8 *addr = (uint8 *)native_ptr;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (!memory_inst) {
+ goto fail;
+ }
+
+ /* integer overflow check */
+ if ((uintptr_t)addr > UINTPTR_MAX - size) {
+ goto fail;
+ }
+
+ if (memory_inst->memory_data <= addr
+ && addr + size <= memory_inst->memory_data_end) {
+ return true;
+ }
+
+fail:
+ wasm_set_exception(module_inst, "out of bounds memory access");
+ return false;
+}
+
+void *
+wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
+ uint32 app_offset)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst;
+ uint8 *addr;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (!memory_inst) {
+ return NULL;
+ }
+
+ addr = memory_inst->memory_data + app_offset;
+
+ if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
+ return addr;
+
+ return NULL;
+}
+
+uint32
+wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
+ void *native_ptr)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst;
+ uint8 *addr = (uint8 *)native_ptr;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (!memory_inst) {
+ return 0;
+ }
+
+ if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
+ return (uint32)(addr - memory_inst->memory_data);
+
+ return 0;
+}
+
+bool
+wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
+ uint32 app_offset, uint32 *p_app_start_offset,
+ uint32 *p_app_end_offset)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst;
+ uint32 memory_data_size;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (!memory_inst) {
+ return false;
+ }
+
+ memory_data_size = memory_inst->memory_data_size;
+
+ if (app_offset < memory_data_size) {
+ if (p_app_start_offset)
+ *p_app_start_offset = 0;
+ if (p_app_end_offset)
+ *p_app_end_offset = memory_data_size;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm,
+ uint8 *native_ptr,
+ uint8 **p_native_start_addr,
+ uint8 **p_native_end_addr)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMMemoryInstance *memory_inst;
+ uint8 *addr = (uint8 *)native_ptr;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (!memory_inst) {
+ return false;
+ }
+
+ if (memory_inst->memory_data <= addr
+ && addr < memory_inst->memory_data_end) {
+ if (p_native_start_addr)
+ *p_native_start_addr = memory_inst->memory_data;
+ if (p_native_end_addr)
+ *p_native_end_addr = memory_inst->memory_data_end;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
+ uint32 app_buf_addr, uint32 app_buf_size,
+ void **p_native_addr)
+{
+ WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
+ uint8 *native_addr;
+
+ if (!memory_inst) {
+ goto fail;
+ }
+
+ native_addr = memory_inst->memory_data + app_buf_addr;
+
+ /* No need to check the app_offset and buf_size if memory access
+ boundary check with hardware trap is enabled */
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ if (app_buf_addr >= memory_inst->memory_data_size) {
+ goto fail;
+ }
+
+ if (!is_str) {
+ if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) {
+ goto fail;
+ }
+ }
+ else {
+ const char *str, *str_end;
+
+ /* The whole string must be in the linear memory */
+ str = (const char *)native_addr;
+ str_end = (const char *)memory_inst->memory_data_end;
+ while (str < str_end && *str != '\0')
+ str++;
+ if (str == str_end)
+ goto fail;
+ }
+#endif
+
+ *p_native_addr = (void *)native_addr;
+ return true;
+fail:
+ wasm_set_exception(module_inst, "out of bounds memory access");
+ return false;
+}
+
+WASMMemoryInstance *
+wasm_get_default_memory(WASMModuleInstance *module_inst)
+{
+ if (module_inst->memories)
+ return module_inst->memories[0];
+ else
+ return NULL;
+}
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+bool
+wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
+{
+ WASMMemoryInstance *memory = wasm_get_default_memory(module);
+ uint8 *memory_data_old, *memory_data_new, *heap_data_old;
+ uint32 num_bytes_per_page, heap_size, total_size_old;
+ uint32 cur_page_count, max_page_count, total_page_count;
+ uint64 total_size_new;
+ bool ret = true;
+
+ if (!memory)
+ return false;
+
+ heap_data_old = memory->heap_data;
+ heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
+
+ memory_data_old = memory->memory_data;
+ total_size_old = memory->memory_data_size;
+
+ num_bytes_per_page = memory->num_bytes_per_page;
+ cur_page_count = memory->cur_page_count;
+ max_page_count = memory->max_page_count;
+ total_page_count = inc_page_count + cur_page_count;
+ total_size_new = num_bytes_per_page * (uint64)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) {
+ return false;
+ }
+
+ bh_assert(total_size_new <= 4 * (uint64)BH_GB);
+ if (total_size_new > UINT32_MAX) {
+ /* Resize to 1 page with size 4G-1 */
+ num_bytes_per_page = UINT32_MAX;
+ total_page_count = max_page_count = 1;
+ total_size_new = UINT32_MAX;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (memory->is_shared) {
+ memory->num_bytes_per_page = num_bytes_per_page;
+ memory->cur_page_count = total_page_count;
+ memory->max_page_count = max_page_count;
+ /* No need to update memory->memory_data_size as it is
+ initialized with the maximum memory data size for
+ shared memory */
+ return true;
+ }
+#endif
+
+ if (heap_size > 0) {
+ if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
+ wasm_runtime_show_app_heap_corrupted_prompt();
+ return false;
+ }
+ }
+
+ if (!(memory_data_new =
+ wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
+ if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
+ return false;
+ }
+ if (memory_data_old) {
+ bh_memcpy_s(memory_data_new, (uint32)total_size_new,
+ memory_data_old, total_size_old);
+ wasm_runtime_free(memory_data_old);
+ }
+ }
+
+ memset(memory_data_new + total_size_old, 0,
+ (uint32)total_size_new - total_size_old);
+
+ if (heap_size > 0) {
+ if (mem_allocator_migrate(memory->heap_handle,
+ (char *)heap_data_old
+ + (memory_data_new - memory_data_old),
+ heap_size)
+ != 0) {
+ /* Don't return here as memory->memory_data is obsolete and
+ must be updated to be correctly used later. */
+ ret = false;
+ }
+ }
+
+ memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
+ memory->heap_data_end = memory->heap_data + heap_size;
+
+ memory->num_bytes_per_page = num_bytes_per_page;
+ memory->cur_page_count = total_page_count;
+ memory->max_page_count = max_page_count;
+ memory->memory_data_size = (uint32)total_size_new;
+
+ memory->memory_data = memory_data_new;
+ memory->memory_data_end = memory_data_new + (uint32)total_size_new;
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
+#if UINTPTR_MAX == UINT64_MAX
+ memory->mem_bound_check_1byte.u64 = total_size_new - 1;
+ memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
+ memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
+ memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
+ memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
+#else
+ memory->mem_bound_check_1byte.u32[0] = (uint32)total_size_new - 1;
+ memory->mem_bound_check_2bytes.u32[0] = (uint32)total_size_new - 2;
+ memory->mem_bound_check_4bytes.u32[0] = (uint32)total_size_new - 4;
+ memory->mem_bound_check_8bytes.u32[0] = (uint32)total_size_new - 8;
+ memory->mem_bound_check_16bytes.u32[0] = (uint32)total_size_new - 16;
+#endif
+#endif
+
+ return ret;
+}
+#else
+bool
+wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
+{
+ WASMMemoryInstance *memory = wasm_get_default_memory(module);
+ uint32 num_bytes_per_page, total_size_old;
+ uint32 cur_page_count, max_page_count, total_page_count;
+ uint64 total_size_new;
+
+ if (!memory)
+ return false;
+
+ num_bytes_per_page = memory->num_bytes_per_page;
+ cur_page_count = memory->cur_page_count;
+ max_page_count = memory->max_page_count;
+ total_size_old = num_bytes_per_page * cur_page_count;
+ total_page_count = inc_page_count + cur_page_count;
+ total_size_new = num_bytes_per_page * (uint64)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) {
+ return false;
+ }
+
+ bh_assert(total_size_new <= 4 * (uint64)BH_GB);
+ if (total_size_new > UINT32_MAX) {
+ /* Resize to 1 page with size 4G-1 */
+ num_bytes_per_page = UINT32_MAX;
+ total_page_count = max_page_count = 1;
+ total_size_new = UINT32_MAX;
+ }
+
+#ifdef BH_PLATFORM_WINDOWS
+ if (!os_mem_commit(memory->memory_data_end,
+ (uint32)total_size_new - total_size_old,
+ MMAP_PROT_READ | MMAP_PROT_WRITE)) {
+ return false;
+ }
+#endif
+
+ if (os_mprotect(memory->memory_data_end,
+ (uint32)total_size_new - total_size_old,
+ MMAP_PROT_READ | MMAP_PROT_WRITE)
+ != 0) {
+#ifdef BH_PLATFORM_WINDOWS
+ os_mem_decommit(memory->memory_data_end,
+ (uint32)total_size_new - total_size_old);
+#endif
+ return false;
+ }
+
+ /* The increased pages are filled with zero by the OS when os_mmap,
+ no need to memset it again here */
+
+ memory->num_bytes_per_page = num_bytes_per_page;
+ memory->cur_page_count = total_page_count;
+ memory->max_page_count = max_page_count;
+ memory->memory_data_size = (uint32)total_size_new;
+ memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
+ memory->mem_bound_check_1byte.u64 = total_size_new - 1;
+ memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
+ memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
+ memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
+ memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
+#endif
+
+ return true;
+}
+#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
+
+bool
+wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
+{
+ bool ret = false;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *node =
+ wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
+ if (node)
+ os_mutex_lock(&node->shared_mem_lock);
+#endif
+ ret = wasm_enlarge_memory_internal(module, inc_page_count);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_unlock(&node->shared_mem_lock);
+#endif
+
+ return ret;
+}
+
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+uint32
+wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node)
+{
+ uint32 num_bytes_per_page;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
+#endif
+ num_bytes_per_page = memory->num_bytes_per_page;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
+#endif
+ return num_bytes_per_page;
+}
+
+uint32
+wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node)
+{
+ uint32 linear_mem_size;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
+#endif
+ linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
+#endif
+ return linear_mem_size;
+}
+#endif \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.h
new file mode 100644
index 000000000..1324742fe
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_memory.h
@@ -0,0 +1,41 @@
+/*
+ * 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
+
+#include "bh_common.h"
+#include "../include/wasm_export.h"
+#include "../interpreter/wasm_runtime.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
+ const MemAllocOption *alloc_option);
+
+void
+wasm_runtime_memory_destroy();
+
+unsigned
+wasm_runtime_memory_pool_size();
+
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+uint32
+wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node);
+
+uint32
+wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_MEMORY_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.c
new file mode 100644
index 000000000..1acaed6ee
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.c
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_native.h"
+#include "wasm_runtime_common.h"
+#include "bh_log.h"
+
+#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
+ && !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
+#define ENABLE_QUICKSORT 1
+#else
+#define ENABLE_QUICKSORT 0
+#endif
+
+#define ENABLE_SORT_DEBUG 0
+
+#if ENABLE_SORT_DEBUG != 0
+#include <sys/time.h>
+#endif
+
+static NativeSymbolsList g_native_symbols_list = NULL;
+
+uint32
+get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
+
+#if WASM_ENABLE_SPEC_TEST != 0
+uint32
+get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
+#endif
+
+uint32
+get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
+
+uint32_t
+get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis);
+
+uint32
+get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
+
+uint32
+get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
+
+#if WASM_ENABLE_LIB_PTHREAD != 0
+bool
+lib_pthread_init();
+
+void
+lib_pthread_destroy();
+
+uint32
+get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
+#endif
+
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+bool
+lib_wasi_threads_init(void);
+
+void
+lib_wasi_threads_destroy(void);
+
+uint32
+get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis);
+#endif
+
+uint32
+get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
+
+uint32
+get_lib_rats_export_apis(NativeSymbol **p_lib_rats_apis);
+
+static bool
+compare_type_with_signautre(uint8 type, const char signature)
+{
+ const char num_sig_map[] = { 'F', 'f', 'I', 'i' };
+
+ if (VALUE_TYPE_F64 <= type && type <= VALUE_TYPE_I32
+ && signature == num_sig_map[type - VALUE_TYPE_F64]) {
+ return true;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if ('r' == signature && type == VALUE_TYPE_EXTERNREF)
+ return true;
+#endif
+
+ /* TODO: a v128 parameter */
+ return false;
+}
+
+static bool
+check_symbol_signature(const WASMType *type, const char *signature)
+{
+ const char *p = signature, *p_end;
+ char sig;
+ uint32 i = 0;
+
+ if (!p || strlen(p) < 2)
+ return false;
+
+ p_end = p + strlen(signature);
+
+ if (*p++ != '(')
+ return false;
+
+ if ((uint32)(p_end - p) < (uint32)(type->param_count + 1))
+ /* signatures of parameters, and ')' */
+ return false;
+
+ for (i = 0; i < type->param_count; i++) {
+ sig = *p++;
+
+ /* a f64/f32/i64/i32/externref parameter */
+ if (compare_type_with_signautre(type->types[i], sig))
+ continue;
+
+ /* a pointer/string paramter */
+ if (type->types[i] != VALUE_TYPE_I32)
+ /* pointer and string must be i32 type */
+ return false;
+
+ if (sig == '*') {
+ /* it is a pointer */
+ if (i + 1 < type->param_count
+ && type->types[i + 1] == VALUE_TYPE_I32 && *p == '~') {
+ /* pointer length followed */
+ i++;
+ p++;
+ }
+ }
+ else if (sig == '$') {
+ /* it is a string */
+ }
+ else {
+ /* invalid signature */
+ return false;
+ }
+ }
+
+ if (*p++ != ')')
+ return false;
+
+ if (type->result_count) {
+ if (p >= p_end)
+ return false;
+
+ /* result types includes: f64,f32,i64,i32,externref */
+ if (!compare_type_with_signautre(type->types[i], *p))
+ return false;
+
+ p++;
+ }
+
+ if (*p != '\0')
+ return false;
+
+ return true;
+}
+
+#if ENABLE_QUICKSORT == 0
+static void
+sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
+{
+ uint32 i, j;
+ NativeSymbol temp;
+
+ for (i = 0; i < n_native_symbols - 1; i++) {
+ for (j = i + 1; j < n_native_symbols; j++) {
+ if (strcmp(native_symbols[i].symbol, native_symbols[j].symbol)
+ > 0) {
+ temp = native_symbols[i];
+ native_symbols[i] = native_symbols[j];
+ native_symbols[j] = temp;
+ }
+ }
+ }
+}
+#else
+static void
+swap_symbol(NativeSymbol *left, NativeSymbol *right)
+{
+ NativeSymbol temp = *left;
+ *left = *right;
+ *right = temp;
+}
+
+static void
+quick_sort_symbols(NativeSymbol *native_symbols, int left, int right)
+{
+ NativeSymbol base_symbol;
+ int pin_left = left;
+ int pin_right = right;
+
+ if (left >= right) {
+ return;
+ }
+
+ base_symbol = native_symbols[left];
+ while (left < right) {
+ while (left < right
+ && strcmp(native_symbols[right].symbol, base_symbol.symbol)
+ > 0) {
+ right--;
+ }
+
+ if (left < right) {
+ swap_symbol(&native_symbols[left], &native_symbols[right]);
+ left++;
+ }
+
+ while (left < right
+ && strcmp(native_symbols[left].symbol, base_symbol.symbol) < 0) {
+ left++;
+ }
+
+ if (left < right) {
+ swap_symbol(&native_symbols[left], &native_symbols[right]);
+ right--;
+ }
+ }
+ native_symbols[left] = base_symbol;
+
+ quick_sort_symbols(native_symbols, pin_left, left - 1);
+ quick_sort_symbols(native_symbols, left + 1, pin_right);
+}
+#endif /* end of ENABLE_QUICKSORT */
+
+static void *
+lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
+ const char *symbol, const char **p_signature, void **p_attachment)
+{
+ int low = 0, mid, ret;
+ int high = (int32)n_native_symbols - 1;
+
+ while (low <= high) {
+ mid = (low + high) / 2;
+ ret = strcmp(symbol, native_symbols[mid].symbol);
+ if (ret == 0) {
+ *p_signature = native_symbols[mid].signature;
+ *p_attachment = native_symbols[mid].attachment;
+ return native_symbols[mid].func_ptr;
+ }
+ else if (ret < 0)
+ high = mid - 1;
+ else
+ low = mid + 1;
+ }
+
+ return NULL;
+}
+
+/**
+ * allow func_type and all outputs, like p_signature, p_attachment and
+ * p_call_conv_raw to be NULL
+ */
+void *
+wasm_native_resolve_symbol(const char *module_name, const char *field_name,
+ const WASMType *func_type, const char **p_signature,
+ void **p_attachment, bool *p_call_conv_raw)
+{
+ NativeSymbolsNode *node, *node_next;
+ const char *signature = NULL;
+ void *func_ptr = NULL, *attachment;
+
+ node = g_native_symbols_list;
+ while (node) {
+ node_next = node->next;
+ if (!strcmp(node->module_name, module_name)) {
+ if ((func_ptr =
+ lookup_symbol(node->native_symbols, node->n_native_symbols,
+ field_name, &signature, &attachment))
+ || (field_name[0] == '_'
+ && (func_ptr = lookup_symbol(
+ node->native_symbols, node->n_native_symbols,
+ field_name + 1, &signature, &attachment))))
+ break;
+ }
+ node = node_next;
+ }
+
+ if (!p_signature || !p_attachment || !p_call_conv_raw)
+ return func_ptr;
+
+ if (func_ptr) {
+ if (signature && signature[0] != '\0') {
+ /* signature is not empty, check its format */
+ if (!func_type || !check_symbol_signature(func_type, signature)) {
+#if WASM_ENABLE_WAMR_COMPILER == 0
+ /* Output warning except running aot compiler */
+ LOG_WARNING("failed to check signature '%s' and resolve "
+ "pointer params for import function (%s %s)\n",
+ signature, module_name, field_name);
+#endif
+ return NULL;
+ }
+ else
+ /* Save signature for runtime to do pointer check and
+ address conversion */
+ *p_signature = signature;
+ }
+ else
+ /* signature is empty */
+ *p_signature = NULL;
+
+ *p_attachment = attachment;
+ *p_call_conv_raw = node->call_conv_raw;
+ }
+
+ return func_ptr;
+}
+
+static bool
+register_natives(const char *module_name, NativeSymbol *native_symbols,
+ uint32 n_native_symbols, bool call_conv_raw)
+{
+ NativeSymbolsNode *node;
+#if ENABLE_SORT_DEBUG != 0
+ struct timeval start;
+ struct timeval end;
+ unsigned long timer;
+#endif
+
+ if (!(node = wasm_runtime_malloc(sizeof(NativeSymbolsNode))))
+ return false;
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ os_printf("Register native, size: %u\n", sizeof(NativeSymbolsNode));
+#endif
+
+ node->module_name = module_name;
+ node->native_symbols = native_symbols;
+ node->n_native_symbols = n_native_symbols;
+ node->call_conv_raw = call_conv_raw;
+
+ /* Add to list head */
+ node->next = g_native_symbols_list;
+ g_native_symbols_list = node;
+
+#if ENABLE_SORT_DEBUG != 0
+ gettimeofday(&start, NULL);
+#endif
+
+#if ENABLE_QUICKSORT == 0
+ sort_symbol_ptr(native_symbols, n_native_symbols);
+#else
+ quick_sort_symbols(native_symbols, 0, (int)(n_native_symbols - 1));
+#endif
+
+#if ENABLE_SORT_DEBUG != 0
+ gettimeofday(&end, NULL);
+ timer =
+ 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
+ LOG_ERROR("module_name: %s, nums: %d, sorted used: %ld us", module_name,
+ n_native_symbols, timer);
+#endif
+ return true;
+}
+
+bool
+wasm_native_register_natives(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols)
+{
+ return register_natives(module_name, native_symbols, n_native_symbols,
+ false);
+}
+
+bool
+wasm_native_register_natives_raw(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols)
+{
+ return register_natives(module_name, native_symbols, n_native_symbols,
+ true);
+}
+
+bool
+wasm_native_unregister_natives(const char *module_name,
+ NativeSymbol *native_symbols)
+{
+ NativeSymbolsNode **prevp;
+ NativeSymbolsNode *node;
+
+ prevp = &g_native_symbols_list;
+ while ((node = *prevp) != NULL) {
+ if (node->native_symbols == native_symbols
+ && !strcmp(node->module_name, module_name)) {
+ *prevp = node->next;
+ wasm_runtime_free(node);
+ return true;
+ }
+ prevp = &node->next;
+ }
+ return false;
+}
+
+bool
+wasm_native_init()
+{
+#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \
+ || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
+ || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
+ || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
+ || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
+ NativeSymbol *native_symbols;
+ uint32 n_native_symbols;
+#endif
+
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+ n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
+ if (!wasm_native_register_natives("env", native_symbols, n_native_symbols))
+ goto fail;
+#endif /* WASM_ENABLE_LIBC_BUILTIN */
+
+#if WASM_ENABLE_SPEC_TEST
+ n_native_symbols = get_spectest_export_apis(&native_symbols);
+ if (!wasm_native_register_natives("spectest", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif /* WASM_ENABLE_SPEC_TEST */
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
+ if (!wasm_native_register_natives("wasi_unstable", native_symbols,
+ n_native_symbols))
+ goto fail;
+ if (!wasm_native_register_natives("wasi_snapshot_preview1", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
+#if WASM_ENABLE_BASE_LIB != 0
+ n_native_symbols = get_base_lib_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("env", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
+#if WASM_ENABLE_APP_FRAMEWORK != 0
+ n_native_symbols = get_ext_lib_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("env", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
+#if WASM_ENABLE_LIB_PTHREAD != 0
+ if (!lib_pthread_init())
+ goto fail;
+
+ n_native_symbols = get_lib_pthread_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("env", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+ if (!lib_wasi_threads_init())
+ goto fail;
+
+ n_native_symbols = get_lib_wasi_threads_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("wasi", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
+#if WASM_ENABLE_LIBC_EMCC != 0
+ n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("env", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif /* WASM_ENABLE_LIBC_EMCC */
+
+#if WASM_ENABLE_LIB_RATS != 0
+ n_native_symbols = get_lib_rats_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("env", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif /* WASM_ENABLE_LIB_RATS */
+
+#if WASM_ENABLE_WASI_NN != 0
+ n_native_symbols = get_wasi_nn_export_apis(&native_symbols);
+ if (!wasm_native_register_natives("wasi_nn", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
+ return true;
+#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \
+ || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
+ || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
+ || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
+ || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
+fail:
+ wasm_native_destroy();
+ return false;
+#endif
+}
+
+void
+wasm_native_destroy()
+{
+ NativeSymbolsNode *node, *node_next;
+
+#if WASM_ENABLE_LIB_PTHREAD != 0
+ lib_pthread_destroy();
+#endif
+
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+ lib_wasi_threads_destroy();
+#endif
+
+ node = g_native_symbols_list;
+ while (node) {
+ node_next = node->next;
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+
+ g_native_symbols_list = NULL;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.h
new file mode 100644
index 000000000..4f6645d25
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_native.h
@@ -0,0 +1,81 @@
+/*
+ * 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"
+#include "../include/wasm_export.h"
+#include "../interpreter/wasm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct NativeSymbolsNode {
+ struct NativeSymbolsNode *next;
+ const char *module_name;
+ NativeSymbol *native_symbols;
+ uint32 n_native_symbols;
+ bool call_conv_raw;
+} NativeSymbolsNode, *NativeSymbolsList;
+
+/**
+ * Lookup global variable of a given import global
+ * from 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 true if success, false otherwise
+ */
+bool
+wasm_native_lookup_libc_builtin_global(const char *module_name,
+ const char *global_name,
+ WASMGlobalImport *global);
+
+/**
+ * Resolve native symbol in all libraries, including libc-builtin, libc-wasi,
+ * base lib and extension lib, and user registered natives
+ * function, which can be auto checked by vm before calling native function
+ *
+ * @param module_name the module name of the import function
+ * @param func_name the function name of the import function
+ * @param func_type the function prototype of the import function
+ * @param p_signature output the signature if resolve success
+ *
+ * @return the native function pointer if success, NULL otherwise
+ */
+void *
+wasm_native_resolve_symbol(const char *module_name, const char *field_name,
+ const WASMType *func_type, const char **p_signature,
+ void **p_attachment, bool *p_call_conv_raw);
+
+bool
+wasm_native_register_natives(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols);
+
+bool
+wasm_native_register_natives_raw(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols);
+
+bool
+wasm_native_unregister_natives(const char *module_name,
+ NativeSymbol *native_symbols);
+
+bool
+wasm_native_init();
+
+void
+wasm_native_destroy();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_NATIVE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.c
new file mode 100644
index 000000000..452a2661b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.c
@@ -0,0 +1,5475 @@
+/*
+ * 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 "bh_log.h"
+#include "wasm_native.h"
+#include "wasm_runtime_common.h"
+#include "wasm_memory.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#if WASM_ENABLE_DEBUG_AOT != 0
+#include "../aot/debug/jit_debug.h"
+#endif
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#include "../libraries/debug-engine/debug_engine.h"
+#endif
+#endif
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+#include "../fast-jit/jit_compiler.h"
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+#include "../compilation/aot_llvm.h"
+#endif
+#include "../common/wasm_c_api_internal.h"
+#include "../../version.h"
+
+/**
+ * For runtime build, BH_MALLOC/BH_FREE should be defined as
+ * wasm_runtime_malloc/wasm_runtime_free.
+ */
+#define CHECK(a) CHECK1(a)
+#define CHECK1(a) SHOULD_BE_##a
+
+#define SHOULD_BE_wasm_runtime_malloc 1
+#if !CHECK(BH_MALLOC)
+#error unexpected BH_MALLOC
+#endif
+#undef SHOULD_BE_wasm_runtime_malloc
+
+#define SHOULD_BE_wasm_runtime_free 1
+#if !CHECK(BH_FREE)
+#error unexpected BH_FREE
+#endif
+#undef SHOULD_BE_wasm_runtime_free
+
+#undef CHECK
+#undef CHECK1
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+/**
+ * A safety insurance to prevent
+ * circular depencies which leads stack overflow
+ * try to break early
+ */
+typedef struct LoadingModule {
+ bh_list_link l;
+ /* point to a string pool */
+ const char *module_name;
+} LoadingModule;
+
+static bh_list loading_module_list_head;
+static bh_list *const loading_module_list = &loading_module_list_head;
+static korp_mutex loading_module_list_lock;
+
+/**
+ * A list to store all exported functions/globals/memories/tables
+ * of every fully loaded module
+ */
+static bh_list registered_module_list_head;
+static bh_list *const registered_module_list = &registered_module_list_head;
+static korp_mutex registered_module_list_lock;
+static void
+wasm_runtime_destroy_registered_module_list();
+#endif /* WASM_ENABLE_MULTI_MODULE */
+
+#define E_TYPE_XIP 4
+
+#if WASM_ENABLE_REF_TYPES != 0
+/* Initialize externref hashmap */
+static bool
+wasm_externref_map_init();
+
+/* Destroy externref hashmap */
+static void
+wasm_externref_map_destroy();
+#endif /* WASM_ENABLE_REF_TYPES */
+
+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 void *
+runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
+ char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ if (module_inst != NULL) {
+ wasm_runtime_set_exception(module_inst, "allocate memory failed");
+ }
+ else if (error_buf != NULL) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ }
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+#if WASM_ENABLE_FAST_JIT != 0
+static JitCompOptions jit_options = { 0 };
+#endif
+
+#if WASM_ENABLE_JIT != 0
+static LLVMJITOptions llvm_jit_options = { 3, 3 };
+#endif
+
+static RunningMode runtime_running_mode = Mode_Default;
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+/* The exec_env of thread local storage, set before calling function
+ and used in signal handler, as we cannot get it from the argument
+ of signal handler */
+static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL;
+
+#ifndef BH_PLATFORM_WINDOWS
+static void
+runtime_signal_handler(void *sig_addr)
+{
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory_inst;
+ WASMJmpBuf *jmpbuf_node;
+ uint8 *mapped_mem_start_addr = NULL;
+ uint8 *mapped_mem_end_addr = NULL;
+ uint32 page_size = os_getpagesize();
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ uint8 *stack_min_addr;
+ uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+#endif
+
+ /* Check whether current thread is running wasm function */
+ if (exec_env_tls && exec_env_tls->handle == os_self_thread()
+ && (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) {
+ /* Get mapped mem info of current instance */
+ module_inst = (WASMModuleInstance *)exec_env_tls->module_inst;
+ /* Get the default memory instance */
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (memory_inst) {
+ mapped_mem_start_addr = memory_inst->memory_data;
+ mapped_mem_end_addr = memory_inst->memory_data + 8 * (uint64)BH_GB;
+ }
+
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ /* Get stack info of current thread */
+ stack_min_addr = os_thread_get_stack_boundary();
+#endif
+
+ if (memory_inst
+ && (mapped_mem_start_addr <= (uint8 *)sig_addr
+ && (uint8 *)sig_addr < mapped_mem_end_addr)) {
+ /* The address which causes segmentation fault is inside
+ the memory instance's guard regions */
+ wasm_set_exception(module_inst, "out of bounds memory access");
+ os_longjmp(jmpbuf_node->jmpbuf, 1);
+ }
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ else if (stack_min_addr - page_size <= (uint8 *)sig_addr
+ && (uint8 *)sig_addr
+ < stack_min_addr + page_size * guard_page_count) {
+ /* The address which causes segmentation fault is inside
+ native thread's guard page */
+ wasm_set_exception(module_inst, "native stack overflow");
+ os_longjmp(jmpbuf_node->jmpbuf, 1);
+ }
+#endif
+ else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr
+ && (uint8 *)sig_addr
+ < exec_env_tls->exce_check_guard_page + page_size) {
+ bh_assert(wasm_copy_exception(module_inst, NULL));
+ os_longjmp(jmpbuf_node->jmpbuf, 1);
+ }
+ }
+}
+#else
+static LONG
+runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
+{
+ PEXCEPTION_RECORD ExceptionRecord = exce_info->ExceptionRecord;
+ uint8 *sig_addr = (uint8 *)ExceptionRecord->ExceptionInformation[1];
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory_inst;
+ WASMJmpBuf *jmpbuf_node;
+ uint8 *mapped_mem_start_addr = NULL;
+ uint8 *mapped_mem_end_addr = NULL;
+ uint32 page_size = os_getpagesize();
+
+ if (exec_env_tls && exec_env_tls->handle == os_self_thread()
+ && (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) {
+ module_inst = (WASMModuleInstance *)exec_env_tls->module_inst;
+ if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+ /* Get the default memory instance */
+ memory_inst = wasm_get_default_memory(module_inst);
+ if (memory_inst) {
+ mapped_mem_start_addr = memory_inst->memory_data;
+ mapped_mem_end_addr =
+ memory_inst->memory_data + 8 * (uint64)BH_GB;
+ }
+
+ if (memory_inst && mapped_mem_start_addr <= (uint8 *)sig_addr
+ && (uint8 *)sig_addr < mapped_mem_end_addr) {
+ /* The address which causes segmentation fault is inside
+ the memory instance's guard regions.
+ Set exception and let the wasm func continue to run, when
+ the wasm func returns, the caller will check whether the
+ exception is thrown and return to runtime. */
+ wasm_set_exception(module_inst, "out of bounds memory access");
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ /* Continue to search next exception handler for
+ interpreter mode as it can be caught by
+ `__try { .. } __except { .. }` sentences in
+ wasm_runtime.c */
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else {
+ /* Skip current instruction and continue to run for
+ AOT mode. TODO: implement unwind support for AOT
+ code in Windows platform */
+ exce_info->ContextRecord->Rip++;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr
+ && (uint8 *)sig_addr
+ < exec_env_tls->exce_check_guard_page + page_size) {
+ bh_assert(wasm_copy_exception(module_inst, NULL));
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else {
+ exce_info->ContextRecord->Rip++;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ }
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ else if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
+ /* Set stack overflow exception and let the wasm func continue
+ to run, when the wasm func returns, the caller will check
+ whether the exception is thrown and return to runtime, and
+ the damaged stack will be recovered by _resetstkoflw(). */
+ wasm_set_exception(module_inst, "native stack overflow");
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else {
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+#endif
+ }
+
+ os_printf("Unhandled exception thrown: exception code: 0x%lx, "
+ "exception address: %p, exception information: %p\n",
+ ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress,
+ sig_addr);
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* end of BH_PLATFORM_WINDOWS */
+
+static bool
+runtime_signal_init()
+{
+#ifndef BH_PLATFORM_WINDOWS
+ return os_thread_signal_init(runtime_signal_handler) == 0 ? true : false;
+#else
+ if (os_thread_signal_init() != 0)
+ return false;
+
+ if (!AddVectoredExceptionHandler(1, runtime_exception_handler)) {
+ os_thread_signal_destroy();
+ return false;
+ }
+#endif
+ return true;
+}
+
+static void
+runtime_signal_destroy()
+{
+#ifdef BH_PLATFORM_WINDOWS
+ RemoveVectoredExceptionHandler(runtime_exception_handler);
+#endif
+ os_thread_signal_destroy();
+}
+
+void
+wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env)
+{
+ exec_env_tls = exec_env;
+}
+
+WASMExecEnv *
+wasm_runtime_get_exec_env_tls()
+{
+ return exec_env_tls;
+}
+#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
+
+static bool
+wasm_runtime_env_init()
+{
+ if (bh_platform_init() != 0)
+ return false;
+
+ if (wasm_native_init() == false) {
+ goto fail1;
+ }
+
+#if WASM_ENABLE_MULTI_MODULE
+ if (BHT_OK != os_mutex_init(&registered_module_list_lock)) {
+ goto fail2;
+ }
+
+ if (BHT_OK != os_mutex_init(&loading_module_list_lock)) {
+ goto fail3;
+ }
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY
+ if (!wasm_shared_memory_init()) {
+ goto fail4;
+ }
+#endif
+
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
+ if (!thread_manager_init()) {
+ goto fail5;
+ }
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!runtime_signal_init()) {
+ goto fail6;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#if WASM_ENABLE_DEBUG_AOT != 0
+ if (!jit_debug_engine_init()) {
+ goto fail7;
+ }
+#endif
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!wasm_externref_map_init()) {
+ goto fail8;
+ }
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0
+ if (!jit_compiler_init(&jit_options)) {
+ goto fail9;
+ }
+#endif
+
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ if (!aot_compiler_init()) {
+ goto fail10;
+ }
+#endif
+
+ return true;
+
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+fail10:
+#if WASM_ENABLE_FAST_JIT != 0
+ jit_compiler_destroy();
+#endif
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+fail9:
+#if WASM_ENABLE_REF_TYPES != 0
+ wasm_externref_map_destroy();
+#endif
+#endif
+#if WASM_ENABLE_REF_TYPES != 0
+fail8:
+#endif
+#if WASM_ENABLE_AOT != 0
+#if WASM_ENABLE_DEBUG_AOT != 0
+ jit_debug_engine_destroy();
+fail7:
+#endif
+#endif
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ runtime_signal_destroy();
+fail6:
+#endif
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
+ thread_manager_destroy();
+fail5:
+#endif
+#if WASM_ENABLE_SHARED_MEMORY
+ wasm_shared_memory_destroy();
+fail4:
+#endif
+#if WASM_ENABLE_MULTI_MODULE
+ os_mutex_destroy(&loading_module_list_lock);
+fail3:
+ os_mutex_destroy(&registered_module_list_lock);
+fail2:
+#endif
+ wasm_native_destroy();
+fail1:
+ bh_platform_destroy();
+
+ return false;
+}
+
+static bool
+wasm_runtime_exec_env_check(WASMExecEnv *exec_env)
+{
+ return 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;
+}
+
+bool
+wasm_runtime_init()
+{
+ if (!wasm_runtime_memory_init(Alloc_With_System_Allocator, NULL))
+ return false;
+
+ if (!wasm_runtime_env_init()) {
+ wasm_runtime_memory_destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void
+wasm_runtime_destroy()
+{
+#if WASM_ENABLE_REF_TYPES != 0
+ wasm_externref_map_destroy();
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#if WASM_ENABLE_DEBUG_AOT != 0
+ jit_debug_engine_destroy();
+#endif
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ runtime_signal_destroy();
+#endif
+
+ /* runtime env destroy */
+#if WASM_ENABLE_MULTI_MODULE
+ wasm_runtime_destroy_loading_module_list();
+ os_mutex_destroy(&loading_module_list_lock);
+
+ wasm_runtime_destroy_registered_module_list();
+ os_mutex_destroy(&registered_module_list_lock);
+#endif
+
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ /* Destroy LLVM-JIT compiler after destroying the modules
+ * loaded by multi-module feature, since these modules may
+ * create backend threads to compile the wasm functions,
+ * which may access the LLVM resources. We wait until they
+ * finish the compilation to avoid accessing the destroyed
+ * resources in the compilation threads.
+ */
+ aot_compiler_destroy();
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /* Destroy Fast-JIT compiler after destroying the modules
+ * loaded by multi-module feature, since the Fast JIT's
+ * code cache allocator may be used by these modules.
+ */
+ jit_compiler_destroy();
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY
+ wasm_shared_memory_destroy();
+#endif
+
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_debug_engine_destroy();
+#endif
+ thread_manager_destroy();
+#endif
+
+ wasm_native_destroy();
+ bh_platform_destroy();
+
+ wasm_runtime_memory_destroy();
+}
+
+RunningMode
+wasm_runtime_get_default_running_mode(void)
+{
+ return runtime_running_mode;
+}
+
+#if WASM_ENABLE_JIT != 0
+LLVMJITOptions
+wasm_runtime_get_llvm_jit_options(void)
+{
+ return llvm_jit_options;
+}
+#endif
+
+bool
+wasm_runtime_full_init(RuntimeInitArgs *init_args)
+{
+ if (!wasm_runtime_memory_init(init_args->mem_alloc_type,
+ &init_args->mem_alloc_option))
+ return false;
+
+ if (!wasm_runtime_set_default_running_mode(init_args->running_mode)) {
+ wasm_runtime_memory_destroy();
+ return false;
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0
+ jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ llvm_jit_options.size_level = init_args->llvm_jit_size_level;
+ llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
+#endif
+
+ if (!wasm_runtime_env_init()) {
+ wasm_runtime_memory_destroy();
+ return false;
+ }
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (strlen(init_args->ip_addr))
+ if (!wasm_debug_engine_init(init_args->ip_addr,
+ init_args->instance_port)) {
+ wasm_runtime_destroy();
+ return false;
+ }
+#endif
+
+ if (init_args->n_native_symbols > 0
+ && !wasm_runtime_register_natives(init_args->native_module_name,
+ init_args->native_symbols,
+ init_args->n_native_symbols)) {
+ wasm_runtime_destroy();
+ return false;
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ wasm_cluster_set_max_thread_num(init_args->max_thread_num);
+#endif
+
+ return true;
+}
+
+bool
+wasm_runtime_is_running_mode_supported(RunningMode running_mode)
+{
+ if (running_mode == Mode_Default) {
+ return true;
+ }
+ else if (running_mode == Mode_Interp) {
+#if WASM_ENABLE_INTERP != 0
+ return true;
+#endif
+ }
+ else if (running_mode == Mode_Fast_JIT) {
+#if WASM_ENABLE_FAST_JIT != 0
+ return true;
+#endif
+ }
+ else if (running_mode == Mode_LLVM_JIT) {
+#if WASM_ENABLE_JIT != 0
+ return true;
+#endif
+ }
+ else if (running_mode == Mode_Multi_Tier_JIT) {
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+bool
+wasm_runtime_set_default_running_mode(RunningMode running_mode)
+{
+ if (wasm_runtime_is_running_mode_supported(running_mode)) {
+ runtime_running_mode = running_mode;
+ return true;
+ }
+ return false;
+}
+
+PackageType
+get_package_type(const uint8 *buf, uint32 size)
+{
+#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
+ uint32 buf32 = *(uint32 *)buf;
+ buf = (const uint8 *)&buf32;
+#endif
+ 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;
+}
+
+#if WASM_ENABLE_AOT != 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);
+}
+
+#define CHECK_BUF(buf, buf_end, length) \
+ do { \
+ if ((uintptr_t)buf + length < (uintptr_t)buf \
+ || (uintptr_t)buf + length > (uintptr_t)buf_end) \
+ return false; \
+ } while (0)
+
+#define read_uint16(p, p_end, res) \
+ do { \
+ p = (uint8 *)align_ptr(p, sizeof(uint16)); \
+ CHECK_BUF(p, p_end, sizeof(uint16)); \
+ res = *(uint16 *)p; \
+ p += sizeof(uint16); \
+ } while (0)
+
+#define read_uint32(p, p_end, res) \
+ do { \
+ p = (uint8 *)align_ptr(p, sizeof(uint32)); \
+ CHECK_BUF(p, p_end, sizeof(uint32)); \
+ res = *(uint32 *)p; \
+ p += sizeof(uint32); \
+ } while (0)
+
+bool
+wasm_runtime_is_xip_file(const uint8 *buf, uint32 size)
+{
+ const uint8 *p = buf, *p_end = buf + size;
+ uint32 section_type, section_size;
+ uint16 e_type;
+
+ if (get_package_type(buf, size) != Wasm_Module_AoT)
+ return false;
+
+ CHECK_BUF(p, p_end, 8);
+ p += 8;
+ while (p < p_end) {
+ read_uint32(p, p_end, section_type);
+ read_uint32(p, p_end, section_size);
+ CHECK_BUF(p, p_end, section_size);
+
+ if (section_type == AOT_SECTION_TYPE_TARGET_INFO) {
+ p += 4;
+ read_uint16(p, p_end, e_type);
+ return (e_type == E_TYPE_XIP) ? true : false;
+ }
+ else if (section_type >= AOT_SECTION_TYPE_SIGANATURE) {
+ return false;
+ }
+ p += section_size;
+ }
+
+ return false;
+}
+#endif /* end of WASM_ENABLE_AOT */
+
+#if (WASM_ENABLE_THREAD_MGR != 0) && (WASM_ENABLE_DEBUG_INTERP != 0)
+uint32
+wasm_runtime_start_debug_instance_with_port(WASMExecEnv *exec_env, int32_t port)
+{
+ WASMModuleInstanceCommon *module_inst =
+ wasm_runtime_get_module_inst(exec_env);
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(module_inst);
+ bh_assert(cluster);
+
+ if (module_inst->module_type != Wasm_Module_Bytecode) {
+ LOG_WARNING("Attempt to create a debug instance for an AOT module");
+ return 0;
+ }
+
+ if (cluster->debug_inst) {
+ LOG_WARNING("Cluster already bind to a debug instance");
+ return cluster->debug_inst->control_thread->port;
+ }
+
+ if (wasm_debug_instance_create(cluster, port)) {
+ return cluster->debug_inst->control_thread->port;
+ }
+
+ return 0;
+}
+
+uint32
+wasm_runtime_start_debug_instance(WASMExecEnv *exec_env)
+{
+ return wasm_runtime_start_debug_instance_with_port(exec_env, -1);
+}
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static module_reader reader;
+static module_destroyer destroyer;
+void
+wasm_runtime_set_module_reader(const module_reader reader_cb,
+ const module_destroyer destroyer_cb)
+{
+ reader = reader_cb;
+ destroyer = destroyer_cb;
+}
+
+module_reader
+wasm_runtime_get_module_reader()
+{
+ return reader;
+}
+
+module_destroyer
+wasm_runtime_get_module_destroyer()
+{
+ return destroyer;
+}
+
+static WASMRegisteredModule *
+wasm_runtime_find_module_registered_by_reference(WASMModuleCommon *module)
+{
+ WASMRegisteredModule *reg_module = NULL;
+
+ os_mutex_lock(&registered_module_list_lock);
+ reg_module = bh_list_first_elem(registered_module_list);
+ while (reg_module && module != reg_module->module) {
+ reg_module = bh_list_elem_next(reg_module);
+ }
+ os_mutex_unlock(&registered_module_list_lock);
+
+ return reg_module;
+}
+
+bool
+wasm_runtime_register_module_internal(const char *module_name,
+ WASMModuleCommon *module,
+ uint8 *orig_file_buf,
+ uint32 orig_file_buf_size,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMRegisteredModule *node = NULL;
+
+ node = wasm_runtime_find_module_registered_by_reference(module);
+ if (node) { /* module has been registered */
+ if (node->module_name) { /* module has name */
+ if (!module_name || strcmp(node->module_name, module_name)) {
+ /* module has different name */
+ LOG_DEBUG("module(%p) has been registered with name %s", module,
+ node->module_name);
+ set_error_buf(error_buf, error_buf_size,
+ "Register module failed: "
+ "failed to rename the module");
+ return false;
+ }
+ else {
+ /* module has the same name */
+ LOG_DEBUG(
+ "module(%p) has been registered with the same name %s",
+ module, node->module_name);
+ return true;
+ }
+ }
+ else {
+ /* module has empyt name, reset it */
+ node->module_name = module_name;
+ return true;
+ }
+ }
+
+ /* module hasn't been registered */
+ node = runtime_malloc(sizeof(WASMRegisteredModule), NULL, NULL, 0);
+ if (!node) {
+ LOG_DEBUG("malloc WASMRegisteredModule failed. SZ=%d",
+ sizeof(WASMRegisteredModule));
+ return false;
+ }
+
+ /* share the string and the module */
+ node->module_name = module_name;
+ node->module = module;
+ node->orig_file_buf = orig_file_buf;
+ node->orig_file_buf_size = orig_file_buf_size;
+
+ os_mutex_lock(&registered_module_list_lock);
+ bh_list_status ret = bh_list_insert(registered_module_list, node);
+ bh_assert(BH_LIST_SUCCESS == ret);
+ (void)ret;
+ os_mutex_unlock(&registered_module_list_lock);
+ return true;
+}
+
+bool
+wasm_runtime_register_module(const char *module_name, WASMModuleCommon *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (!error_buf || !error_buf_size) {
+ LOG_ERROR("error buffer is required");
+ return false;
+ }
+
+ if (!module_name || !module) {
+ LOG_DEBUG("module_name and module are required");
+ set_error_buf(error_buf, error_buf_size,
+ "Register module failed: "
+ "module_name and module are required");
+ return false;
+ }
+
+ if (wasm_runtime_is_built_in_module(module_name)) {
+ LOG_DEBUG("%s is a built-in module name", module_name);
+ set_error_buf(error_buf, error_buf_size,
+ "Register module failed: "
+ "can not register as a built-in module");
+ return false;
+ }
+
+ return wasm_runtime_register_module_internal(module_name, module, NULL, 0,
+ error_buf, error_buf_size);
+}
+
+void
+wasm_runtime_unregister_module(const WASMModuleCommon *module)
+{
+ WASMRegisteredModule *registered_module = NULL;
+
+ os_mutex_lock(&registered_module_list_lock);
+ registered_module = bh_list_first_elem(registered_module_list);
+ while (registered_module && module != registered_module->module) {
+ registered_module = bh_list_elem_next(registered_module);
+ }
+
+ /* it does not matter if it is not exist. after all, it is gone */
+ if (registered_module) {
+ bh_list_remove(registered_module_list, registered_module);
+ wasm_runtime_free(registered_module);
+ }
+ os_mutex_unlock(&registered_module_list_lock);
+}
+
+WASMModuleCommon *
+wasm_runtime_find_module_registered(const char *module_name)
+{
+ WASMRegisteredModule *module = NULL, *module_next;
+
+ os_mutex_lock(&registered_module_list_lock);
+ module = bh_list_first_elem(registered_module_list);
+ while (module) {
+ module_next = bh_list_elem_next(module);
+ if (module->module_name && !strcmp(module_name, module->module_name)) {
+ break;
+ }
+ module = module_next;
+ }
+ os_mutex_unlock(&registered_module_list_lock);
+
+ return module ? module->module : NULL;
+}
+
+/*
+ * simply destroy all
+ */
+static void
+wasm_runtime_destroy_registered_module_list()
+{
+ WASMRegisteredModule *reg_module = NULL;
+
+ os_mutex_lock(&registered_module_list_lock);
+ reg_module = bh_list_first_elem(registered_module_list);
+ while (reg_module) {
+ WASMRegisteredModule *next_reg_module = bh_list_elem_next(reg_module);
+
+ bh_list_remove(registered_module_list, reg_module);
+
+ /* now, it is time to release every module in the runtime */
+ if (reg_module->module->module_type == Wasm_Module_Bytecode) {
+#if WASM_ENABLE_INTERP != 0
+ wasm_unload((WASMModule *)reg_module->module);
+#endif
+ }
+ else {
+#if WASM_ENABLE_AOT != 0
+ aot_unload((AOTModule *)reg_module->module);
+#endif
+ }
+
+ /* destroy the file buffer */
+ if (destroyer && reg_module->orig_file_buf) {
+ destroyer(reg_module->orig_file_buf,
+ reg_module->orig_file_buf_size);
+ reg_module->orig_file_buf = NULL;
+ reg_module->orig_file_buf_size = 0;
+ }
+
+ wasm_runtime_free(reg_module);
+ reg_module = next_reg_module;
+ }
+ os_mutex_unlock(&registered_module_list_lock);
+}
+
+bool
+wasm_runtime_add_loading_module(const char *module_name, char *error_buf,
+ uint32 error_buf_size)
+{
+ LOG_DEBUG("add %s into a loading list", module_name);
+ LoadingModule *loadingModule =
+ runtime_malloc(sizeof(LoadingModule), NULL, error_buf, error_buf_size);
+
+ if (!loadingModule) {
+ return false;
+ }
+
+ /* share the incoming string */
+ loadingModule->module_name = module_name;
+
+ os_mutex_lock(&loading_module_list_lock);
+ bh_list_status ret = bh_list_insert(loading_module_list, loadingModule);
+ bh_assert(BH_LIST_SUCCESS == ret);
+ (void)ret;
+ os_mutex_unlock(&loading_module_list_lock);
+ return true;
+}
+
+void
+wasm_runtime_delete_loading_module(const char *module_name)
+{
+ LOG_DEBUG("delete %s from a loading list", module_name);
+
+ LoadingModule *module = NULL;
+
+ os_mutex_lock(&loading_module_list_lock);
+ module = bh_list_first_elem(loading_module_list);
+ while (module && strcmp(module->module_name, module_name)) {
+ module = bh_list_elem_next(module);
+ }
+
+ /* it does not matter if it is not exist. after all, it is gone */
+ if (module) {
+ bh_list_remove(loading_module_list, module);
+ wasm_runtime_free(module);
+ }
+ os_mutex_unlock(&loading_module_list_lock);
+}
+
+bool
+wasm_runtime_is_loading_module(const char *module_name)
+{
+ LOG_DEBUG("find %s in a loading list", module_name);
+
+ LoadingModule *module = NULL;
+
+ os_mutex_lock(&loading_module_list_lock);
+ module = bh_list_first_elem(loading_module_list);
+ while (module && strcmp(module_name, module->module_name)) {
+ module = bh_list_elem_next(module);
+ }
+ os_mutex_unlock(&loading_module_list_lock);
+
+ return module != NULL;
+}
+
+void
+wasm_runtime_destroy_loading_module_list()
+{
+ LoadingModule *module = NULL;
+
+ os_mutex_lock(&loading_module_list_lock);
+ module = bh_list_first_elem(loading_module_list);
+ while (module) {
+ LoadingModule *next_module = bh_list_elem_next(module);
+
+ bh_list_remove(loading_module_list, module);
+ /*
+ * will not free the module_name since it is
+ * shared one of the const string pool
+ */
+ wasm_runtime_free(module);
+
+ module = next_module;
+ }
+
+ os_mutex_unlock(&loading_module_list_lock);
+}
+#endif /* WASM_ENABLE_MULTI_MODULE */
+
+bool
+wasm_runtime_is_built_in_module(const char *module_name)
+{
+ return (!strcmp("env", module_name) || !strcmp("wasi_unstable", module_name)
+ || !strcmp("wasi_snapshot_preview1", module_name)
+#if WASM_ENABLE_SPEC_TEST != 0
+ || !strcmp("spectest", module_name)
+#endif
+ || !strcmp("", module_name));
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset,
+ uint32 size)
+{
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ return wasm_set_aux_stack(exec_env, start_offset, size);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ return aot_set_aux_stack(exec_env, start_offset, size);
+ }
+#endif
+ return false;
+}
+
+bool
+wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset,
+ uint32 *size)
+{
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ return wasm_get_aux_stack(exec_env, start_offset, size);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ return aot_get_aux_stack(exec_env, start_offset, size);
+ }
+#endif
+ return false;
+}
+
+void
+wasm_runtime_set_max_thread_num(uint32 num)
+{
+ wasm_cluster_set_max_thread_num(num);
+}
+#endif /* end of WASM_ENABLE_THREAD_MGR */
+
+static WASMModuleCommon *
+register_module_with_null_name(WASMModuleCommon *module_common, char *error_buf,
+ uint32 error_buf_size)
+{
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (module_common) {
+ if (!wasm_runtime_register_module_internal(NULL, module_common, NULL, 0,
+ error_buf, error_buf_size)) {
+ wasm_runtime_unload(module_common);
+ return NULL;
+ }
+ return module_common;
+ }
+ else
+ return NULL;
+#else
+ return module_common;
+#endif
+}
+
+WASMModuleCommon *
+wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModuleCommon *module_common = NULL;
+
+ if (get_package_type(buf, size) == Wasm_Module_Bytecode) {
+#if WASM_ENABLE_INTERP != 0
+ module_common =
+ (WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size);
+ return register_module_with_null_name(module_common, error_buf,
+ error_buf_size);
+#endif
+ }
+ else if (get_package_type(buf, size) == Wasm_Module_AoT) {
+#if WASM_ENABLE_AOT != 0
+ module_common = (WASMModuleCommon *)aot_load_from_aot_file(
+ buf, size, error_buf, error_buf_size);
+ return register_module_with_null_name(module_common, error_buf,
+ error_buf_size);
+#endif
+ }
+
+ 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 error_buf_size)
+{
+ WASMModuleCommon *module_common;
+
+ if (!is_aot) {
+#if WASM_ENABLE_INTERP != 0
+ module_common = (WASMModuleCommon *)wasm_load_from_sections(
+ section_list, error_buf, error_buf_size);
+ return register_module_with_null_name(module_common, error_buf,
+ error_buf_size);
+#endif
+ }
+ else {
+#if WASM_ENABLE_AOT != 0
+ module_common = (WASMModuleCommon *)aot_load_from_sections(
+ section_list, error_buf, error_buf_size);
+ return register_module_with_null_name(module_common, error_buf,
+ error_buf_size);
+#endif
+ }
+
+#if WASM_ENABLE_INTERP == 0 || WASM_ENABLE_AOT == 0
+ set_error_buf(error_buf, error_buf_size,
+ "WASM module load failed: invalid section list type");
+ return NULL;
+#endif
+}
+
+void
+wasm_runtime_unload(WASMModuleCommon *module)
+{
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /**
+ * since we will unload and free all module when runtime_destroy()
+ * we don't want users to unwillingly disrupt it
+ */
+ return;
+#endif
+
+#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_internal(WASMModuleCommon *module, bool is_sub_inst,
+ WASMExecEnv *exec_env_main, 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, is_sub_inst, exec_env_main, 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, is_sub_inst, exec_env_main, 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;
+}
+
+WASMModuleInstanceCommon *
+wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
+ uint32 heap_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ return wasm_runtime_instantiate_internal(
+ module, false, NULL, stack_size, heap_size, error_buf, error_buf_size);
+}
+
+void
+wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
+ bool is_sub_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ wasm_deinstantiate((WASMModuleInstance *)module_inst, is_sub_inst);
+ return;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ aot_deinstantiate((AOTModuleInstance *)module_inst, is_sub_inst);
+ return;
+ }
+#endif
+}
+
+bool
+wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
+ RunningMode running_mode)
+{
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT)
+ return true;
+#endif
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *module_inst_interp =
+ (WASMModuleInstance *)module_inst;
+
+ return wasm_set_running_mode(module_inst_interp, running_mode);
+ }
+#endif
+
+ return false;
+}
+
+RunningMode
+wasm_runtime_get_running_mode(wasm_module_inst_t module_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *module_inst_interp =
+ (WASMModuleInstance *)module_inst;
+ return module_inst_interp->e->running_mode;
+ }
+#endif
+
+ return Mode_Default;
+}
+
+void
+wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
+{
+ wasm_runtime_deinstantiate_internal(module_inst, false);
+}
+
+WASMModuleCommon *
+wasm_runtime_get_module(WASMModuleInstanceCommon *module_inst)
+{
+ return (WASMModuleCommon *)((WASMModuleInstance *)module_inst)->module;
+}
+
+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);
+}
+
+bool
+wasm_runtime_init_thread_env(void)
+{
+#ifdef BH_PLATFORM_WINDOWS
+ if (os_thread_env_init() != 0)
+ return false;
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!runtime_signal_init()) {
+#ifdef BH_PLATFORM_WINDOWS
+ os_thread_env_destroy();
+#endif
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+void
+wasm_runtime_destroy_thread_env(void)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ runtime_signal_destroy();
+#endif
+
+#ifdef BH_PLATFORM_WINDOWS
+ os_thread_env_destroy();
+#endif
+}
+
+bool
+wasm_runtime_thread_env_inited(void)
+{
+#ifdef BH_PLATFORM_WINDOWS
+ if (!os_thread_env_inited())
+ return false;
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!os_thread_signal_inited())
+ return false;
+#endif
+#endif
+ return true;
+}
+
+#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0)
+void
+wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module)
+{
+ WASMModuleMemConsumption mem_conspn = { 0 };
+
+#if WASM_ENABLE_INTERP != 0
+ if (module->module_type == Wasm_Module_Bytecode) {
+ wasm_get_module_mem_consumption((WASMModule *)module, &mem_conspn);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module->module_type == Wasm_Module_AoT) {
+ aot_get_module_mem_consumption((AOTModule *)module, &mem_conspn);
+ }
+#endif
+
+ os_printf("WASM module memory consumption, total size: %u\n",
+ mem_conspn.total_size);
+ os_printf(" module struct size: %u\n", mem_conspn.module_struct_size);
+ os_printf(" types size: %u\n", mem_conspn.types_size);
+ os_printf(" imports size: %u\n", mem_conspn.imports_size);
+ os_printf(" funcs size: %u\n", mem_conspn.functions_size);
+ os_printf(" tables size: %u\n", mem_conspn.tables_size);
+ os_printf(" memories size: %u\n", mem_conspn.memories_size);
+ os_printf(" globals size: %u\n", mem_conspn.globals_size);
+ os_printf(" exports size: %u\n", mem_conspn.exports_size);
+ os_printf(" table segs size: %u\n", mem_conspn.table_segs_size);
+ os_printf(" data segs size: %u\n", mem_conspn.data_segs_size);
+ os_printf(" const strings size: %u\n", mem_conspn.const_strs_size);
+#if WASM_ENABLE_AOT != 0
+ os_printf(" aot code size: %u\n", mem_conspn.aot_code_size);
+#endif
+}
+
+void
+wasm_runtime_dump_module_inst_mem_consumption(
+ const WASMModuleInstanceCommon *module_inst)
+{
+ WASMModuleInstMemConsumption mem_conspn = { 0 };
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ wasm_get_module_inst_mem_consumption((WASMModuleInstance *)module_inst,
+ &mem_conspn);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ aot_get_module_inst_mem_consumption((AOTModuleInstance *)module_inst,
+ &mem_conspn);
+ }
+#endif
+
+ os_printf("WASM module inst memory consumption, total size: %u\n",
+ mem_conspn.total_size);
+ os_printf(" module inst struct size: %u\n",
+ mem_conspn.module_inst_struct_size);
+ os_printf(" memories size: %u\n", mem_conspn.memories_size);
+ os_printf(" app heap size: %u\n", mem_conspn.app_heap_size);
+ os_printf(" tables size: %u\n", mem_conspn.tables_size);
+ os_printf(" functions size: %u\n", mem_conspn.functions_size);
+ os_printf(" globals size: %u\n", mem_conspn.globals_size);
+ os_printf(" exports size: %u\n", mem_conspn.exports_size);
+}
+
+void
+wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env)
+{
+ uint32 total_size =
+ offsetof(WASMExecEnv, wasm_stack.s.bottom) + exec_env->wasm_stack_size;
+
+ os_printf("Exec env memory consumption, total size: %u\n", total_size);
+ os_printf(" exec env struct size: %u\n",
+ offsetof(WASMExecEnv, wasm_stack.s.bottom));
+#if WASM_ENABLE_INTERP != 0 && WASM_ENABLE_FAST_INTERP == 0
+ os_printf(" block addr cache size: %u\n",
+ sizeof(exec_env->block_addr_cache));
+#endif
+ os_printf(" stack size: %u\n", exec_env->wasm_stack_size);
+}
+
+uint32
+gc_get_heap_highmark_size(void *heap);
+
+void
+wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
+{
+ WASMModuleInstMemConsumption module_inst_mem_consps;
+ WASMModuleMemConsumption module_mem_consps;
+ WASMModuleInstanceCommon *module_inst_common;
+ WASMModuleCommon *module_common = NULL;
+ void *heap_handle = NULL;
+ uint32 total_size = 0, app_heap_peak_size = 0;
+ uint32 max_aux_stack_used = -1;
+
+ module_inst_common = exec_env->module_inst;
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_common->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *wasm_module_inst =
+ (WASMModuleInstance *)module_inst_common;
+ WASMModule *wasm_module = wasm_module_inst->module;
+ module_common = (WASMModuleCommon *)wasm_module;
+ if (wasm_module_inst->memories) {
+ heap_handle = wasm_module_inst->memories[0]->heap_handle;
+ }
+ wasm_get_module_inst_mem_consumption(wasm_module_inst,
+ &module_inst_mem_consps);
+ wasm_get_module_mem_consumption(wasm_module, &module_mem_consps);
+ if (wasm_module_inst->module->aux_stack_top_global_index != (uint32)-1)
+ max_aux_stack_used = wasm_module_inst->e->max_aux_stack_used;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_common->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *aot_module_inst =
+ (AOTModuleInstance *)module_inst_common;
+ AOTModule *aot_module = (AOTModule *)aot_module_inst->module;
+ module_common = (WASMModuleCommon *)aot_module;
+ if (aot_module_inst->memories) {
+ AOTMemoryInstance **memories = aot_module_inst->memories;
+ heap_handle = memories[0]->heap_handle;
+ }
+ aot_get_module_inst_mem_consumption(aot_module_inst,
+ &module_inst_mem_consps);
+ aot_get_module_mem_consumption(aot_module, &module_mem_consps);
+ }
+#endif
+
+ bh_assert(module_common != NULL);
+
+ if (heap_handle) {
+ app_heap_peak_size = gc_get_heap_highmark_size(heap_handle);
+ }
+
+ total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
+ + exec_env->wasm_stack_size + module_mem_consps.total_size
+ + module_inst_mem_consps.total_size;
+
+ os_printf("\nMemory consumption summary (bytes):\n");
+ wasm_runtime_dump_module_mem_consumption(module_common);
+ wasm_runtime_dump_module_inst_mem_consumption(module_inst_common);
+ wasm_runtime_dump_exec_env_mem_consumption(exec_env);
+ os_printf("\nTotal memory consumption of module, module inst and "
+ "exec env: %u\n",
+ total_size);
+ os_printf("Total interpreter stack used: %u\n",
+ exec_env->max_wasm_stack_used);
+
+ if (max_aux_stack_used != (uint32)-1)
+ os_printf("Total auxiliary stack used: %u\n", max_aux_stack_used);
+ else
+ os_printf("Total aux stack used: no enough info to profile\n");
+
+ /*
+ * Report the native stack usage estimation.
+ *
+ * Unlike the aux stack above, we report the amount unused
+ * because we don't know the stack "bottom".
+ *
+ * Note that this is just about what the runtime itself observed.
+ * It doesn't cover host func implementations, signal handlers, etc.
+ */
+ if (exec_env->native_stack_top_min != (void *)UINTPTR_MAX)
+ os_printf("Native stack left: %zd\n",
+ exec_env->native_stack_top_min
+ - exec_env->native_stack_boundary);
+ else
+ os_printf("Native stack left: no enough info to profile\n");
+
+ os_printf("Total app heap used: %u\n", app_heap_peak_size);
+}
+#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
+ || (WASM_ENABLE_MEMORY_TRACING != 0) */
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+void
+wasm_runtime_dump_perf_profiling(WASMModuleInstanceCommon *module_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ wasm_dump_perf_profiling((WASMModuleInstance *)module_inst);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ aot_dump_perf_profiling((AOTModuleInstance *)module_inst);
+ }
+#endif
+}
+#endif
+
+WASMModuleInstanceCommon *
+wasm_runtime_get_module_inst(WASMExecEnv *exec_env)
+{
+ return wasm_exec_env_get_module_inst(exec_env);
+}
+
+void
+wasm_runtime_set_module_inst(WASMExecEnv *exec_env,
+ WASMModuleInstanceCommon *const module_inst)
+{
+ wasm_exec_env_set_module_inst(exec_env, module_inst);
+}
+
+void *
+wasm_runtime_get_function_attachment(WASMExecEnv *exec_env)
+{
+ return exec_env->attachment;
+}
+
+void
+wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data)
+{
+ exec_env->user_data = user_data;
+}
+
+void *
+wasm_runtime_get_user_data(WASMExecEnv *exec_env)
+{
+ return exec_env->user_data;
+}
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+void
+wasm_runtime_access_exce_check_guard_page()
+{
+ if (exec_env_tls && exec_env_tls->handle == os_self_thread()) {
+ uint32 page_size = os_getpagesize();
+ memset(exec_env_tls->exce_check_guard_page, 0, page_size);
+ }
+}
+#endif
+
+WASMType *
+wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
+ uint32 module_type)
+{
+ WASMType *type = NULL;
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_type == Wasm_Module_Bytecode) {
+ WASMFunctionInstance *wasm_func = (WASMFunctionInstance *)function;
+ type = wasm_func->is_import_func ? wasm_func->u.func_import->func_type
+ : wasm_func->u.func->func_type;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_type == Wasm_Module_AoT) {
+ AOTFunctionInstance *aot_func = (AOTFunctionInstance *)function;
+ type = aot_func->is_import_func ? aot_func->u.func_import->func_type
+ : aot_func->u.func.func_type;
+ }
+#endif
+
+ return type;
+}
+
+WASMFunctionInstanceCommon *
+wasm_runtime_lookup_function(WASMModuleInstanceCommon *const 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;
+}
+
+uint32
+wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst)
+{
+ WASMType *type =
+ wasm_runtime_get_function_type(func_inst, module_inst->module_type);
+ bh_assert(type);
+
+ return type->param_count;
+}
+
+uint32
+wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst)
+{
+ WASMType *type =
+ wasm_runtime_get_function_type(func_inst, module_inst->module_type);
+ bh_assert(type);
+
+ return type->result_count;
+}
+
+static uint8
+val_type_to_val_kind(uint8 value_type)
+{
+ switch (value_type) {
+ case VALUE_TYPE_I32:
+ return WASM_I32;
+ case VALUE_TYPE_I64:
+ return WASM_I64;
+ case VALUE_TYPE_F32:
+ return WASM_F32;
+ case VALUE_TYPE_F64:
+ return WASM_F64;
+ case VALUE_TYPE_FUNCREF:
+ return WASM_FUNCREF;
+ case VALUE_TYPE_EXTERNREF:
+ return WASM_ANYREF;
+ default:
+ bh_assert(0);
+ return 0;
+ }
+}
+
+void
+wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst,
+ wasm_valkind_t *param_types)
+{
+ WASMType *type =
+ wasm_runtime_get_function_type(func_inst, module_inst->module_type);
+ uint32 i;
+
+ bh_assert(type);
+
+ for (i = 0; i < type->param_count; i++) {
+ param_types[i] = val_type_to_val_kind(type->types[i]);
+ }
+}
+
+void
+wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst,
+ wasm_valkind_t *result_types)
+{
+ WASMType *type =
+ wasm_runtime_get_function_type(func_inst, module_inst->module_type);
+ uint32 i;
+
+ bh_assert(type);
+
+ for (i = 0; i < type->result_count; i++) {
+ result_types[i] =
+ val_type_to_val_kind(type->types[type->param_count + i]);
+ }
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+/* (uintptr_t)externref -> (uint32)index */
+/* argv -> *ret_argv */
+static bool
+wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function,
+ uint32 *argv, uint32 argc, uint32 **ret_argv,
+ uint32 *ret_argc_param,
+ uint32 *ret_argc_result)
+{
+ uint32 *new_argv = NULL, argv_i = 0, new_argv_i = 0, param_i = 0,
+ result_i = 0;
+ bool need_param_transform = false, need_result_transform = false;
+ uint64 size = 0;
+ WASMType *func_type = wasm_runtime_get_function_type(
+ function, exec_env->module_inst->module_type);
+
+ bh_assert(func_type);
+
+ *ret_argc_param = func_type->param_cell_num;
+ *ret_argc_result = func_type->ret_cell_num;
+ for (param_i = 0; param_i < func_type->param_count; param_i++) {
+ if (VALUE_TYPE_EXTERNREF == func_type->types[param_i]) {
+ need_param_transform = true;
+ }
+ }
+
+ for (result_i = 0; result_i < func_type->result_count; result_i++) {
+ if (VALUE_TYPE_EXTERNREF
+ == func_type->types[func_type->param_count + result_i]) {
+ need_result_transform = true;
+ }
+ }
+
+ if (!need_param_transform && !need_result_transform) {
+ *ret_argv = argv;
+ return true;
+ }
+
+ if (func_type->param_cell_num >= func_type->ret_cell_num) {
+ size = sizeof(uint32) * func_type->param_cell_num;
+ }
+ else {
+ size = sizeof(uint32) * func_type->ret_cell_num;
+ }
+
+ if (!(new_argv = runtime_malloc(size, exec_env->module_inst, NULL, 0))) {
+ return false;
+ }
+
+ if (!need_param_transform) {
+ bh_memcpy_s(new_argv, (uint32)size, argv, (uint32)size);
+ }
+ else {
+ for (param_i = 0; param_i < func_type->param_count && argv_i < argc
+ && new_argv_i < func_type->param_cell_num;
+ param_i++) {
+ uint8 param_type = func_type->types[param_i];
+ if (VALUE_TYPE_EXTERNREF == param_type) {
+ void *externref_obj;
+ uint32 externref_index;
+
+#if UINTPTR_MAX == UINT32_MAX
+ externref_obj = (void *)argv[argv_i];
+#else
+ union {
+ uintptr_t val;
+ uint32 parts[2];
+ } u;
+
+ u.parts[0] = argv[argv_i];
+ u.parts[1] = argv[argv_i + 1];
+ externref_obj = (void *)u.val;
+#endif
+ if (!wasm_externref_obj2ref(exec_env->module_inst,
+ externref_obj, &externref_index)) {
+ wasm_runtime_free(new_argv);
+ return false;
+ }
+
+ new_argv[new_argv_i] = externref_index;
+ argv_i += sizeof(uintptr_t) / sizeof(uint32);
+ new_argv_i++;
+ }
+ else {
+ uint16 param_cell_num = wasm_value_type_cell_num(param_type);
+ uint32 param_size = sizeof(uint32) * param_cell_num;
+ bh_memcpy_s(new_argv + new_argv_i, param_size, argv + argv_i,
+ param_size);
+ argv_i += param_cell_num;
+ new_argv_i += param_cell_num;
+ }
+ }
+ }
+
+ *ret_argv = new_argv;
+ return true;
+}
+
+/* (uintptr_t)externref <- (uint32)index */
+/* argv <- new_argv */
+static bool
+wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function,
+ uint32 *argv, uint32 argc, uint32 *ret_argv)
+{
+ uint32 argv_i = 0, result_i = 0, ret_argv_i = 0;
+ WASMType *func_type;
+
+ bh_assert((argv && ret_argv) || (argc == 0));
+
+ if (argv == ret_argv) {
+ /* no need to transfrom externref results */
+ return true;
+ }
+
+ func_type = wasm_runtime_get_function_type(
+ function, exec_env->module_inst->module_type);
+ bh_assert(func_type);
+
+ for (result_i = 0; result_i < func_type->result_count && argv_i < argc;
+ result_i++) {
+ uint8 result_type = func_type->types[func_type->param_count + result_i];
+ if (result_type == VALUE_TYPE_EXTERNREF) {
+ void *externref_obj;
+#if UINTPTR_MAX != UINT32_MAX
+ union {
+ uintptr_t val;
+ uint32 parts[2];
+ } u;
+#endif
+
+ if (!wasm_externref_ref2obj(argv[argv_i], &externref_obj)) {
+ wasm_runtime_free(argv);
+ return false;
+ }
+
+#if UINTPTR_MAX == UINT32_MAX
+ ret_argv[ret_argv_i] = (uintptr_t)externref_obj;
+#else
+ u.val = (uintptr_t)externref_obj;
+ ret_argv[ret_argv_i] = u.parts[0];
+ ret_argv[ret_argv_i + 1] = u.parts[1];
+#endif
+ argv_i += 1;
+ ret_argv_i += sizeof(uintptr_t) / sizeof(uint32);
+ }
+ else {
+ uint16 result_cell_num = wasm_value_type_cell_num(result_type);
+ uint32 result_size = sizeof(uint32) * result_cell_num;
+ bh_memcpy_s(ret_argv + ret_argv_i, result_size, argv + argv_i,
+ result_size);
+ argv_i += result_cell_num;
+ ret_argv_i += result_cell_num;
+ }
+ }
+
+ wasm_runtime_free(argv);
+ return true;
+}
+#endif
+
+static bool
+clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm)
+{
+#if WASM_ENABLE_LIBC_WASI != 0
+ bool has_exception;
+ char exception[EXCEPTION_BUF_LEN];
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ has_exception = wasm_copy_exception(module_inst, exception);
+ if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) {
+ /* The "wasi proc exit" exception is thrown by native lib to
+ let wasm app exit, which is a normal behavior, we clear
+ the exception here. And just clear the exception of current
+ thread, don't call `wasm_set_exception(module_inst, NULL)`
+ which will clear the exception of all threads. */
+ module_inst->cur_exception[0] = '\0';
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif
+}
+
+bool
+wasm_runtime_call_wasm(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function, uint32 argc,
+ uint32 argv[])
+{
+ bool ret = false;
+ uint32 *new_argv = NULL, param_argc;
+#if WASM_ENABLE_REF_TYPES != 0
+ uint32 result_argc = 0;
+#endif
+
+ if (!wasm_runtime_exec_env_check(exec_env)) {
+ LOG_ERROR("Invalid exec env stack info.");
+ return false;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!wasm_runtime_prepare_call_function(exec_env, function, argv, argc,
+ &new_argv, &param_argc,
+ &result_argc)) {
+ wasm_runtime_set_exception(exec_env->module_inst,
+ "the arguments conversion is failed");
+ return false;
+ }
+#else
+ new_argv = argv;
+ param_argc = argc;
+#endif
+
+#if WASM_ENABLE_INTERP != 0
+ if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
+ ret = wasm_call_function(exec_env, (WASMFunctionInstance *)function,
+ param_argc, new_argv);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (exec_env->module_inst->module_type == Wasm_Module_AoT)
+ ret = aot_call_function(exec_env, (AOTFunctionInstance *)function,
+ param_argc, new_argv);
+#endif
+ if (!ret) {
+ if (clear_wasi_proc_exit_exception(exec_env->module_inst)) {
+ ret = true;
+ }
+ else {
+ if (new_argv != argv) {
+ wasm_runtime_free(new_argv);
+ }
+ return false;
+ }
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!wasm_runtime_finalize_call_function(exec_env, function, new_argv,
+ result_argc, argv)) {
+ wasm_runtime_set_exception(exec_env->module_inst,
+ "the result conversion is failed");
+ return false;
+ }
+#endif
+
+ return ret;
+}
+
+static void
+parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
+{
+ uint32 i, p;
+
+ for (i = 0, p = 0; i < type->param_count; i++) {
+ switch (args[i].kind) {
+ case WASM_I32:
+ out_argv[p++] = args[i].of.i32;
+ break;
+ case WASM_I64:
+ {
+ union {
+ uint64 val;
+ uint32 parts[2];
+ } u;
+ u.val = args[i].of.i64;
+ out_argv[p++] = u.parts[0];
+ out_argv[p++] = u.parts[1];
+ break;
+ }
+ case WASM_F32:
+ {
+ union {
+ float32 val;
+ uint32 part;
+ } u;
+ u.val = args[i].of.f32;
+ out_argv[p++] = u.part;
+ break;
+ }
+ case WASM_F64:
+ {
+ union {
+ float64 val;
+ uint32 parts[2];
+ } u;
+ u.val = args[i].of.f64;
+ out_argv[p++] = u.parts[0];
+ out_argv[p++] = u.parts[1];
+ break;
+ }
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_FUNCREF:
+ {
+ out_argv[p++] = args[i].of.i32;
+ break;
+ }
+ case WASM_ANYREF:
+ {
+#if UINTPTR_MAX == UINT32_MAX
+ out_argv[p++] = args[i].of.foreign;
+#else
+ union {
+ uintptr_t val;
+ uint32 parts[2];
+ } u;
+
+ u.val = (uintptr_t)args[i].of.foreign;
+ out_argv[p++] = u.parts[0];
+ out_argv[p++] = u.parts[1];
+#endif
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+}
+
+static void
+parse_uint32_array_to_results(WASMType *type, uint32 *argv,
+ wasm_val_t *out_results)
+{
+ uint32 i, p;
+
+ for (i = 0, p = 0; i < type->result_count; i++) {
+ switch (type->types[type->param_count + i]) {
+ case VALUE_TYPE_I32:
+ out_results[i].kind = WASM_I32;
+ out_results[i].of.i32 = (int32)argv[p++];
+ break;
+ case VALUE_TYPE_I64:
+ {
+ union {
+ uint64 val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = argv[p++];
+ u.parts[1] = argv[p++];
+ out_results[i].kind = WASM_I64;
+ out_results[i].of.i64 = u.val;
+ break;
+ }
+ case VALUE_TYPE_F32:
+ {
+ union {
+ float32 val;
+ uint32 part;
+ } u;
+ u.part = argv[p++];
+ out_results[i].kind = WASM_F32;
+ out_results[i].of.f32 = u.val;
+ break;
+ }
+ case VALUE_TYPE_F64:
+ {
+ union {
+ float64 val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = argv[p++];
+ u.parts[1] = argv[p++];
+ out_results[i].kind = WASM_F64;
+ out_results[i].of.f64 = u.val;
+ break;
+ }
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ {
+ out_results[i].kind = WASM_I32;
+ out_results[i].of.i32 = (int32)argv[p++];
+ break;
+ }
+ case VALUE_TYPE_EXTERNREF:
+ {
+#if UINTPTR_MAX == UINT32_MAX
+ out_results[i].kind = WASM_ANYREF;
+ out_results[i].of.foreign = (uintptr_t)argv[p++];
+#else
+ union {
+ uintptr_t val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = argv[p++];
+ u.parts[1] = argv[p++];
+ out_results[i].kind = WASM_ANYREF;
+ out_results[i].of.foreign = u.val;
+#endif
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+}
+
+bool
+wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function,
+ uint32 num_results, wasm_val_t results[],
+ uint32 num_args, wasm_val_t args[])
+{
+ uint32 argc, argv_buf[16] = { 0 }, *argv = argv_buf, cell_num, module_type;
+#if WASM_ENABLE_REF_TYPES != 0
+ uint32 i, param_size_in_double_world = 0, result_size_in_double_world = 0;
+#endif
+ uint64 total_size;
+ WASMType *type;
+ bool ret = false;
+
+ module_type = exec_env->module_inst->module_type;
+ type = wasm_runtime_get_function_type(function, module_type);
+
+ if (!type) {
+ LOG_ERROR("Function type get failed, WAMR Interpreter and AOT must be "
+ "enabled at least one.");
+ goto fail1;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ for (i = 0; i < type->param_count; i++) {
+ param_size_in_double_world +=
+ wasm_value_type_cell_num_outside(type->types[i]);
+ }
+ for (i = 0; i < type->result_count; i++) {
+ result_size_in_double_world += wasm_value_type_cell_num_outside(
+ type->types[type->param_count + i]);
+ }
+ argc = param_size_in_double_world;
+ cell_num = (argc >= result_size_in_double_world)
+ ? argc
+ : result_size_in_double_world;
+#else
+ argc = type->param_cell_num;
+ cell_num = (argc > type->ret_cell_num) ? argc : type->ret_cell_num;
+#endif
+
+ if (num_results != type->result_count) {
+ LOG_ERROR(
+ "The result value number does not match the function declaration.");
+ goto fail1;
+ }
+
+ if (num_args != type->param_count) {
+ LOG_ERROR("The argument value number does not match the function "
+ "declaration.");
+ goto fail1;
+ }
+
+ total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
+ if (total_size > sizeof(argv_buf)) {
+ if (!(argv =
+ runtime_malloc(total_size, exec_env->module_inst, NULL, 0))) {
+ goto fail1;
+ }
+ }
+
+ parse_args_to_uint32_array(type, args, argv);
+ if (!(ret = wasm_runtime_call_wasm(exec_env, function, argc, argv)))
+ goto fail2;
+
+ parse_uint32_array_to_results(type, argv, results);
+
+fail2:
+ if (argv != argv_buf)
+ wasm_runtime_free(argv);
+fail1:
+ return ret;
+}
+
+bool
+wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function,
+ uint32 num_results, wasm_val_t results[],
+ uint32 num_args, ...)
+{
+ wasm_val_t args_buf[8] = { 0 }, *args = args_buf;
+ WASMType *type = NULL;
+ bool ret = false;
+ uint64 total_size;
+ uint32 i = 0, module_type;
+ va_list vargs;
+
+ module_type = exec_env->module_inst->module_type;
+ type = wasm_runtime_get_function_type(function, module_type);
+
+ if (!type) {
+ LOG_ERROR("Function type get failed, WAMR Interpreter and AOT "
+ "must be enabled at least one.");
+ goto fail1;
+ }
+
+ if (num_args != type->param_count) {
+ LOG_ERROR("The argument value number does not match the "
+ "function declaration.");
+ goto fail1;
+ }
+
+ total_size = sizeof(wasm_val_t) * (uint64)num_args;
+ if (total_size > sizeof(args_buf)) {
+ if (!(args =
+ runtime_malloc(total_size, exec_env->module_inst, NULL, 0))) {
+ goto fail1;
+ }
+ }
+
+ va_start(vargs, num_args);
+ for (i = 0; i < num_args; i++) {
+ switch (type->types[i]) {
+ case VALUE_TYPE_I32:
+ args[i].kind = WASM_I32;
+ args[i].of.i32 = va_arg(vargs, uint32);
+ break;
+ case VALUE_TYPE_I64:
+ args[i].kind = WASM_I64;
+ args[i].of.i64 = va_arg(vargs, uint64);
+ break;
+ case VALUE_TYPE_F32:
+ args[i].kind = WASM_F32;
+ args[i].of.f32 = (float32)va_arg(vargs, float64);
+ break;
+ case VALUE_TYPE_F64:
+ args[i].kind = WASM_F64;
+ args[i].of.f64 = va_arg(vargs, float64);
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ {
+ args[i].kind = WASM_FUNCREF;
+ args[i].of.i32 = va_arg(vargs, uint32);
+ break;
+ }
+ case VALUE_TYPE_EXTERNREF:
+ {
+ args[i].kind = WASM_ANYREF;
+ args[i].of.foreign = va_arg(vargs, uintptr_t);
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+ va_end(vargs);
+
+ ret = wasm_runtime_call_wasm_a(exec_env, function, num_results, results,
+ num_args, args);
+ if (args != args_buf)
+ wasm_runtime_free(args);
+
+fail1:
+ return ret;
+}
+
+bool
+wasm_runtime_create_exec_env_singleton(
+ WASMModuleInstanceCommon *module_inst_comm)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+ WASMExecEnv *exec_env = NULL;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ if (module_inst->exec_env_singleton) {
+ return true;
+ }
+
+ exec_env = wasm_exec_env_create(module_inst_comm,
+ module_inst->default_wasm_stack_size);
+ if (exec_env)
+ module_inst->exec_env_singleton = exec_env;
+
+ return exec_env ? true : false;
+}
+
+WASMExecEnv *
+wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+
+ if (!module_inst->exec_env_singleton) {
+ wasm_runtime_create_exec_env_singleton(module_inst_comm);
+ }
+ return module_inst->exec_env_singleton;
+}
+
+void
+wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
+{
+ WASMExecEnv *exec_env = NULL;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *node =
+ wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module);
+ if (node)
+ os_mutex_lock(&node->shared_mem_lock);
+#endif
+ if (exception) {
+ snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
+ "Exception: %s", exception);
+ }
+ else {
+ module_inst->cur_exception[0] = '\0';
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_unlock(&node->shared_mem_lock);
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ exec_env =
+ wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
+ if (exec_env) {
+ wasm_cluster_spread_exception(exec_env, exception ? false : true);
+ }
+#else
+ (void)exec_env;
+#endif
+}
+
+/* clang-format off */
+static const char *exception_msgs[] = {
+ "unreachable", /* EXCE_UNREACHABLE */
+ "allocate memory failed", /* EXCE_OUT_OF_MEMORY */
+ "out of bounds memory access", /* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
+ "integer overflow", /* EXCE_INTEGER_OVERFLOW */
+ "integer divide by zero", /* EXCE_INTEGER_DIVIDE_BY_ZERO */
+ "invalid conversion to integer", /* EXCE_INVALID_CONVERSION_TO_INTEGER */
+ "indirect call type mismatch", /* EXCE_INVALID_FUNCTION_TYPE_INDEX */
+ "invalid function index", /* EXCE_INVALID_FUNCTION_INDEX */
+ "undefined element", /* EXCE_UNDEFINED_ELEMENT */
+ "uninitialized element", /* EXCE_UNINITIALIZED_ELEMENT */
+ "failed to call unlinked import function", /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
+ "native stack overflow", /* EXCE_NATIVE_STACK_OVERFLOW */
+ "unaligned atomic", /* EXCE_UNALIGNED_ATOMIC */
+ "wasm auxiliary stack overflow", /* EXCE_AUX_STACK_OVERFLOW */
+ "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
+ "out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
+ "wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
+ "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
+ "", /* EXCE_ALREADY_THROWN */
+};
+/* clang-format on */
+
+void
+wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id)
+{
+ if (id < EXCE_NUM)
+ wasm_set_exception(module_inst, exception_msgs[id]);
+ else
+ wasm_set_exception(module_inst, "unknown exception");
+}
+
+const char *
+wasm_get_exception(WASMModuleInstance *module_inst)
+{
+ if (module_inst->cur_exception[0] == '\0')
+ return NULL;
+ else
+ return module_inst->cur_exception;
+}
+
+bool
+wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
+{
+ bool has_exception = false;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *node =
+ wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module);
+ if (node)
+ os_mutex_lock(&node->shared_mem_lock);
+#endif
+ if (module_inst->cur_exception[0] != '\0') {
+ /* NULL is passed if the caller is not interested in getting the
+ * exception content, but only in knowing if an exception has been
+ * raised
+ */
+ if (exception_buf != NULL)
+ bh_memcpy_s(exception_buf, sizeof(module_inst->cur_exception),
+ module_inst->cur_exception,
+ sizeof(module_inst->cur_exception));
+ has_exception = true;
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (node)
+ os_mutex_unlock(&node->shared_mem_lock);
+#endif
+
+ return has_exception;
+}
+
+void
+wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst_comm,
+ const char *exception)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ wasm_set_exception(module_inst, exception);
+}
+
+const char *
+wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst_comm)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ return wasm_get_exception(module_inst);
+}
+
+bool
+wasm_runtime_copy_exception(WASMModuleInstanceCommon *module_inst_comm,
+ char *exception_buf)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ return wasm_copy_exception(module_inst, exception_buf);
+}
+
+void
+wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
+{
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ wasm_runtime_set_exception(module_inst_comm, NULL);
+}
+
+void
+wasm_runtime_set_custom_data_internal(
+ WASMModuleInstanceCommon *module_inst_comm, void *custom_data)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ module_inst->custom_data = custom_data;
+}
+
+void
+wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst,
+ void *custom_data)
+{
+#if WASM_ENABLE_THREAD_MGR != 0
+ wasm_cluster_spread_custom_data(module_inst, custom_data);
+#else
+ wasm_runtime_set_custom_data_internal(module_inst, custom_data);
+#endif
+}
+
+void *
+wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst_comm)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ return module_inst->custom_data;
+}
+
+uint32
+wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst,
+ WASMExecEnv *exec_env, uint32 size,
+ void **p_native_addr)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode)
+ return wasm_module_malloc_internal((WASMModuleInstance *)module_inst,
+ exec_env, size, p_native_addr);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT)
+ return aot_module_malloc_internal((AOTModuleInstance *)module_inst,
+ exec_env, size, p_native_addr);
+#endif
+ return 0;
+}
+
+uint32
+wasm_runtime_module_realloc_internal(WASMModuleInstanceCommon *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr,
+ uint32 size, void **p_native_addr)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode)
+ return wasm_module_realloc_internal((WASMModuleInstance *)module_inst,
+ exec_env, ptr, size, p_native_addr);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT)
+ return aot_module_realloc_internal((AOTModuleInstance *)module_inst,
+ exec_env, ptr, size, p_native_addr);
+#endif
+ return 0;
+}
+
+void
+wasm_runtime_module_free_internal(WASMModuleInstanceCommon *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ wasm_module_free_internal((WASMModuleInstance *)module_inst, exec_env,
+ ptr);
+ return;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ aot_module_free_internal((AOTModuleInstance *)module_inst, exec_env,
+ ptr);
+ return;
+ }
+#endif
+}
+
+uint32
+wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size,
+ void **p_native_addr)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode)
+ return wasm_module_malloc((WASMModuleInstance *)module_inst, size,
+ p_native_addr);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT)
+ return aot_module_malloc((AOTModuleInstance *)module_inst, size,
+ p_native_addr);
+#endif
+ return 0;
+}
+
+uint32
+wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr,
+ uint32 size, void **p_native_addr)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode)
+ return wasm_module_realloc((WASMModuleInstance *)module_inst, ptr, size,
+ p_native_addr);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT)
+ return aot_module_realloc((AOTModuleInstance *)module_inst, ptr, size,
+ p_native_addr);
+#endif
+ return 0;
+}
+
+void
+wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 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
+}
+
+uint32
+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;
+}
+
+#if WASM_ENABLE_LIBC_WASI != 0
+
+static WASIArguments *
+get_wasi_args_from_module(wasm_module_t module)
+{
+ 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
+
+ return wasi_args;
+}
+
+void
+wasm_runtime_set_wasi_args_ex(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, char *argv[], int argc,
+ int stdinfd, int stdoutfd, int stderrfd)
+{
+ WASIArguments *wasi_args = get_wasi_args_from_module(module);
+
+ bh_assert(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 = (uint32)argc;
+ wasi_args->stdio[0] = stdinfd;
+ wasi_args->stdio[1] = stdoutfd;
+ wasi_args->stdio[2] = stderrfd;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+#if WASM_ENABLE_INTERP != 0
+ if (module->module_type == Wasm_Module_Bytecode) {
+ wasm_propagate_wasi_args((WASMModule *)module);
+ }
+#endif
+#endif
+}
+
+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, char *argv[], int argc)
+{
+ wasm_runtime_set_wasi_args_ex(module, dir_list, dir_count, map_dir_list,
+ map_dir_count, env_list, env_count, argv,
+ argc, -1, -1, -1);
+}
+
+void
+wasm_runtime_set_wasi_addr_pool(wasm_module_t module, const char *addr_pool[],
+ uint32 addr_pool_size)
+{
+ WASIArguments *wasi_args = get_wasi_args_from_module(module);
+
+ if (wasi_args) {
+ wasi_args->addr_pool = addr_pool;
+ wasi_args->addr_count = addr_pool_size;
+ }
+}
+
+void
+wasm_runtime_set_wasi_ns_lookup_pool(wasm_module_t module,
+ const char *ns_lookup_pool[],
+ uint32 ns_lookup_pool_size)
+{
+ WASIArguments *wasi_args = get_wasi_args_from_module(module);
+
+ if (wasi_args) {
+ wasi_args->ns_lookup_pool = ns_lookup_pool;
+ wasi_args->ns_lookup_count = ns_lookup_pool_size;
+ }
+}
+
+#if WASM_ENABLE_UVWASI == 0
+static bool
+copy_string_array(const char *array[], uint32 array_size, char **buf_ptr,
+ char ***list_ptr, uint64 *out_buf_size)
+{
+ uint64 buf_size = 0, total_size;
+ uint32 buf_offset = 0, i;
+ char *buf = NULL, **list = NULL;
+
+ for (i = 0; i < array_size; i++)
+ buf_size += strlen(array[i]) + 1;
+
+ /* We add +1 to generate null-terminated array of strings */
+ total_size = sizeof(char *) * ((uint64)array_size + 1);
+ if (total_size >= UINT32_MAX
+ || (total_size > 0 && !(list = wasm_runtime_malloc((uint32)total_size)))
+ || buf_size >= UINT32_MAX
+ || (buf_size > 0 && !(buf = wasm_runtime_malloc((uint32)buf_size)))) {
+
+ if (buf)
+ wasm_runtime_free(buf);
+ if (list)
+ wasm_runtime_free(list);
+ return false;
+ }
+
+ for (i = 0; i < array_size; i++) {
+ list[i] = buf + buf_offset;
+ bh_strcpy_s(buf + buf_offset, (uint32)buf_size - buf_offset, array[i]);
+ buf_offset += (uint32)(strlen(array[i]) + 1);
+ }
+ list[array_size] = NULL;
+
+ *list_ptr = list;
+ *buf_ptr = buf;
+ if (out_buf_size)
+ *out_buf_size = buf_size;
+
+ return true;
+}
+
+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 *addr_pool[], uint32 addr_pool_size,
+ const char *ns_lookup_pool[], uint32 ns_lookup_pool_size,
+ char *argv[], uint32 argc, int stdinfd, int stdoutfd,
+ int stderrfd, char *error_buf, uint32 error_buf_size)
+{
+ WASIContext *wasi_ctx;
+ char *argv_buf = NULL;
+ char **argv_list = NULL;
+ char *env_buf = NULL;
+ char **env_list = NULL;
+ char *ns_lookup_buf = NULL;
+ char **ns_lookup_list = NULL;
+ uint64 argv_buf_size = 0, env_buf_size = 0;
+ struct fd_table *curfds = NULL;
+ struct fd_prestats *prestats = NULL;
+ struct argv_environ_values *argv_environ = NULL;
+ struct addr_pool *apool = NULL;
+ bool fd_table_inited = false, fd_prestats_inited = false;
+ bool argv_environ_inited = false;
+ bool addr_pool_inited = false;
+ __wasi_fd_t wasm_fd = 3;
+ int32 raw_fd;
+ char *path, resolved_path[PATH_MAX];
+ uint32 i;
+
+ if (!(wasi_ctx = runtime_malloc(sizeof(WASIContext), NULL, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+ wasm_runtime_set_wasi_ctx(module_inst, wasi_ctx);
+
+ /* process argv[0], trip the path and suffix, only keep the program name
+ */
+ if (!copy_string_array((const char **)argv, argc, &argv_buf, &argv_list,
+ &argv_buf_size)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: allocate memory failed");
+ goto fail;
+ }
+
+ if (!copy_string_array(env, env_count, &env_buf, &env_list,
+ &env_buf_size)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: allocate memory failed");
+ goto fail;
+ }
+
+ if (!(curfds = wasm_runtime_malloc(sizeof(struct fd_table)))
+ || !(prestats = wasm_runtime_malloc(sizeof(struct fd_prestats)))
+ || !(argv_environ =
+ wasm_runtime_malloc(sizeof(struct argv_environ_values)))
+ || !(apool = wasm_runtime_malloc(sizeof(struct addr_pool)))) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: allocate memory failed");
+ goto fail;
+ }
+
+ if (!fd_table_init(curfds)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: "
+ "init fd table failed");
+ goto fail;
+ }
+ fd_table_inited = true;
+
+ if (!fd_prestats_init(prestats)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: "
+ "init fd prestats failed");
+ goto fail;
+ }
+ fd_prestats_inited = true;
+
+ if (!argv_environ_init(argv_environ, argv_buf, argv_buf_size, argv_list,
+ argc, env_buf, env_buf_size, env_list, env_count)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: "
+ "init argument environment failed");
+ goto fail;
+ }
+ argv_environ_inited = true;
+
+ if (!addr_pool_init(apool)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: "
+ "init the address pool failed");
+ goto fail;
+ }
+ addr_pool_inited = true;
+
+ /* Prepopulate curfds with stdin, stdout, and stderr file descriptors.
+ *
+ * If -1 is given, use STDIN_FILENO (0), STDOUT_FILENO (1),
+ * STDERR_FILENO (2) respectively.
+ */
+ if (!fd_table_insert_existing(curfds, 0, (stdinfd != -1) ? stdinfd : 0)
+ || !fd_table_insert_existing(curfds, 1, (stdoutfd != -1) ? stdoutfd : 1)
+ || !fd_table_insert_existing(curfds, 2,
+ (stderrfd != -1) ? stderrfd : 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);
+ }
+
+ /* addr_pool(textual) -> apool */
+ for (i = 0; i < addr_pool_size; i++) {
+ char *cp, *address, *mask;
+ bool ret = false;
+
+ cp = bh_strdup(addr_pool[i]);
+ if (!cp) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: copy address failed");
+ goto fail;
+ }
+
+ address = strtok(cp, "/");
+ mask = strtok(NULL, "/");
+
+ ret = addr_pool_insert(apool, address, (uint8)(mask ? atoi(mask) : 0));
+ wasm_runtime_free(cp);
+ if (!ret) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: store address failed");
+ goto fail;
+ }
+ }
+
+ if (!copy_string_array(ns_lookup_pool, ns_lookup_pool_size, &ns_lookup_buf,
+ &ns_lookup_list, NULL)) {
+ set_error_buf(error_buf, error_buf_size,
+ "Init wasi environment failed: allocate memory failed");
+ goto fail;
+ }
+
+ wasi_ctx->curfds = curfds;
+ wasi_ctx->prestats = prestats;
+ wasi_ctx->argv_environ = argv_environ;
+ wasi_ctx->addr_pool = apool;
+ wasi_ctx->argv_buf = argv_buf;
+ wasi_ctx->argv_list = argv_list;
+ wasi_ctx->env_buf = env_buf;
+ wasi_ctx->env_list = env_list;
+ wasi_ctx->ns_lookup_buf = ns_lookup_buf;
+ wasi_ctx->ns_lookup_list = ns_lookup_list;
+
+ return true;
+
+fail:
+ if (argv_environ_inited)
+ argv_environ_destroy(argv_environ);
+ if (fd_prestats_inited)
+ fd_prestats_destroy(prestats);
+ if (fd_table_inited)
+ fd_table_destroy(curfds);
+ if (addr_pool_inited)
+ addr_pool_destroy(apool);
+ if (curfds)
+ wasm_runtime_free(curfds);
+ if (prestats)
+ wasm_runtime_free(prestats);
+ if (argv_environ)
+ wasm_runtime_free(argv_environ);
+ if (apool)
+ wasm_runtime_free(apool);
+ if (argv_buf)
+ wasm_runtime_free(argv_buf);
+ if (argv_list)
+ wasm_runtime_free(argv_list);
+ if (env_buf)
+ wasm_runtime_free(env_buf);
+ if (env_list)
+ wasm_runtime_free(env_list);
+ if (ns_lookup_buf)
+ wasm_runtime_free(ns_lookup_buf);
+ if (ns_lookup_list)
+ wasm_runtime_free(ns_lookup_list);
+ return false;
+}
+#else /* else of WASM_ENABLE_UVWASI == 0 */
+static void *
+wasm_uvwasi_malloc(size_t size, void *mem_user_data)
+{
+ return runtime_malloc(size, NULL, NULL, 0);
+ (void)mem_user_data;
+}
+
+static void
+wasm_uvwasi_free(void *ptr, void *mem_user_data)
+{
+ if (ptr)
+ wasm_runtime_free(ptr);
+ (void)mem_user_data;
+}
+
+static void *
+wasm_uvwasi_calloc(size_t nmemb, size_t size, void *mem_user_data)
+{
+ uint64 total_size = (uint64)nmemb * size;
+ return runtime_malloc(total_size, NULL, NULL, 0);
+ (void)mem_user_data;
+}
+
+static void *
+wasm_uvwasi_realloc(void *ptr, size_t size, void *mem_user_data)
+{
+ if (size >= UINT32_MAX) {
+ return NULL;
+ }
+ return wasm_runtime_realloc(ptr, (uint32)size);
+}
+
+/* clang-format off */
+static uvwasi_mem_t uvwasi_allocator = {
+ .mem_user_data = 0,
+ .malloc = wasm_uvwasi_malloc,
+ .free = wasm_uvwasi_free,
+ .calloc = wasm_uvwasi_calloc,
+ .realloc = wasm_uvwasi_realloc
+};
+/* clang-format on */
+
+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 *addr_pool[], uint32 addr_pool_size,
+ const char *ns_lookup_pool[], uint32 ns_lookup_pool_size,
+ char *argv[], uint32 argc, int stdinfd, int stdoutfd,
+ int stderrfd, char *error_buf, uint32 error_buf_size)
+{
+ WASIContext *ctx;
+ uvwasi_t *uvwasi;
+ uvwasi_options_t init_options;
+ const char **envp = NULL;
+ uint64 total_size;
+ uint32 i;
+ bool ret = false;
+
+ ctx = runtime_malloc(sizeof(*ctx), module_inst, error_buf, error_buf_size);
+ if (!ctx)
+ return false;
+ uvwasi = &ctx->uvwasi;
+
+ /* Setup the initialization options */
+ uvwasi_options_init(&init_options);
+ init_options.allocator = &uvwasi_allocator;
+ init_options.argc = argc;
+ init_options.argv = (const char **)argv;
+ init_options.in = (stdinfd != -1) ? (uvwasi_fd_t)stdinfd : init_options.in;
+ init_options.out =
+ (stdoutfd != -1) ? (uvwasi_fd_t)stdoutfd : init_options.out;
+ init_options.err =
+ (stderrfd != -1) ? (uvwasi_fd_t)stderrfd : init_options.err;
+
+ if (dir_count > 0) {
+ init_options.preopenc = dir_count;
+
+ total_size = sizeof(uvwasi_preopen_t) * (uint64)init_options.preopenc;
+ init_options.preopens = (uvwasi_preopen_t *)runtime_malloc(
+ total_size, module_inst, error_buf, error_buf_size);
+ if (init_options.preopens == NULL)
+ goto fail;
+
+ for (i = 0; i < init_options.preopenc; i++) {
+ init_options.preopens[i].real_path = dir_list[i];
+ init_options.preopens[i].mapped_path =
+ (i < map_dir_count) ? map_dir_list[i] : dir_list[i];
+ }
+ }
+
+ if (env_count > 0) {
+ total_size = sizeof(char *) * (uint64)(env_count + 1);
+ envp =
+ runtime_malloc(total_size, module_inst, error_buf, error_buf_size);
+ if (envp == NULL)
+ goto fail;
+
+ for (i = 0; i < env_count; i++) {
+ envp[i] = env[i];
+ }
+ envp[env_count] = NULL;
+ init_options.envp = envp;
+ }
+
+ if (UVWASI_ESUCCESS != uvwasi_init(uvwasi, &init_options)) {
+ set_error_buf(error_buf, error_buf_size, "uvwasi init failed");
+ goto fail;
+ }
+
+ wasm_runtime_set_wasi_ctx(module_inst, ctx);
+
+ ret = true;
+
+fail:
+ if (envp)
+ wasm_runtime_free((void *)envp);
+
+ if (init_options.preopens)
+ wasm_runtime_free(init_options.preopens);
+
+ if (!ret && uvwasi)
+ wasm_runtime_free(uvwasi);
+
+ return ret;
+}
+#endif /* end of WASM_ENABLE_UVWASI */
+
+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->import_wasi_api)
+ return true;
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT
+ && ((AOTModule *)((AOTModuleInstance *)module_inst)->module)
+ ->import_wasi_api)
+ 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;
+ AOTFunctionInstance *export_funcs =
+ (AOTFunctionInstance *)aot_inst->export_functions;
+ for (i = 0; i < aot_inst->export_func_count; i++) {
+ if (!strcmp(export_funcs[i].func_name, "_start")) {
+ AOTFuncType *func_type = export_funcs[i].u.func.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 *)&export_funcs[i];
+ }
+ }
+ return NULL;
+ }
+#endif /* end of WASM_ENABLE_AOT */
+
+ return NULL;
+}
+
+#if WASM_ENABLE_UVWASI == 0
+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);
+ wasm_runtime_free(wasi_ctx->argv_environ);
+ }
+ if (wasi_ctx->curfds) {
+ fd_table_destroy(wasi_ctx->curfds);
+ wasm_runtime_free(wasi_ctx->curfds);
+ }
+ if (wasi_ctx->prestats) {
+ fd_prestats_destroy(wasi_ctx->prestats);
+ wasm_runtime_free(wasi_ctx->prestats);
+ }
+ if (wasi_ctx->addr_pool) {
+ addr_pool_destroy(wasi_ctx->addr_pool);
+ wasm_runtime_free(wasi_ctx->addr_pool);
+ }
+ if (wasi_ctx->argv_buf)
+ wasm_runtime_free(wasi_ctx->argv_buf);
+ if (wasi_ctx->argv_list)
+ wasm_runtime_free(wasi_ctx->argv_list);
+ if (wasi_ctx->env_buf)
+ wasm_runtime_free(wasi_ctx->env_buf);
+ if (wasi_ctx->env_list)
+ wasm_runtime_free(wasi_ctx->env_list);
+ if (wasi_ctx->ns_lookup_buf)
+ wasm_runtime_free(wasi_ctx->ns_lookup_buf);
+ if (wasi_ctx->ns_lookup_list)
+ wasm_runtime_free(wasi_ctx->ns_lookup_list);
+
+ wasm_runtime_free(wasi_ctx);
+ }
+}
+#else
+void
+wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst)
+{
+ WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+
+ if (wasi_ctx) {
+ uvwasi_destroy(&wasi_ctx->uvwasi);
+ wasm_runtime_free(wasi_ctx);
+ }
+}
+#endif
+
+uint32_t
+wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
+{
+ WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+#if WASM_ENABLE_THREAD_MGR != 0
+ WASMCluster *cluster;
+ WASMExecEnv *exec_env;
+
+ exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
+ if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) {
+ /**
+ * The main thread may exit earlier than other threads, and
+ * the exit_code of wasi_ctx may be changed by other thread
+ * when it runs into wasi_proc_exit, here we wait until all
+ * other threads exit to avoid getting invalid exit_code.
+ */
+ wasm_cluster_wait_for_all_except_self(cluster, exec_env);
+ }
+#endif
+ return wasi_ctx->exit_code;
+}
+
+WASIContext *
+wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ return module_inst->wasi_ctx;
+}
+
+void
+wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
+ WASIContext *wasi_ctx)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ module_inst->wasi_ctx = wasi_ctx;
+}
+#endif /* end of WASM_ENABLE_LIBC_WASI */
+
+WASMModuleCommon *
+wasm_exec_env_get_module(WASMExecEnv *exec_env)
+{
+ WASMModuleInstanceCommon *module_inst_comm =
+ wasm_runtime_get_module_inst(exec_env);
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+ bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+ || module_inst_comm->module_type == Wasm_Module_AoT);
+ return (WASMModuleCommon *)module_inst->module;
+}
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+const uint8 *
+wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
+ const char *name, uint32 *len)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_comm->module_type == Wasm_Module_Bytecode)
+ return wasm_loader_get_custom_section((WASMModule *)module_comm, name,
+ len);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_comm->module_type == Wasm_Module_AoT)
+ return aot_get_custom_section((AOTModule *)module_comm, name, len);
+#endif
+ return NULL;
+}
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
+
+static union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+bool
+wasm_runtime_register_natives(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols)
+{
+ return wasm_native_register_natives(module_name, native_symbols,
+ n_native_symbols);
+}
+
+bool
+wasm_runtime_register_natives_raw(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols)
+{
+ return wasm_native_register_natives_raw(module_name, native_symbols,
+ n_native_symbols);
+}
+
+bool
+wasm_runtime_unregister_natives(const char *module_name,
+ NativeSymbol *native_symbols)
+{
+ return wasm_native_unregister_natives(module_name, native_symbols);
+}
+
+bool
+wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type, const char *signature,
+ void *attachment, uint32 *argv, uint32 argc,
+ uint32 *argv_ret)
+{
+ WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
+ typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *);
+ NativeRawFuncPtr invokeNativeRaw = (NativeRawFuncPtr)func_ptr;
+ uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size;
+ uint32 *argv_src = argv, i, argc1, ptr_len;
+ uint32 arg_i32;
+ bool ret = false;
+
+ argc1 = func_type->param_count;
+ if (argc1 > sizeof(argv_buf) / sizeof(uint64)) {
+ size = sizeof(uint64) * (uint64)argc1;
+ if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL,
+ 0))) {
+ return false;
+ }
+ }
+
+ argv_dst = argv1;
+
+ /* Traverse secondly to fill in each argument */
+ for (i = 0; i < func_type->param_count; i++, argv_dst++) {
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ {
+ *(uint32 *)argv_dst = arg_i32 = *argv_src++;
+ if (signature) {
+ if (signature[i + 1] == '*') {
+ /* param is a pointer */
+ if (signature[i + 2] == '~')
+ /* pointer with length followed */
+ ptr_len = *argv_src;
+ else
+ /* pointer without length followed */
+ ptr_len = 1;
+
+ if (!wasm_runtime_validate_app_addr(module, arg_i32,
+ ptr_len))
+ goto fail;
+
+ *(uintptr_t *)argv_dst =
+ (uintptr_t)wasm_runtime_addr_app_to_native(module,
+ arg_i32);
+ }
+ else if (signature[i + 1] == '$') {
+ /* param is a string */
+ if (!wasm_runtime_validate_app_str_addr(module,
+ arg_i32))
+ goto fail;
+
+ *(uintptr_t *)argv_dst =
+ (uintptr_t)wasm_runtime_addr_app_to_native(module,
+ arg_i32);
+ }
+ }
+ break;
+ }
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ bh_memcpy_s(argv_dst, sizeof(uint64), argv_src,
+ sizeof(uint32) * 2);
+ argv_src += 2;
+ break;
+ case VALUE_TYPE_F32:
+ *(float32 *)argv_dst = *(float32 *)argv_src++;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ uint32 externref_idx = *argv_src++;
+
+ void *externref_obj;
+
+ if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
+ goto fail;
+
+ bh_memcpy_s(argv_dst, sizeof(uintptr_t), argv_src,
+ sizeof(uintptr_t));
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ exec_env->attachment = attachment;
+ invokeNativeRaw(exec_env, argv1);
+ exec_env->attachment = NULL;
+
+ if (func_type->result_count > 0) {
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ argv_ret[0] = *(uint32 *)argv1;
+ break;
+ case VALUE_TYPE_F32:
+ *(float32 *)argv_ret = *(float32 *)argv1;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1,
+ sizeof(uint64));
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ uint32 externref_idx;
+ uint64 externref_obj;
+
+ bh_memcpy_s(&externref_obj, sizeof(uint64), argv1,
+ sizeof(uint64));
+
+ if (!wasm_externref_obj2ref(exec_env->module_inst,
+ (void *)(uintptr_t)externref_obj,
+ &externref_idx))
+ goto fail;
+ argv_ret[0] = externref_idx;
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ ret = !wasm_runtime_copy_exception(module, NULL);
+
+fail:
+ if (argv1 != argv_buf)
+ wasm_runtime_free(argv1);
+ return ret;
+}
+
+/**
+ * Implementation of wasm_runtime_invoke_native()
+ */
+
+/* The invoke native implementation on ARM platform with VFP co-processor */
+#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) \
+ || defined(BUILD_TARGET_RISCV32_ILP32D) \
+ || defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
+typedef void (*GenericFunctionPointer)();
+void
+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 volatile Float64FuncPtr invokeNative_Float64 =
+ (Float64FuncPtr)(uintptr_t)invokeNative;
+static volatile Float32FuncPtr invokeNative_Float32 =
+ (Float32FuncPtr)(uintptr_t)invokeNative;
+static volatile Int64FuncPtr invokeNative_Int64 =
+ (Int64FuncPtr)(uintptr_t)invokeNative;
+static volatile Int32FuncPtr invokeNative_Int32 =
+ (Int32FuncPtr)(uintptr_t)invokeNative;
+static volatile VoidFuncPtr invokeNative_Void =
+ (VoidFuncPtr)(uintptr_t)invokeNative;
+
+#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
+#define MAX_REG_INTS 4
+#define MAX_REG_FLOATS 16
+#else
+#define MAX_REG_INTS 8
+#define MAX_REG_FLOATS 8
+#endif
+
+bool
+wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type, const char *signature,
+ void *attachment, uint32 *argv, uint32 argc,
+ uint32 *argv_ret)
+{
+ WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
+ /* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args
+ */
+ uint32 argv_buf[32], *argv1 = argv_buf, *ints, *stacks, size;
+ uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0;
+ uint32 arg_i32, ptr_len;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
+ bool ret = false;
+#if WASM_ENABLE_REF_TYPES != 0
+ bool is_aot_func = (NULL == signature);
+#endif
+#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
+ uint32 *fps;
+ int n_fps = 0;
+#else
+#define fps ints
+#define n_fps n_ints
+#endif
+
+ 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 WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ if (n_ints < MAX_REG_INTS)
+ n_ints++;
+ else
+ n_stacks++;
+ break;
+ case VALUE_TYPE_I64:
+ if (n_ints < MAX_REG_INTS - 1) {
+#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
+ /* 64-bit data must be 8 bytes aligned in arm */
+ if (n_ints & 1)
+ n_ints++;
+#endif
+ n_ints += 2;
+ }
+#if defined(BUILD_TARGET_RISCV32_ILP32) \
+ || defined(BUILD_TARGET_RISCV32_ILP32D) || defined(BUILD_TARGET_ARC)
+ /* part in register, part in stack */
+ else if (n_ints == MAX_REG_INTS - 1) {
+ n_ints++;
+ n_stacks++;
+ }
+#endif
+ else {
+ /* 64-bit data in stack must be 8 bytes aligned
+ in arm and riscv32 */
+#if !defined(BUILD_TARGET_ARC)
+ if (n_stacks & 1)
+ n_stacks++;
+#endif
+ n_stacks += 2;
+ }
+ break;
+#if !defined(BUILD_TARGET_RISCV32_ILP32D)
+ 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) {
+#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
+ /* 64-bit data must be 8 bytes aligned in arm */
+ if (n_fps & 1)
+ n_fps++;
+#endif
+ n_fps += 2;
+ }
+#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
+ else if (n_fps == MAX_REG_FLOATS - 1) {
+ n_fps++;
+ n_stacks++;
+ }
+#endif
+ else {
+ /* 64-bit data in stack must be 8 bytes aligned
+ in arm and riscv32 */
+#if !defined(BUILD_TARGET_ARC)
+ if (n_stacks & 1)
+ n_stacks++;
+#endif
+ n_stacks += 2;
+ }
+ break;
+#else /* BUILD_TARGET_RISCV32_ILP32D */
+ case VALUE_TYPE_F32:
+ case VALUE_TYPE_F64:
+ if (n_fps < MAX_REG_FLOATS) {
+ n_fps++;
+ }
+ else if (func_type->types[i] == VALUE_TYPE_F32
+ && n_ints < MAX_REG_INTS) {
+ /* use int reg firstly if available */
+ n_ints++;
+ }
+ else if (func_type->types[i] == VALUE_TYPE_F64
+ && n_ints < MAX_REG_INTS - 1) {
+ /* use int regs firstly if available */
+ if (n_ints & 1)
+ n_ints++;
+ ints += 2;
+ }
+ else {
+ /* 64-bit data in stack must be 8 bytes aligned in riscv32
+ */
+ if (n_stacks & 1)
+ n_stacks++;
+ n_stacks += 2;
+ }
+ break;
+#endif /* BUILD_TARGET_RISCV32_ILP32D */
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ for (i = 0; i < ext_ret_count; i++) {
+ if (n_ints < MAX_REG_INTS)
+ n_ints++;
+ else
+ n_stacks++;
+ }
+
+#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
+ argc1 = MAX_REG_INTS + MAX_REG_FLOATS + n_stacks;
+#elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
+ argc1 = MAX_REG_INTS + n_stacks;
+#else /* for BUILD_TARGET_RISCV32_ILP32D */
+ argc1 = MAX_REG_INTS + MAX_REG_FLOATS * 2 + n_stacks;
+#endif
+
+ if (argc1 > sizeof(argv_buf) / sizeof(uint32)) {
+ size = sizeof(uint32) * (uint32)argc1;
+ if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL,
+ 0))) {
+ return false;
+ }
+ }
+
+ ints = argv1;
+#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
+ fps = ints + MAX_REG_INTS;
+ stacks = fps + MAX_REG_FLOATS;
+#elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
+ stacks = ints + MAX_REG_INTS;
+#else /* for BUILD_TARGET_RISCV32_ILP32D */
+ fps = ints + MAX_REG_INTS;
+ stacks = fps + MAX_REG_FLOATS * 2;
+#endif
+
+ 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 WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ {
+ arg_i32 = *argv_src++;
+
+ if (signature) {
+ if (signature[i + 1] == '*') {
+ /* param is a pointer */
+ if (signature[i + 2] == '~')
+ /* pointer with length followed */
+ ptr_len = *argv_src;
+ else
+ /* pointer without length followed */
+ ptr_len = 1;
+
+ if (!wasm_runtime_validate_app_addr(module, arg_i32,
+ ptr_len))
+ goto fail;
+
+ arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native(
+ module, arg_i32);
+ }
+ else if (signature[i + 1] == '$') {
+ /* param is a string */
+ if (!wasm_runtime_validate_app_str_addr(module,
+ arg_i32))
+ goto fail;
+
+ arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native(
+ module, arg_i32);
+ }
+ }
+
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = arg_i32;
+ else
+ stacks[n_stacks++] = arg_i32;
+ break;
+ }
+ case VALUE_TYPE_I64:
+ {
+ if (n_ints < MAX_REG_INTS - 1) {
+#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
+ /* 64-bit data must be 8 bytes aligned in arm */
+ if (n_ints & 1)
+ n_ints++;
+#endif
+ ints[n_ints++] = *argv_src++;
+ ints[n_ints++] = *argv_src++;
+ }
+#if defined(BUILD_TARGET_RISCV32_ILP32) \
+ || defined(BUILD_TARGET_RISCV32_ILP32D) || defined(BUILD_TARGET_ARC)
+ else if (n_ints == MAX_REG_INTS - 1) {
+ ints[n_ints++] = *argv_src++;
+ stacks[n_stacks++] = *argv_src++;
+ }
+#endif
+ else {
+ /* 64-bit data in stack must be 8 bytes aligned
+ in arm and riscv32 */
+#if !defined(BUILD_TARGET_ARC)
+ if (n_stacks & 1)
+ n_stacks++;
+#endif
+ stacks[n_stacks++] = *argv_src++;
+ stacks[n_stacks++] = *argv_src++;
+ }
+ break;
+ }
+#if !defined(BUILD_TARGET_RISCV32_ILP32D)
+ 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) {
+#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
+ /* 64-bit data must be 8 bytes aligned in arm */
+ if (n_fps & 1)
+ n_fps++;
+#endif
+ fps[n_fps++] = *argv_src++;
+ fps[n_fps++] = *argv_src++;
+ }
+#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
+ else if (n_fps == MAX_REG_FLOATS - 1) {
+ fps[n_fps++] = *argv_src++;
+ stacks[n_stacks++] = *argv_src++;
+ }
+#endif
+ else {
+ /* 64-bit data in stack must be 8 bytes aligned
+ in arm and riscv32 */
+#if !defined(BUILD_TARGET_ARC)
+ if (n_stacks & 1)
+ n_stacks++;
+#endif
+ stacks[n_stacks++] = *argv_src++;
+ stacks[n_stacks++] = *argv_src++;
+ }
+ break;
+ }
+#else /* BUILD_TARGET_RISCV32_ILP32D */
+ case VALUE_TYPE_F32:
+ case VALUE_TYPE_F64:
+ {
+ if (n_fps < MAX_REG_FLOATS) {
+ if (func_type->types[i] == VALUE_TYPE_F32) {
+ *(float32 *)&fps[n_fps * 2] = *(float32 *)argv_src++;
+ /* NaN boxing, the upper bits of a valid NaN-boxed
+ value must be all 1s. */
+ fps[n_fps * 2 + 1] = 0xFFFFFFFF;
+ }
+ else {
+ *(float64 *)&fps[n_fps * 2] = *(float64 *)argv_src;
+ argv_src += 2;
+ }
+ n_fps++;
+ }
+ else if (func_type->types[i] == VALUE_TYPE_F32
+ && n_ints < MAX_REG_INTS) {
+ /* use int reg firstly if available */
+ *(float32 *)&ints[n_ints++] = *(float32 *)argv_src++;
+ }
+ else if (func_type->types[i] == VALUE_TYPE_F64
+ && n_ints < MAX_REG_INTS - 1) {
+ /* use int regs firstly if available */
+ if (n_ints & 1)
+ n_ints++;
+ *(float64 *)&ints[n_ints] = *(float64 *)argv_src;
+ n_ints += 2;
+ argv_src += 2;
+ }
+ else {
+ /* 64-bit data in stack must be 8 bytes aligned in riscv32
+ */
+ if (n_stacks & 1)
+ n_stacks++;
+ if (func_type->types[i] == VALUE_TYPE_F32) {
+ *(float32 *)&stacks[n_stacks] = *(float32 *)argv_src++;
+ /* NaN boxing, the upper bits of a valid NaN-boxed
+ value must be all 1s. */
+ stacks[n_stacks + 1] = 0xFFFFFFFF;
+ }
+ else {
+ *(float64 *)&stacks[n_stacks] = *(float64 *)argv_src;
+ argv_src += 2;
+ }
+ n_stacks += 2;
+ }
+ break;
+ }
+#endif /* BUILD_TARGET_RISCV32_ILP32D */
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ uint32 externref_idx = *argv_src++;
+
+ if (is_aot_func) {
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = externref_idx;
+ else
+ stacks[n_stacks++] = externref_idx;
+ }
+ else {
+ void *externref_obj;
+
+ if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
+ goto fail;
+
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = (uintptr_t)externref_obj;
+ else
+ stacks[n_stacks++] = (uintptr_t)externref_obj;
+ }
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ /* Save extra result values' address to argv1 */
+ for (i = 0; i < ext_ret_count; i++) {
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = *(uint32 *)argv_src++;
+ else
+ stacks[n_stacks++] = *(uint32 *)argv_src++;
+ }
+
+ exec_env->attachment = attachment;
+ 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:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ argv_ret[0] =
+ (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
+ break;
+ case VALUE_TYPE_I64:
+ PUT_I64_TO_ADDR(argv_ret,
+ invokeNative_Int64(func_ptr, argv1, n_stacks));
+ break;
+ case VALUE_TYPE_F32:
+ *(float32 *)argv_ret =
+ invokeNative_Float32(func_ptr, argv1, n_stacks);
+ break;
+ case VALUE_TYPE_F64:
+ PUT_F64_TO_ADDR(
+ argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ if (is_aot_func) {
+ uint32 externref_idx =
+ (uint32)invokeNative_Int32(func_ptr, argv1, argc1);
+ argv_ret[0] = externref_idx;
+ }
+ else {
+ uint32 externref_idx;
+ void *externref_obj;
+
+ externref_obj = (void *)(uintptr_t)invokeNative_Int32(
+ func_ptr, argv1, argc1);
+
+ if (!wasm_externref_obj2ref(exec_env->module_inst,
+ externref_obj, &externref_idx))
+ goto fail;
+
+ argv_ret[0] = externref_idx;
+ }
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+ exec_env->attachment = NULL;
+
+ ret = !wasm_runtime_copy_exception(module, NULL);
+
+fail:
+ if (argv1 != argv_buf)
+ wasm_runtime_free(argv1);
+ return ret;
+}
+#endif /* end of defined(BUILD_TARGET_ARM_VFP) \
+ || defined(BUILD_TARGET_THUMB_VFP) \
+ || defined(BUILD_TARGET_RISCV32_ILP32D) \
+ || defined(BUILD_TARGET_RISCV32_ILP32) \
+ || defined(BUILD_TARGET_ARC) */
+
+#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)();
+void
+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 volatile Int64FuncPtr invokeNative_Int64 =
+ (Int64FuncPtr)(uintptr_t)invokeNative;
+static volatile Int32FuncPtr invokeNative_Int32 =
+ (Int32FuncPtr)(uintptr_t)invokeNative;
+static volatile Float64FuncPtr invokeNative_Float64 =
+ (Float64FuncPtr)(uintptr_t)invokeNative;
+static volatile Float32FuncPtr invokeNative_Float32 =
+ (Float32FuncPtr)(uintptr_t)invokeNative;
+static volatile VoidFuncPtr invokeNative_Void =
+ (VoidFuncPtr)(uintptr_t)invokeNative;
+
+static inline void
+word_copy(uint32 *dest, uint32 *src, unsigned num)
+{
+ for (; num > 0; num--)
+ *dest++ = *src++;
+}
+
+bool
+wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type, const char *signature,
+ void *attachment, uint32 *argv, uint32 argc,
+ uint32 *argv_ret)
+{
+ WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
+ uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0;
+ uint32 arg_i32, ptr_len;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
+ uint64 size;
+ bool ret = false;
+#if WASM_ENABLE_REF_TYPES != 0
+ bool is_aot_func = (NULL == signature);
+#endif
+
+#if defined(BUILD_TARGET_X86_32)
+ argc1 = argc + ext_ret_count + 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 + ext_ret_count + 2;
+#endif
+
+ if (argc1 > sizeof(argv_buf) / sizeof(uint32)) {
+ size = sizeof(uint32) * (uint64)argc1;
+ if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL,
+ 0))) {
+ return false;
+ }
+ }
+
+ for (i = 0; i < sizeof(WASMExecEnv *) / sizeof(uint32); i++)
+ argv1[j++] = ((uint32 *)&exec_env)[i];
+
+ for (i = 0; i < func_type->param_count; i++) {
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ {
+ arg_i32 = *argv++;
+
+ if (signature) {
+ if (signature[i + 1] == '*') {
+ /* param is a pointer */
+ if (signature[i + 2] == '~')
+ /* pointer with length followed */
+ ptr_len = *argv;
+ else
+ /* pointer without length followed */
+ ptr_len = 1;
+
+ if (!wasm_runtime_validate_app_addr(module, arg_i32,
+ ptr_len))
+ goto fail;
+
+ arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native(
+ module, arg_i32);
+ }
+ else if (signature[i + 1] == '$') {
+ /* param is a string */
+ if (!wasm_runtime_validate_app_str_addr(module,
+ arg_i32))
+ goto fail;
+
+ arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native(
+ module, arg_i32);
+ }
+ }
+
+ argv1[j++] = arg_i32;
+ break;
+ }
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+#if !defined(BUILD_TARGET_X86_32)
+ /* 64-bit data must be 8 bytes aligned in arm, thumb, mips
+ and xtensa */
+ if (j & 1)
+ j++;
+#endif
+ argv1[j++] = *argv++;
+ argv1[j++] = *argv++;
+ break;
+ case VALUE_TYPE_F32:
+ argv1[j++] = *argv++;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ uint32 externref_idx = *argv++;
+ if (is_aot_func) {
+ argv1[j++] = externref_idx;
+ }
+ else {
+ void *externref_obj;
+
+ if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
+ goto fail;
+
+ argv1[j++] = (uintptr_t)externref_obj;
+ }
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ /* Save extra result values' address to argv1 */
+ word_copy(argv1 + j, argv, ext_ret_count);
+
+ argc1 = j + ext_ret_count;
+ exec_env->attachment = attachment;
+ 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:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ argv_ret[0] =
+ (uint32)invokeNative_Int32(func_ptr, argv1, argc1);
+ break;
+ case VALUE_TYPE_I64:
+ PUT_I64_TO_ADDR(argv_ret,
+ invokeNative_Int64(func_ptr, argv1, argc1));
+ break;
+ case VALUE_TYPE_F32:
+ *(float32 *)argv_ret =
+ invokeNative_Float32(func_ptr, argv1, argc1);
+ break;
+ case VALUE_TYPE_F64:
+ PUT_F64_TO_ADDR(argv_ret,
+ invokeNative_Float64(func_ptr, argv1, argc1));
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ if (is_aot_func) {
+ uint32 externref_idx =
+ (uint32)invokeNative_Int32(func_ptr, argv1, argc1);
+ argv_ret[0] = externref_idx;
+ }
+ else {
+ void *externref_obj = (void *)(uintptr_t)invokeNative_Int32(
+ func_ptr, argv1, argc1);
+ uint32 externref_idx;
+ if (!wasm_externref_obj2ref(exec_env->module_inst,
+ externref_obj, &externref_idx))
+ goto fail;
+ argv_ret[0] = externref_idx;
+ }
+ break;
+ }
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+ exec_env->attachment = NULL;
+
+ ret = !wasm_runtime_copy_exception(module, NULL);
+
+fail:
+ if (argv1 != argv_buf)
+ wasm_runtime_free(argv1);
+ return ret;
+}
+
+#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) \
+ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+
+#if WASM_ENABLE_SIMD != 0
+#ifdef v128
+#undef v128
+#endif
+
+#if defined(_WIN32) || defined(_WIN32_)
+typedef union __declspec(intrin_type) __declspec(align(8)) v128 {
+ __int8 m128i_i8[16];
+ __int16 m128i_i16[8];
+ __int32 m128i_i32[4];
+ __int64 m128i_i64[2];
+ unsigned __int8 m128i_u8[16];
+ unsigned __int16 m128i_u16[8];
+ unsigned __int32 m128i_u32[4];
+ unsigned __int64 m128i_u64[2];
+} v128;
+#elif defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+typedef long long v128
+ __attribute__((__vector_size__(16), __may_alias__, __aligned__(1)));
+#elif defined(BUILD_TARGET_AARCH64)
+#include <arm_neon.h>
+typedef uint32x4_t __m128i;
+#define v128 __m128i
+#endif
+
+#endif /* end of WASM_ENABLE_SIMD != 0 */
+
+typedef void (*GenericFunctionPointer)();
+void
+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 volatile Float64FuncPtr invokeNative_Float64 =
+ (Float64FuncPtr)(uintptr_t)invokeNative;
+static volatile Float32FuncPtr invokeNative_Float32 =
+ (Float32FuncPtr)(uintptr_t)invokeNative;
+static volatile Int64FuncPtr invokeNative_Int64 =
+ (Int64FuncPtr)(uintptr_t)invokeNative;
+static volatile Int32FuncPtr invokeNative_Int32 =
+ (Int32FuncPtr)(uintptr_t)invokeNative;
+static volatile VoidFuncPtr invokeNative_Void =
+ (VoidFuncPtr)(uintptr_t)invokeNative;
+
+#if WASM_ENABLE_SIMD != 0
+typedef v128 (*V128FuncPtr)(GenericFunctionPointer, uint64 *, uint64);
+static V128FuncPtr invokeNative_V128 = (V128FuncPtr)(uintptr_t)invokeNative;
+#endif
+
+#if defined(_WIN32) || defined(_WIN32_)
+#define MAX_REG_FLOATS 4
+#define MAX_REG_INTS 4
+#else /* else of defined(_WIN32) || defined(_WIN32_) */
+#define MAX_REG_FLOATS 8
+#if defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+#define MAX_REG_INTS 8
+#else
+#define MAX_REG_INTS 6
+#endif /* end of defined(BUILD_TARGET_AARCH64) \
+ || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64) */
+#endif /* end of defined(_WIN32) || defined(_WIN32_) */
+
+bool
+wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type, const char *signature,
+ void *attachment, uint32 *argv, uint32 argc,
+ uint32 *argv_ret)
+{
+ WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
+ uint64 argv_buf[32] = { 0 }, *argv1 = argv_buf, *ints, *stacks, size,
+ arg_i64;
+ uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0;
+ uint32 arg_i32, ptr_len;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
+ bool ret = false;
+#if WASM_ENABLE_REF_TYPES != 0
+ bool is_aot_func = (NULL == signature);
+#endif
+#ifndef BUILD_TARGET_RISCV64_LP64
+#if WASM_ENABLE_SIMD == 0
+ uint64 *fps;
+#else
+ v128 *fps;
+#endif
+#else /* else of BUILD_TARGET_RISCV64_LP64 */
+#define fps ints
+#endif /* end of BUILD_TARGET_RISCV64_LP64 */
+
+#if defined(_WIN32) || defined(_WIN32_) || defined(BUILD_TARGET_RISCV64_LP64)
+ /* important difference in calling conventions */
+#define n_fps n_ints
+#else
+ int n_fps = 0;
+#endif
+
+#if WASM_ENABLE_SIMD == 0
+ argc1 = 1 + MAX_REG_FLOATS + (uint32)func_type->param_count + ext_ret_count;
+#else
+ argc1 = 1 + MAX_REG_FLOATS * 2 + (uint32)func_type->param_count * 2
+ + ext_ret_count;
+#endif
+ if (argc1 > sizeof(argv_buf) / sizeof(uint64)) {
+ size = sizeof(uint64) * (uint64)argc1;
+ if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL,
+ 0))) {
+ return false;
+ }
+ }
+
+#ifndef BUILD_TARGET_RISCV64_LP64
+#if WASM_ENABLE_SIMD == 0
+ fps = argv1;
+ ints = fps + MAX_REG_FLOATS;
+#else
+ fps = (v128 *)argv1;
+ ints = (uint64 *)(fps + MAX_REG_FLOATS);
+#endif
+#else /* else of BUILD_TARGET_RISCV64_LP64 */
+ ints = argv1;
+#endif /* end of BUILD_TARGET_RISCV64_LP64 */
+ 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 WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ {
+ arg_i32 = *argv_src++;
+ arg_i64 = arg_i32;
+ if (signature) {
+ if (signature[i + 1] == '*') {
+ /* param is a pointer */
+ if (signature[i + 2] == '~')
+ /* pointer with length followed */
+ ptr_len = *argv_src;
+ else
+ /* pointer without length followed */
+ ptr_len = 1;
+
+ if (!wasm_runtime_validate_app_addr(module, arg_i32,
+ ptr_len))
+ goto fail;
+
+ arg_i64 = (uintptr_t)wasm_runtime_addr_app_to_native(
+ module, arg_i32);
+ }
+ else if (signature[i + 1] == '$') {
+ /* param is a string */
+ if (!wasm_runtime_validate_app_str_addr(module,
+ arg_i32))
+ goto fail;
+
+ arg_i64 = (uintptr_t)wasm_runtime_addr_app_to_native(
+ module, arg_i32);
+ }
+ }
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = arg_i64;
+ else
+ stacks[n_stacks++] = arg_i64;
+ 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;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ uint32 externref_idx = *argv_src++;
+ if (is_aot_func) {
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = externref_idx;
+ else
+ stacks[n_stacks++] = externref_idx;
+ }
+ else {
+ void *externref_obj;
+
+ if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
+ goto fail;
+
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = (uintptr_t)externref_obj;
+ else
+ stacks[n_stacks++] = (uintptr_t)externref_obj;
+ }
+ break;
+ }
+#endif
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ if (n_fps < MAX_REG_FLOATS) {
+ *(v128 *)&fps[n_fps++] = *(v128 *)argv_src;
+ }
+ else {
+ *(v128 *)&stacks[n_stacks++] = *(v128 *)argv_src;
+ n_stacks++;
+ }
+ argv_src += 4;
+ break;
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ /* Save extra result values' address to argv1 */
+ for (i = 0; i < ext_ret_count; i++) {
+ if (n_ints < MAX_REG_INTS)
+ ints[n_ints++] = *(uint64 *)argv_src;
+ else
+ stacks[n_stacks++] = *(uint64 *)argv_src;
+ argv_src += 2;
+ }
+
+ exec_env->attachment = attachment;
+ if (result_count == 0) {
+ invokeNative_Void(func_ptr, argv1, n_stacks);
+ }
+ else {
+ /* Invoke the native function and get the first result value */
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+#endif
+ argv_ret[0] =
+ (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
+ break;
+ case VALUE_TYPE_I64:
+ PUT_I64_TO_ADDR(argv_ret,
+ invokeNative_Int64(func_ptr, argv1, n_stacks));
+ break;
+ case VALUE_TYPE_F32:
+ *(float32 *)argv_ret =
+ invokeNative_Float32(func_ptr, argv1, n_stacks);
+ break;
+ case VALUE_TYPE_F64:
+ PUT_F64_TO_ADDR(
+ argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ {
+ if (is_aot_func) {
+ argv_ret[0] = invokeNative_Int32(func_ptr, argv1, n_stacks);
+ }
+ else {
+ uint32 externref_idx;
+ void *externref_obj = (void *)(uintptr_t)invokeNative_Int64(
+ func_ptr, argv1, n_stacks);
+
+ if (!wasm_externref_obj2ref(exec_env->module_inst,
+ externref_obj, &externref_idx))
+ goto fail;
+
+ argv_ret[0] = externref_idx;
+ }
+ break;
+ }
+#endif
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ *(v128 *)argv_ret =
+ invokeNative_V128(func_ptr, argv1, n_stacks);
+ break;
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+ exec_env->attachment = NULL;
+
+ ret = !wasm_runtime_copy_exception(module, NULL);
+fail:
+ if (argv1 != argv_buf)
+ wasm_runtime_free(argv1);
+
+ return ret;
+}
+
+#endif /* end of defined(BUILD_TARGET_X86_64) \
+ || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_AARCH64) \
+ || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64) */
+
+bool
+wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
+ uint32 argc, uint32 argv[])
+{
+ bool ret = false;
+
+ if (!wasm_runtime_exec_env_check(exec_env)) {
+ LOG_ERROR("Invalid exec env stack info.");
+ return false;
+ }
+
+ /* this function is called from native code, so exec_env->handle and
+ exec_env->native_stack_boundary must have been set, we don't set
+ it again */
+
+#if WASM_ENABLE_INTERP != 0
+ if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
+ ret = wasm_call_indirect(exec_env, 0, element_index, argc, argv);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (exec_env->module_inst->module_type == Wasm_Module_AoT)
+ ret = aot_call_indirect(exec_env, 0, element_index, argc, argv);
+#endif
+
+ if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) {
+ ret = true;
+ }
+
+ return ret;
+}
+
+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 *p_data)
+{
+ uint32 value;
+
+ value = *(uint32 *)p_data;
+ *(uint32 *)p_data = *(uint32 *)(p_data + 4);
+ *(uint32 *)(p_data + 4) = value;
+ exchange_uint32(p_data);
+ exchange_uint32(p_data + 4);
+}
+
+void
+wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2)
+{
+ uint64 u1, u2;
+
+ bh_memcpy_s(&u1, 8, bytes, 8);
+ bh_memcpy_s(&u2, 8, bytes + 8, 8);
+
+ if (!is_little_endian()) {
+ exchange_uint64((uint8 *)&u1);
+ exchange_uint64((uint8 *)&u2);
+ *ret1 = u2;
+ *ret2 = u1;
+ }
+ else {
+ *ret1 = u1;
+ *ret2 = u2;
+ }
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+typedef struct WASMThreadArg {
+ WASMExecEnv *new_exec_env;
+ wasm_thread_callback_t callback;
+ void *arg;
+} WASMThreadArg;
+
+WASMExecEnv *
+wasm_runtime_spawn_exec_env(WASMExecEnv *exec_env)
+{
+ return wasm_cluster_spawn_exec_env(exec_env);
+}
+
+void
+wasm_runtime_destroy_spawned_exec_env(WASMExecEnv *exec_env)
+{
+ wasm_cluster_destroy_spawned_exec_env(exec_env);
+}
+
+static void *
+wasm_runtime_thread_routine(void *arg)
+{
+ WASMThreadArg *thread_arg = (WASMThreadArg *)arg;
+ void *ret;
+
+ bh_assert(thread_arg->new_exec_env);
+ ret = thread_arg->callback(thread_arg->new_exec_env, thread_arg->arg);
+
+ wasm_runtime_destroy_spawned_exec_env(thread_arg->new_exec_env);
+ wasm_runtime_free(thread_arg);
+
+ os_thread_exit(ret);
+ return ret;
+}
+
+int32
+wasm_runtime_spawn_thread(WASMExecEnv *exec_env, wasm_thread_t *tid,
+ wasm_thread_callback_t callback, void *arg)
+{
+ WASMExecEnv *new_exec_env = wasm_runtime_spawn_exec_env(exec_env);
+ WASMThreadArg *thread_arg;
+ int32 ret;
+
+ if (!new_exec_env)
+ return -1;
+
+ if (!(thread_arg = wasm_runtime_malloc(sizeof(WASMThreadArg)))) {
+ wasm_runtime_destroy_spawned_exec_env(new_exec_env);
+ return -1;
+ }
+
+ thread_arg->new_exec_env = new_exec_env;
+ thread_arg->callback = callback;
+ thread_arg->arg = arg;
+
+ ret = os_thread_create((korp_tid *)tid, wasm_runtime_thread_routine,
+ thread_arg, APP_THREAD_STACK_SIZE_DEFAULT);
+
+ if (ret != 0) {
+ wasm_runtime_destroy_spawned_exec_env(new_exec_env);
+ wasm_runtime_free(thread_arg);
+ }
+
+ return ret;
+}
+
+int32
+wasm_runtime_join_thread(wasm_thread_t tid, void **retval)
+{
+ return os_thread_join((korp_tid)tid, retval);
+}
+
+#endif /* end of WASM_ENABLE_THREAD_MGR */
+
+#if WASM_ENABLE_REF_TYPES != 0
+
+static korp_mutex externref_lock;
+static uint32 externref_global_id = 1;
+static HashMap *externref_map;
+
+typedef struct ExternRefMapNode {
+ /* The extern object from runtime embedder */
+ void *extern_obj;
+ /* The module instance it belongs to */
+ WASMModuleInstanceCommon *module_inst;
+ /* Whether it is retained */
+ bool retained;
+ /* Whether it is marked by runtime */
+ bool marked;
+} ExternRefMapNode;
+
+static uint32
+wasm_externref_hash(const void *key)
+{
+ uint32 externref_idx = (uint32)(uintptr_t)key;
+ return externref_idx;
+}
+
+static bool
+wasm_externref_equal(void *key1, void *key2)
+{
+ uint32 externref_idx1 = (uint32)(uintptr_t)key1;
+ uint32 externref_idx2 = (uint32)(uintptr_t)key2;
+ return externref_idx1 == externref_idx2 ? true : false;
+}
+
+static bool
+wasm_externref_map_init()
+{
+ if (os_mutex_init(&externref_lock) != 0)
+ return false;
+
+ if (!(externref_map = bh_hash_map_create(32, false, wasm_externref_hash,
+ wasm_externref_equal, NULL,
+ wasm_runtime_free))) {
+ os_mutex_destroy(&externref_lock);
+ return false;
+ }
+
+ externref_global_id = 1;
+ return true;
+}
+
+static void
+wasm_externref_map_destroy()
+{
+ bh_hash_map_destroy(externref_map);
+ os_mutex_destroy(&externref_lock);
+}
+
+typedef struct LookupExtObj_UserData {
+ ExternRefMapNode node;
+ bool found;
+ uint32 externref_idx;
+} LookupExtObj_UserData;
+
+static void
+lookup_extobj_callback(void *key, void *value, void *user_data)
+{
+ uint32 externref_idx = (uint32)(uintptr_t)key;
+ ExternRefMapNode *node = (ExternRefMapNode *)value;
+ LookupExtObj_UserData *user_data_lookup =
+ (LookupExtObj_UserData *)user_data;
+
+ if (node->extern_obj == user_data_lookup->node.extern_obj
+ && node->module_inst == user_data_lookup->node.module_inst) {
+ user_data_lookup->found = true;
+ user_data_lookup->externref_idx = externref_idx;
+ }
+}
+
+bool
+wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
+ uint32 *p_externref_idx)
+{
+ LookupExtObj_UserData lookup_user_data = { 0 };
+ ExternRefMapNode *node;
+ uint32 externref_idx;
+
+ /*
+ * to catch a parameter from `wasm_application_execute_func`,
+ * which represents a string 'null'
+ */
+#if UINTPTR_MAX == UINT32_MAX
+ if ((uint32)-1 == (uintptr_t)extern_obj) {
+#else
+ if ((uint64)-1LL == (uintptr_t)extern_obj) {
+#endif
+ *p_externref_idx = NULL_REF;
+ return true;
+ }
+
+ /* in a wrapper, extern_obj could be any value */
+ lookup_user_data.node.extern_obj = extern_obj;
+ lookup_user_data.node.module_inst = module_inst;
+ lookup_user_data.found = false;
+
+ os_mutex_lock(&externref_lock);
+
+ /* Lookup hashmap firstly */
+ bh_hash_map_traverse(externref_map, lookup_extobj_callback,
+ (void *)&lookup_user_data);
+ if (lookup_user_data.found) {
+ *p_externref_idx = lookup_user_data.externref_idx;
+ os_mutex_unlock(&externref_lock);
+ return true;
+ }
+
+ /* Not found in hashmap */
+ if (externref_global_id == NULL_REF || externref_global_id == 0) {
+ goto fail1;
+ }
+
+ if (!(node = wasm_runtime_malloc(sizeof(ExternRefMapNode)))) {
+ goto fail1;
+ }
+
+ memset(node, 0, sizeof(ExternRefMapNode));
+ node->extern_obj = extern_obj;
+ node->module_inst = module_inst;
+
+ externref_idx = externref_global_id;
+
+ if (!bh_hash_map_insert(externref_map, (void *)(uintptr_t)externref_idx,
+ (void *)node)) {
+ goto fail2;
+ }
+
+ externref_global_id++;
+ *p_externref_idx = externref_idx;
+ os_mutex_unlock(&externref_lock);
+ return true;
+fail2:
+ wasm_runtime_free(node);
+fail1:
+ os_mutex_unlock(&externref_lock);
+ return false;
+}
+
+bool
+wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj)
+{
+ ExternRefMapNode *node;
+
+ /* catch a `ref.null` vairable */
+ if (externref_idx == NULL_REF) {
+ *p_extern_obj = NULL;
+ return true;
+ }
+
+ os_mutex_lock(&externref_lock);
+ node = bh_hash_map_find(externref_map, (void *)(uintptr_t)externref_idx);
+ os_mutex_unlock(&externref_lock);
+
+ if (!node)
+ return false;
+
+ *p_extern_obj = node->extern_obj;
+ return true;
+}
+
+static void
+reclaim_extobj_callback(void *key, void *value, void *user_data)
+{
+ ExternRefMapNode *node = (ExternRefMapNode *)value;
+ WASMModuleInstanceCommon *module_inst =
+ (WASMModuleInstanceCommon *)user_data;
+
+ if (node->module_inst == module_inst) {
+ if (!node->marked && !node->retained) {
+ bh_hash_map_remove(externref_map, key, NULL, NULL);
+ wasm_runtime_free(value);
+ }
+ else {
+ node->marked = false;
+ }
+ }
+}
+
+static void
+mark_externref(uint32 externref_idx)
+{
+ ExternRefMapNode *node;
+
+ if (externref_idx != NULL_REF) {
+ node =
+ bh_hash_map_find(externref_map, (void *)(uintptr_t)externref_idx);
+ if (node) {
+ node->marked = true;
+ }
+ }
+}
+
+#if WASM_ENABLE_INTERP != 0
+static void
+interp_mark_all_externrefs(WASMModuleInstance *module_inst)
+{
+ uint32 i, j, externref_idx, *table_data;
+ uint8 *global_data = module_inst->global_data;
+ WASMGlobalInstance *global;
+ WASMTableInstance *table;
+
+ global = module_inst->e->globals;
+ for (i = 0; i < module_inst->e->global_count; i++, global++) {
+ if (global->type == VALUE_TYPE_EXTERNREF) {
+ externref_idx = *(uint32 *)(global_data + global->data_offset);
+ mark_externref(externref_idx);
+ }
+ }
+
+ for (i = 0; i < module_inst->table_count; i++) {
+ uint8 elem_type = 0;
+ uint32 init_size, max_size;
+
+ table = wasm_get_table_inst(module_inst, i);
+ (void)wasm_runtime_get_table_inst_elem_type(
+ (WASMModuleInstanceCommon *)module_inst, i, &elem_type, &init_size,
+ &max_size);
+
+ if (elem_type == VALUE_TYPE_EXTERNREF) {
+ table_data = table->elems;
+ for (j = 0; j < table->cur_size; j++) {
+ externref_idx = table_data[j];
+ mark_externref(externref_idx);
+ }
+ }
+ (void)init_size;
+ (void)max_size;
+ }
+}
+#endif
+
+#if WASM_ENABLE_AOT != 0
+static void
+aot_mark_all_externrefs(AOTModuleInstance *module_inst)
+{
+ uint32 i = 0, j = 0;
+ const AOTModule *module = (AOTModule *)module_inst->module;
+ const AOTTable *table = module->tables;
+ const AOTGlobal *global = module->globals;
+ const AOTTableInstance *table_inst;
+
+ for (i = 0; i < module->global_count; i++, global++) {
+ if (global->type == VALUE_TYPE_EXTERNREF) {
+ mark_externref(
+ *(uint32 *)(module_inst->global_data + global->data_offset));
+ }
+ }
+
+ for (i = 0; i < module->table_count; i++) {
+ table_inst = module_inst->tables[i];
+ if ((table + i)->elem_type == VALUE_TYPE_EXTERNREF) {
+ while (j < table_inst->cur_size) {
+ mark_externref(table_inst->elems[j++]);
+ }
+ }
+ }
+}
+#endif
+
+void
+wasm_externref_reclaim(WASMModuleInstanceCommon *module_inst)
+{
+ os_mutex_lock(&externref_lock);
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode)
+ interp_mark_all_externrefs((WASMModuleInstance *)module_inst);
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT)
+ aot_mark_all_externrefs((AOTModuleInstance *)module_inst);
+#endif
+
+ bh_hash_map_traverse(externref_map, reclaim_extobj_callback,
+ (void *)module_inst);
+ os_mutex_unlock(&externref_lock);
+}
+
+static void
+cleanup_extobj_callback(void *key, void *value, void *user_data)
+{
+ ExternRefMapNode *node = (ExternRefMapNode *)value;
+ WASMModuleInstanceCommon *module_inst =
+ (WASMModuleInstanceCommon *)user_data;
+
+ if (node->module_inst == module_inst) {
+ bh_hash_map_remove(externref_map, key, NULL, NULL);
+ wasm_runtime_free(value);
+ }
+}
+
+void
+wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst)
+{
+ os_mutex_lock(&externref_lock);
+ bh_hash_map_traverse(externref_map, cleanup_extobj_callback,
+ (void *)module_inst);
+ os_mutex_unlock(&externref_lock);
+}
+
+bool
+wasm_externref_retain(uint32 externref_idx)
+{
+ ExternRefMapNode *node;
+
+ os_mutex_lock(&externref_lock);
+
+ if (externref_idx != NULL_REF) {
+ node =
+ bh_hash_map_find(externref_map, (void *)(uintptr_t)externref_idx);
+ if (node) {
+ node->retained = true;
+ os_mutex_unlock(&externref_lock);
+ return true;
+ }
+ }
+
+ os_mutex_unlock(&externref_lock);
+ return false;
+}
+#endif /* end of WASM_ENABLE_REF_TYPES */
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+uint32
+wasm_runtime_dump_line_buf_impl(const char *line_buf, bool dump_or_print,
+ char **buf, uint32 *len)
+{
+ if (dump_or_print) {
+ return (uint32)os_printf("%s", line_buf);
+ }
+ else if (*buf) {
+ uint32 dump_len;
+
+ dump_len = snprintf(*buf, *len, "%s", line_buf);
+ if (dump_len >= *len) {
+ dump_len = *len;
+ }
+
+ *len = *len - dump_len;
+ *buf = *buf + dump_len;
+ return dump_len;
+ }
+ else {
+ return (uint32)strlen(line_buf);
+ }
+}
+
+void
+wasm_runtime_dump_call_stack(WASMExecEnv *exec_env)
+{
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ aot_dump_call_stack(exec_env, true, NULL, 0);
+ }
+#endif
+}
+
+uint32
+wasm_runtime_get_call_stack_buf_size(wasm_exec_env_t exec_env)
+{
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ return wasm_interp_dump_call_stack(exec_env, false, NULL, 0);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ return aot_dump_call_stack(exec_env, false, NULL, 0);
+ }
+#endif
+
+ return 0;
+}
+
+uint32
+wasm_runtime_dump_call_stack_to_buf(wasm_exec_env_t exec_env, char *buf,
+ uint32 len)
+{
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ return wasm_interp_dump_call_stack(exec_env, false, buf, len);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ return aot_dump_call_stack(exec_env, false, buf, len);
+ }
+#endif
+
+ return 0;
+}
+#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
+
+bool
+wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
+ uint32 table_idx, uint8 *out_elem_type,
+ uint32 *out_min_size, uint32 *out_max_size)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModule *module = (WASMModule *)module_comm;
+
+ if (table_idx < module->import_table_count) {
+ WASMTableImport *import_table =
+ &((module->import_tables + table_idx)->u.table);
+ *out_elem_type = import_table->elem_type;
+ *out_min_size = import_table->init_size;
+ *out_max_size = import_table->max_size;
+ }
+ else {
+ WASMTable *table =
+ module->tables + (table_idx - module->import_table_count);
+ *out_elem_type = table->elem_type;
+ *out_min_size = table->init_size;
+ *out_max_size = table->max_size;
+ }
+ return true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_comm->module_type == Wasm_Module_AoT) {
+ AOTModule *module = (AOTModule *)module_comm;
+
+ if (table_idx < module->import_table_count) {
+ AOTImportTable *import_table = module->import_tables + table_idx;
+ *out_elem_type = VALUE_TYPE_FUNCREF;
+ *out_min_size = import_table->table_init_size;
+ *out_max_size = import_table->table_max_size;
+ }
+ else {
+ AOTTable *table =
+ module->tables + (table_idx - module->import_table_count);
+ *out_elem_type = table->elem_type;
+ *out_min_size = table->table_init_size;
+ *out_max_size = table->table_max_size;
+ }
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+bool
+wasm_runtime_get_table_inst_elem_type(
+ const WASMModuleInstanceCommon *module_inst_comm, uint32 table_idx,
+ uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)module_inst_comm;
+ return wasm_runtime_get_table_elem_type(
+ (WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
+ out_min_size, out_max_size);
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_comm->module_type == Wasm_Module_AoT) {
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
+ return wasm_runtime_get_table_elem_type(
+ (WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
+ out_min_size, out_max_size);
+ }
+#endif
+ return false;
+}
+
+bool
+wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export, WASMType **out)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModule *module = (WASMModule *)module_comm;
+
+ if (export->index < module->import_function_count) {
+ *out = module->import_functions[export->index].u.function.func_type;
+ }
+ else {
+ *out =
+ module->functions[export->index - module->import_function_count]
+ ->func_type;
+ }
+ return true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_comm->module_type == Wasm_Module_AoT) {
+ AOTModule *module = (AOTModule *)module_comm;
+
+ if (export->index < module->import_func_count) {
+ *out = module->func_types[module->import_funcs[export->index]
+ .func_type_index];
+ }
+ else {
+ *out = module->func_types
+ [module->func_type_indexes[export->index
+ - module->import_func_count]];
+ }
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool
+wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export,
+ uint8 *out_val_type, bool *out_mutability)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModule *module = (WASMModule *)module_comm;
+
+ if (export->index < module->import_global_count) {
+ WASMGlobalImport *import_global =
+ &((module->import_globals + export->index)->u.global);
+ *out_val_type = import_global->type;
+ *out_mutability = import_global->is_mutable;
+ }
+ else {
+ WASMGlobal *global =
+ module->globals + (export->index - module->import_global_count);
+ *out_val_type = global->type;
+ *out_mutability = global->is_mutable;
+ }
+ return true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_comm->module_type == Wasm_Module_AoT) {
+ AOTModule *module = (AOTModule *)module_comm;
+
+ if (export->index < module->import_global_count) {
+ AOTImportGlobal *import_global =
+ module->import_globals + export->index;
+ *out_val_type = import_global->type;
+ *out_mutability = import_global->is_mutable;
+ }
+ else {
+ AOTGlobal *global =
+ module->globals + (export->index - module->import_global_count);
+ *out_val_type = global->type;
+ *out_mutability = global->is_mutable;
+ }
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool
+wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export,
+ uint32 *out_min_page, uint32 *out_max_page)
+{
+#if WASM_ENABLE_INTERP != 0
+ if (module_comm->module_type == Wasm_Module_Bytecode) {
+ WASMModule *module = (WASMModule *)module_comm;
+
+ if (export->index < module->import_memory_count) {
+ WASMMemoryImport *import_memory =
+ &((module->import_memories + export->index)->u.memory);
+ *out_min_page = import_memory->init_page_count;
+ *out_max_page = import_memory->max_page_count;
+ }
+ else {
+ WASMMemory *memory =
+ module->memories
+ + (export->index - module->import_memory_count);
+ *out_min_page = memory->init_page_count;
+ *out_max_page = memory->max_page_count;
+ }
+ return true;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_comm->module_type == Wasm_Module_AoT) {
+ AOTModule *module = (AOTModule *)module_comm;
+
+ if (export->index < module->import_memory_count) {
+ AOTImportMemory *import_memory =
+ module->import_memories + export->index;
+ *out_min_page = import_memory->mem_init_page_count;
+ *out_max_page = import_memory->mem_max_page_count;
+ }
+ else {
+ AOTMemory *memory = module->memories
+ + (export->index - module->import_memory_count);
+ *out_min_page = memory->mem_init_page_count;
+ *out_max_page = memory->mem_max_page_count;
+ }
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool
+wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export,
+ uint8 *out_elem_type, uint32 *out_min_size,
+ uint32 *out_max_size)
+{
+ return wasm_runtime_get_table_elem_type(
+ module_comm, export->index, out_elem_type, out_min_size, out_max_size);
+}
+
+static inline bool
+argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
+{
+ wasm_val_t *param = out_params;
+ uint32 i = 0, *u32;
+
+ for (i = 0; i < func_type->param_count; i++, param++) {
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+ param->kind = WASM_I32;
+ param->of.i32 = *argv++;
+ break;
+ case VALUE_TYPE_I64:
+ param->kind = WASM_I64;
+ u32 = (uint32 *)&param->of.i64;
+ u32[0] = *argv++;
+ u32[1] = *argv++;
+ break;
+ case VALUE_TYPE_F32:
+ param->kind = WASM_F32;
+ param->of.f32 = *(float32 *)argv++;
+ break;
+ case VALUE_TYPE_F64:
+ param->kind = WASM_F64;
+ u32 = (uint32 *)&param->of.i64;
+ u32[0] = *argv++;
+ u32[1] = *argv++;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ param->kind = WASM_ANYREF;
+
+ if (!wasm_externref_ref2obj(*argv,
+ (void **)&param->of.foreign)) {
+ return false;
+ }
+
+ argv++;
+ break;
+#endif
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static inline bool
+results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
+ const wasm_val_t *results, WASMType *func_type)
+{
+ const wasm_val_t *result = results;
+ uint32 *argv = out_argv, *u32, i;
+ uint8 *result_types = func_type->types + func_type->param_count;
+
+ for (i = 0; i < func_type->result_count; i++, result++) {
+ switch (result_types[i]) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+ *(int32 *)argv++ = result->of.i32;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ u32 = (uint32 *)&result->of.i64;
+ *argv++ = u32[0];
+ *argv++ = u32[1];
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ if (!wasm_externref_obj2ref(module_inst,
+ (void *)result->of.foreign, argv)) {
+ return false;
+ }
+ argv++;
+ break;
+#endif
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
+ void *func_ptr, WASMType *func_type,
+ uint32 argc, uint32 *argv, bool with_env,
+ void *wasm_c_api_env)
+{
+ wasm_val_t params_buf[16] = { 0 }, results_buf[4] = { 0 };
+ wasm_val_t *params = params_buf, *results = results_buf;
+ wasm_trap_t *trap = NULL;
+ bool ret = false;
+ wasm_val_vec_t params_vec, results_vec;
+
+ if (func_type->param_count > 16) {
+ if (!(params =
+ runtime_malloc(sizeof(wasm_val_t) * func_type->param_count,
+ module_inst, NULL, 0))) {
+ wasm_runtime_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+
+ if (!argv_to_params(params, argv, func_type)) {
+ wasm_runtime_set_exception(module_inst, "unsupported param type");
+ goto fail;
+ }
+
+ if (func_type->result_count > 4) {
+ if (!(results =
+ runtime_malloc(sizeof(wasm_val_t) * func_type->result_count,
+ module_inst, NULL, 0))) {
+ wasm_runtime_set_exception(module_inst, "allocate memory failed");
+ goto fail;
+ }
+ }
+
+ params_vec.data = params;
+ params_vec.num_elems = func_type->param_count;
+ params_vec.size = func_type->param_count;
+ params_vec.size_of_elem = sizeof(wasm_val_t);
+
+ results_vec.data = results;
+ results_vec.num_elems = 0;
+ results_vec.size = func_type->result_count;
+ results_vec.size_of_elem = sizeof(wasm_val_t);
+
+ if (!with_env) {
+ wasm_func_callback_t callback = (wasm_func_callback_t)func_ptr;
+ trap = callback(&params_vec, &results_vec);
+ }
+ else {
+ wasm_func_callback_with_env_t callback =
+ (wasm_func_callback_with_env_t)func_ptr;
+ trap = callback(wasm_c_api_env, &params_vec, &results_vec);
+ }
+
+ if (trap) {
+ if (trap->message->data) {
+ /* since trap->message->data does not end with '\0' */
+ char trap_message[108] = { 0 };
+ uint32 max_size_to_copy = (uint32)sizeof(trap_message) - 1;
+ uint32 size_to_copy = (trap->message->size < max_size_to_copy)
+ ? (uint32)trap->message->size
+ : max_size_to_copy;
+ bh_memcpy_s(trap_message, (uint32)sizeof(trap_message),
+ trap->message->data, size_to_copy);
+ wasm_runtime_set_exception(module_inst, trap_message);
+ }
+ else {
+ wasm_runtime_set_exception(
+ module_inst, "native function throw unknown exception");
+ }
+ wasm_trap_delete(trap);
+ goto fail;
+ }
+
+ if (!results_to_argv(module_inst, argv, results, func_type)) {
+ wasm_runtime_set_exception(module_inst, "unsupported result type");
+ goto fail;
+ }
+ results_vec.num_elems = func_type->result_count;
+ ret = true;
+
+fail:
+ if (params != params_buf)
+ wasm_runtime_free(params);
+ if (results != results_buf)
+ wasm_runtime_free(results);
+ return ret;
+}
+
+void
+wasm_runtime_show_app_heap_corrupted_prompt()
+{
+ LOG_ERROR("Error: app heap is corrupted, if the wasm file "
+ "is compiled by wasi-sdk-12.0 or higher version, "
+ "please add -Wl,--export=malloc -Wl,--export=free "
+ "to export malloc and free functions. If it is "
+ "compiled by asc, please add --exportRuntime to "
+ "export the runtime helpers.");
+}
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+void
+wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list)
+{
+ WASMCustomSection *section = section_list, *next;
+ while (section) {
+ next = section->next;
+ wasm_runtime_free(section);
+ section = next;
+ }
+}
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */
+
+void
+wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
+{
+ *major = WAMR_VERSION_MAJOR;
+ *minor = WAMR_VERSION_MINOR;
+ *patch = WAMR_VERSION_PATCH;
+}
+
+bool
+wasm_runtime_is_import_func_linked(const char *module_name,
+ const char *func_name)
+{
+ return wasm_native_resolve_symbol(module_name, func_name, NULL, NULL, NULL,
+ NULL);
+}
+
+bool
+wasm_runtime_is_import_global_linked(const char *module_name,
+ const char *global_name)
+{
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+ WASMGlobalImport global = { 0 };
+ return wasm_native_lookup_libc_builtin_global(module_name, global_name,
+ &global);
+#else
+ return false;
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.h
new file mode 100644
index 000000000..00d5ba237
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_runtime_common.h
@@ -0,0 +1,1010 @@
+/*
+ * 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 "wasm_exec_env.h"
+#include "wasm_native.h"
+#include "../include/wasm_export.h"
+#include "../interpreter/wasm.h"
+#if WASM_ENABLE_LIBC_WASI != 0
+#if WASM_ENABLE_UVWASI == 0
+#include "wasmtime_ssp.h"
+#include "posix.h"
+#else
+#include "uvwasi.h"
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Internal use for setting default running mode */
+#define Mode_Default 0
+
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+
+#define PUT_I64_TO_ADDR(addr, value) \
+ do { \
+ *(int64 *)(addr) = (int64)(value); \
+ } while (0)
+#define PUT_F64_TO_ADDR(addr, value) \
+ do { \
+ *(float64 *)(addr) = (float64)(value); \
+ } while (0)
+
+#define GET_I64_FROM_ADDR(addr) (*(int64 *)(addr))
+#define GET_F64_FROM_ADDR(addr) (*(float64 *)(addr))
+
+/* For STORE opcodes */
+#define STORE_I64 PUT_I64_TO_ADDR
+#define STORE_U32(addr, value) \
+ do { \
+ *(uint32 *)(addr) = (uint32)(value); \
+ } while (0)
+#define STORE_U16(addr, value) \
+ do { \
+ *(uint16 *)(addr) = (uint16)(value); \
+ } while (0)
+
+/* For LOAD opcodes */
+#define LOAD_I64(addr) (*(int64 *)(addr))
+#define LOAD_F64(addr) (*(float64 *)(addr))
+#define LOAD_I32(addr) (*(int32 *)(addr))
+#define LOAD_U32(addr) (*(uint32 *)(addr))
+#define LOAD_I16(addr) (*(int16 *)(addr))
+#define LOAD_U16(addr) (*(uint16 *)(addr))
+
+#define STORE_PTR(addr, ptr) \
+ do { \
+ *(void **)addr = (void *)ptr; \
+ } while (0)
+
+#else /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
+
+#define PUT_I64_TO_ADDR(addr, value) \
+ do { \
+ uint32 *addr_u32 = (uint32 *)(addr); \
+ union { \
+ int64 val; \
+ uint32 parts[2]; \
+ } u; \
+ u.val = (int64)(value); \
+ addr_u32[0] = u.parts[0]; \
+ addr_u32[1] = u.parts[1]; \
+ } while (0)
+#define PUT_F64_TO_ADDR(addr, value) \
+ do { \
+ uint32 *addr_u32 = (uint32 *)(addr); \
+ union { \
+ float64 val; \
+ uint32 parts[2]; \
+ } u; \
+ u.val = (value); \
+ addr_u32[0] = u.parts[0]; \
+ addr_u32[1] = u.parts[1]; \
+ } while (0)
+
+static inline int64
+GET_I64_FROM_ADDR(uint32 *addr)
+{
+ union {
+ int64 val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = addr[0];
+ u.parts[1] = addr[1];
+ return u.val;
+}
+
+static inline float64
+GET_F64_FROM_ADDR(uint32 *addr)
+{
+ union {
+ float64 val;
+ uint32 parts[2];
+ } u;
+ u.parts[0] = addr[0];
+ u.parts[1] = addr[1];
+ return u.val;
+}
+
+/* For STORE opcodes */
+#define STORE_I64(addr, value) \
+ do { \
+ uintptr_t addr_ = (uintptr_t)(addr); \
+ union { \
+ int64 val; \
+ uint32 u32[2]; \
+ uint16 u16[4]; \
+ uint8 u8[8]; \
+ } u; \
+ if ((addr_ & (uintptr_t)7) == 0) \
+ *(int64 *)(addr) = (int64)(value); \
+ else { \
+ u.val = (int64)(value); \
+ if ((addr_ & (uintptr_t)3) == 0) { \
+ ((uint32 *)(addr))[0] = u.u32[0]; \
+ ((uint32 *)(addr))[1] = u.u32[1]; \
+ } \
+ else if ((addr_ & (uintptr_t)1) == 0) { \
+ ((uint16 *)(addr))[0] = u.u16[0]; \
+ ((uint16 *)(addr))[1] = u.u16[1]; \
+ ((uint16 *)(addr))[2] = u.u16[2]; \
+ ((uint16 *)(addr))[3] = u.u16[3]; \
+ } \
+ else { \
+ int32 t; \
+ for (t = 0; t < 8; t++) \
+ ((uint8 *)(addr))[t] = u.u8[t]; \
+ } \
+ } \
+ } while (0)
+
+#define STORE_U32(addr, value) \
+ do { \
+ uintptr_t addr_ = (uintptr_t)(addr); \
+ union { \
+ uint32 val; \
+ uint16 u16[2]; \
+ uint8 u8[4]; \
+ } u; \
+ if ((addr_ & (uintptr_t)3) == 0) \
+ *(uint32 *)(addr) = (uint32)(value); \
+ else { \
+ u.val = (uint32)(value); \
+ if ((addr_ & (uintptr_t)1) == 0) { \
+ ((uint16 *)(addr))[0] = u.u16[0]; \
+ ((uint16 *)(addr))[1] = u.u16[1]; \
+ } \
+ else { \
+ ((uint8 *)(addr))[0] = u.u8[0]; \
+ ((uint8 *)(addr))[1] = u.u8[1]; \
+ ((uint8 *)(addr))[2] = u.u8[2]; \
+ ((uint8 *)(addr))[3] = u.u8[3]; \
+ } \
+ } \
+ } while (0)
+
+#define STORE_U16(addr, value) \
+ do { \
+ union { \
+ uint16 val; \
+ uint8 u8[2]; \
+ } u; \
+ u.val = (uint16)(value); \
+ ((uint8 *)(addr))[0] = u.u8[0]; \
+ ((uint8 *)(addr))[1] = u.u8[1]; \
+ } while (0)
+
+/* For LOAD opcodes */
+static inline int64
+LOAD_I64(void *addr)
+{
+ uintptr_t addr1 = (uintptr_t)addr;
+ union {
+ int64 val;
+ uint32 u32[2];
+ uint16 u16[4];
+ uint8 u8[8];
+ } u;
+ if ((addr1 & (uintptr_t)7) == 0)
+ return *(int64 *)addr;
+
+ if ((addr1 & (uintptr_t)3) == 0) {
+ u.u32[0] = ((uint32 *)addr)[0];
+ u.u32[1] = ((uint32 *)addr)[1];
+ }
+ else if ((addr1 & (uintptr_t)1) == 0) {
+ u.u16[0] = ((uint16 *)addr)[0];
+ u.u16[1] = ((uint16 *)addr)[1];
+ u.u16[2] = ((uint16 *)addr)[2];
+ u.u16[3] = ((uint16 *)addr)[3];
+ }
+ else {
+ int32 t;
+ for (t = 0; t < 8; t++)
+ u.u8[t] = ((uint8 *)addr)[t];
+ }
+ return u.val;
+}
+
+static inline float64
+LOAD_F64(void *addr)
+{
+ uintptr_t addr1 = (uintptr_t)addr;
+ union {
+ float64 val;
+ uint32 u32[2];
+ uint16 u16[4];
+ uint8 u8[8];
+ } u;
+ if ((addr1 & (uintptr_t)7) == 0)
+ return *(float64 *)addr;
+
+ if ((addr1 & (uintptr_t)3) == 0) {
+ u.u32[0] = ((uint32 *)addr)[0];
+ u.u32[1] = ((uint32 *)addr)[1];
+ }
+ else if ((addr1 & (uintptr_t)1) == 0) {
+ u.u16[0] = ((uint16 *)addr)[0];
+ u.u16[1] = ((uint16 *)addr)[1];
+ u.u16[2] = ((uint16 *)addr)[2];
+ u.u16[3] = ((uint16 *)addr)[3];
+ }
+ else {
+ int32 t;
+ for (t = 0; t < 8; t++)
+ u.u8[t] = ((uint8 *)addr)[t];
+ }
+ return u.val;
+}
+
+static inline int32
+LOAD_I32(void *addr)
+{
+ uintptr_t addr1 = (uintptr_t)addr;
+ union {
+ int32 val;
+ uint16 u16[2];
+ uint8 u8[4];
+ } u;
+ if ((addr1 & (uintptr_t)3) == 0)
+ return *(int32 *)addr;
+
+ if ((addr1 & (uintptr_t)1) == 0) {
+ u.u16[0] = ((uint16 *)addr)[0];
+ u.u16[1] = ((uint16 *)addr)[1];
+ }
+ else {
+ u.u8[0] = ((uint8 *)addr)[0];
+ u.u8[1] = ((uint8 *)addr)[1];
+ u.u8[2] = ((uint8 *)addr)[2];
+ u.u8[3] = ((uint8 *)addr)[3];
+ }
+ return u.val;
+}
+
+static inline int16
+LOAD_I16(void *addr)
+{
+ uintptr_t addr1 = (uintptr_t)addr;
+ union {
+ int16 val;
+ uint8 u8[2];
+ } u;
+ if ((addr1 & (uintptr_t)1)) {
+ u.u8[0] = ((uint8 *)addr)[0];
+ u.u8[1] = ((uint8 *)addr)[1];
+ return u.val;
+ }
+ return *(int16 *)addr;
+}
+
+#define LOAD_U32(addr) ((uint32)LOAD_I32(addr))
+#define LOAD_U16(addr) ((uint16)LOAD_I16(addr))
+
+#if UINTPTR_MAX == UINT32_MAX
+#define STORE_PTR(addr, ptr) STORE_U32(addr, (uintptr_t)ptr)
+#elif UINTPTR_MAX == UINT64_MAX
+#define STORE_PTR(addr, ptr) STORE_I64(addr, (uintptr_t)ptr)
+#endif
+
+#endif /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
+
+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;
+
+ /* The following uint8[1] member is a dummy just to indicate
+ some module_type dependent members follow.
+ Typically it should be accessed by casting to the corresponding
+ actual module_type dependent structure, not via this member. */
+ 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;
+
+ /* The following uint8[1] member is a dummy just to indicate
+ some module_type dependent members follow.
+ Typically it should be accessed by casting to the corresponding
+ actual module_type dependent structure, not via this member. */
+ uint8 module_inst_data[1];
+} WASMModuleInstanceCommon;
+
+typedef struct WASMModuleMemConsumption {
+ uint32 total_size;
+ uint32 module_struct_size;
+ uint32 types_size;
+ uint32 imports_size;
+ uint32 functions_size;
+ uint32 tables_size;
+ uint32 memories_size;
+ uint32 globals_size;
+ uint32 exports_size;
+ uint32 table_segs_size;
+ uint32 data_segs_size;
+ uint32 const_strs_size;
+#if WASM_ENABLE_AOT != 0
+ uint32 aot_code_size;
+#endif
+} WASMModuleMemConsumption;
+
+typedef struct WASMModuleInstMemConsumption {
+ uint32 total_size;
+ uint32 module_inst_struct_size;
+ uint32 memories_size;
+ uint32 app_heap_size;
+ uint32 tables_size;
+ uint32 globals_size;
+ uint32 functions_size;
+ uint32 exports_size;
+} WASMModuleInstMemConsumption;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+#if WASM_ENABLE_UVWASI == 0
+typedef struct WASIContext {
+ struct fd_table *curfds;
+ struct fd_prestats *prestats;
+ struct argv_environ_values *argv_environ;
+ struct addr_pool *addr_pool;
+ char *ns_lookup_buf;
+ char **ns_lookup_list;
+ char *argv_buf;
+ char **argv_list;
+ char *env_buf;
+ char **env_list;
+ uint32_t exit_code;
+} WASIContext;
+#else
+typedef struct WASIContext {
+ uvwasi_t uvwasi;
+ uint32_t exit_code;
+} WASIContext;
+#endif
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+typedef struct WASMRegisteredModule {
+ bh_list_link l;
+ /* point to a string pool */
+ const char *module_name;
+ WASMModuleCommon *module;
+ /* to store the original module file buffer address */
+ uint8 *orig_file_buf;
+ uint32 orig_file_buf_size;
+} WASMRegisteredModule;
+#endif
+
+typedef struct WASMMemoryInstanceCommon {
+ uint32 module_type;
+
+ /* The following uint8[1] member is a dummy just to indicate
+ some module_type dependent members follow.
+ Typically it should be accessed by casting to the corresponding
+ actual module_type dependent structure, not via this member. */
+ uint8 memory_inst_data[1];
+} WASMMemoryInstanceCommon;
+
+typedef package_type_t PackageType;
+typedef wasm_section_t WASMSection, AOTSection;
+
+typedef struct wasm_frame_t {
+ /* wasm_instance_t */
+ void *instance;
+ uint32 module_offset;
+ uint32 func_index;
+ uint32 func_offset;
+ const char *func_name_wp;
+} WASMCApiFrame;
+
+#ifdef WASM_ENABLE_JIT
+typedef struct LLVMJITOptions {
+ uint32 opt_level;
+ uint32 size_level;
+} LLVMJITOptions;
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+/* Signal info passing to interp/aot signal handler */
+typedef struct WASMSignalInfo {
+ WASMExecEnv *exec_env_tls;
+#ifndef BH_PLATFORM_WINDOWS
+ void *sig_addr;
+#else
+ EXCEPTION_POINTERS *exce_info;
+#endif
+} WASMSignalInfo;
+
+/* Set exec_env of thread local storage */
+void
+wasm_runtime_set_exec_env_tls(WASMExecEnv *exec_env);
+
+/* Get exec_env of thread local storage */
+WASMExecEnv *
+wasm_runtime_get_exec_env_tls(void);
+#endif
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_init(void);
+
+/* Internal API */
+RunningMode
+wasm_runtime_get_default_running_mode(void);
+
+#if WASM_ENABLE_JIT != 0
+/* Internal API */
+LLVMJITOptions
+wasm_runtime_get_llvm_jit_options(void);
+#endif
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_full_init(RuntimeInitArgs *init_args);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_running_mode_supported(RunningMode running_mode);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_default_running_mode(RunningMode running_mode);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy(void);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN PackageType
+get_package_type(const uint8 *buf, uint32 size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_xip_file(const uint8 *buf, uint32 size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMModuleCommon *
+wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
+ uint32 error_buf_size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMModuleCommon *
+wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
+ char *error_buf, uint32 error_buf_size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_unload(WASMModuleCommon *module);
+
+/* Internal API */
+WASMModuleInstanceCommon *
+wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
+ WASMExecEnv *exec_env_main, uint32 stack_size,
+ uint32 heap_size, char *error_buf,
+ uint32 error_buf_size);
+
+/* Internal API */
+void
+wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
+ bool is_sub_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
+wasm_runtime_instantiate(WASMModuleCommon *module, uint32 default_stack_size,
+ uint32 host_managed_heap_size, char *error_buf,
+ uint32 error_buf_size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
+ RunningMode running_mode);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN RunningMode
+wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMModuleCommon *
+wasm_runtime_get_module(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
+wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
+ const char *name, const char *signature);
+
+/* Internal API */
+WASMType *
+wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
+ uint32 module_type);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst,
+ wasm_valkind_t *param_types);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst,
+ WASMModuleInstanceCommon *const module_inst,
+ wasm_valkind_t *result_types);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMExecEnv *
+wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
+ uint32 stack_size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
+wasm_runtime_get_module_inst(WASMExecEnv *exec_env);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_module_inst(WASMExecEnv *exec_env,
+ WASMModuleInstanceCommon *const module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_function_attachment(WASMExecEnv *exec_env);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_user_data(WASMExecEnv *exec_env);
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+/* Access exception check guard page to trigger the signal handler */
+void
+wasm_runtime_access_exce_check_guard_page();
+#endif
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function, uint32 argc,
+ uint32 argv[]);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function,
+ uint32 num_results, wasm_val_t *results,
+ uint32 num_args, wasm_val_t *args);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
+ WASMFunctionInstanceCommon *function,
+ uint32 num_results, wasm_val_t *results,
+ uint32 num_args, ...);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
+ uint32 argc, uint32 argv[]);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_runtime_start_debug_instance_with_port(WASMExecEnv *exec_env,
+ int32_t port);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_runtime_start_debug_instance(WASMExecEnv *exec_env);
+#endif
+
+bool
+wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMExecEnv *
+wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
+ char *argv[]);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
+ const char *name, int32 argc, char *argv[]);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_exception(WASMModuleInstanceCommon *module,
+ const char *exception);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN const char *
+wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
+
+/* Internal API */
+void
+wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,
+ void *custom_data);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst,
+ void *custom_data);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst);
+
+/* Internal API */
+uint32
+wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst,
+ WASMExecEnv *exec_env, uint32 size,
+ void **p_native_addr);
+
+/* Internal API */
+uint32
+wasm_runtime_module_realloc_internal(WASMModuleInstanceCommon *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr,
+ uint32 size, void **p_native_addr);
+
+/* Internal API */
+void
+wasm_runtime_module_free_internal(WASMModuleInstanceCommon *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size,
+ void **p_native_addr);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst,
+ const char *src, uint32 size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst,
+ uint32 app_offset, uint32 size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst,
+ uint32 app_str_offset);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst,
+ void *native_ptr, uint32 size);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst,
+ uint32 app_offset);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32
+wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst,
+ void *native_ptr);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst,
+ uint32 app_offset, uint32 *p_app_start_offset,
+ uint32 *p_app_end_offset);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
+ uint8 *native_ptr,
+ uint8 **p_native_start_addr,
+ uint8 **p_native_end_addr);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN const uint8 *
+wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
+ const char *name, uint32 *len);
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_module_reader(const module_reader reader,
+ const module_destroyer destroyer);
+
+module_reader
+wasm_runtime_get_module_reader();
+
+module_destroyer
+wasm_runtime_get_module_destroyer();
+
+bool
+wasm_runtime_register_module_internal(const char *module_name,
+ WASMModuleCommon *module,
+ uint8 *orig_file_buf,
+ uint32 orig_file_buf_size,
+ char *error_buf, uint32 error_buf_size);
+
+void
+wasm_runtime_unregister_module(const WASMModuleCommon *module);
+
+bool
+wasm_runtime_add_loading_module(const char *module_name, char *error_buf,
+ uint32 error_buf_size);
+
+void
+wasm_runtime_delete_loading_module(const char *module_name);
+
+bool
+wasm_runtime_is_loading_module(const char *module_name);
+
+void
+wasm_runtime_destroy_loading_module_list();
+#endif /* WASM_ENALBE_MULTI_MODULE */
+
+bool
+wasm_runtime_is_built_in_module(const char *module_name);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset,
+ uint32 *size);
+
+bool
+wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset,
+ uint32 size);
+#endif
+
+#if WASM_ENABLE_LIBC_WASI != 0
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_args_ex(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, char *argv[], int argc,
+ int stdinfd, int stdoutfd, int stderrfd);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN 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, char *argv[], int argc);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
+wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_get_wasi_exit_code(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 *addr_pool[], uint32 addr_pool_size,
+ const char *ns_lookup_pool[], uint32 ns_lookup_pool_size,
+ char *argv[], uint32 argc, int stdinfd, int stdoutfd,
+ int stderrfd, 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);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_addr_pool(wasm_module_t module, const char *addr_pool[],
+ uint32 addr_pool_size);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_ns_lookup_pool(wasm_module_t module,
+ const char *ns_lookup_pool[],
+ uint32 ns_lookup_pool_size);
+#endif /* end of WASM_ENABLE_LIBC_WASI */
+
+#if WASM_ENABLE_REF_TYPES != 0
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
+ uint32 *p_externref_idx);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_retain(uint32 externref_idx);
+
+/**
+ * Reclaim the externref objects/indexes which are not used by
+ * module instance
+ */
+void
+wasm_externref_reclaim(WASMModuleInstanceCommon *module_inst);
+
+/**
+ * Cleanup the externref objects/indexes of the module instance
+ */
+void
+wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst);
+#endif /* end of WASM_ENABLE_REF_TYPES */
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+/**
+ * @brief Internal implementation for dumping or printing callstack line
+ *
+ * @note if dump_or_print is true, then print to stdout directly;
+ * if dump_or_print is false, but *buf is NULL, then return the length of the
+ * line;
+ * if dump_or_print is false, and *buf is not NULL, then dump content to
+ * the memory pointed by *buf, and adjust *buf and *len according to actual
+ * bytes dumped, and return the actual dumped length
+ *
+ * @param line_buf current line to dump or print
+ * @param dump_or_print whether to print to stdout or dump to buf
+ * @param buf [INOUT] pointer to the buffer
+ * @param len [INOUT] pointer to remaining length
+ * @return bytes printed to stdout or dumped to buf
+ */
+uint32
+wasm_runtime_dump_line_buf_impl(const char *line_buf, bool dump_or_print,
+ char **buf, uint32 *len);
+#endif /* end of WASM_ENABLE_DUMP_CALL_STACK != 0 */
+
+/* Get module of the current exec_env */
+WASMModuleCommon *
+wasm_exec_env_get_module(WASMExecEnv *exec_env);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_register_natives(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_register_natives_raw(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32 n_native_symbols);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_unregister_natives(const char *module_name,
+ NativeSymbol *native_symbols);
+
+bool
+wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type, const char *signature,
+ void *attachment, uint32 *argv, uint32 argc,
+ uint32 *ret);
+
+bool
+wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMType *func_type, const char *signature,
+ void *attachment, uint32 *argv, uint32 argc,
+ uint32 *ret);
+
+void
+wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2);
+
+void
+wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module);
+
+void
+wasm_runtime_dump_module_inst_mem_consumption(
+ const WASMModuleInstanceCommon *module_inst);
+
+void
+wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
+
+bool
+wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
+ uint32 table_idx, uint8 *out_elem_type,
+ uint32 *out_min_size, uint32 *out_max_size);
+
+bool
+wasm_runtime_get_table_inst_elem_type(
+ const WASMModuleInstanceCommon *module_inst_comm, uint32 table_idx,
+ uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size);
+
+bool
+wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export_, WASMType **out);
+
+bool
+wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export_,
+ uint8 *out_val_type, bool *out_mutability);
+
+bool
+wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export_,
+ uint32 *out_min_page, uint32 *out_max_page);
+
+bool
+wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
+ const WASMExport *export_,
+ uint8 *out_elem_type, uint32 *out_min_size,
+ uint32 *out_max_size);
+
+bool
+wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
+ void *func_ptr, WASMType *func_type,
+ uint32 argc, uint32 *argv, bool with_env,
+ void *wasm_c_api_env);
+
+void
+wasm_runtime_show_app_heap_corrupted_prompt();
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+void
+wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
+#endif
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_func_linked(const char *module_name,
+ const char *func_name);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_global_linked(const char *module_name,
+ const char *global_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_COMMON_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.c
new file mode 100644
index 000000000..54fc8200f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "wasm_shared_memory.h"
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#endif
+
+static bh_list shared_memory_list_head;
+static bh_list *const shared_memory_list = &shared_memory_list_head;
+static korp_mutex shared_memory_list_lock;
+
+/* clang-format off */
+enum {
+ S_WAITING,
+ S_NOTIFIED
+};
+/* clang-format on */
+
+typedef struct AtomicWaitInfo {
+ bh_list wait_list_head;
+ bh_list *wait_list;
+ /* WARNING: insert to the list allowed only in acquire_wait_info
+ otherwise there will be data race as described in PR #2016 */
+} AtomicWaitInfo;
+
+typedef struct AtomicWaitNode {
+ bh_list_link l;
+ uint8 status;
+ korp_cond wait_cond;
+} AtomicWaitNode;
+
+/* Atomic wait map */
+static HashMap *wait_map;
+
+static uint32
+wait_address_hash(void *address);
+
+static bool
+wait_address_equal(void *h1, void *h2);
+
+static void
+destroy_wait_info(void *wait_info);
+
+bool
+wasm_shared_memory_init()
+{
+ if (os_mutex_init(&shared_memory_list_lock) != 0)
+ return false;
+
+ /* wait map not exists, create new map */
+ if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash,
+ (KeyEqualFunc)wait_address_equal, NULL,
+ destroy_wait_info))) {
+ os_mutex_destroy(&shared_memory_list_lock);
+ return false;
+ }
+
+ return true;
+}
+
+void
+wasm_shared_memory_destroy()
+{
+ bh_hash_map_destroy(wait_map);
+ os_mutex_destroy(&shared_memory_list_lock);
+}
+
+static WASMSharedMemNode *
+search_module(WASMModuleCommon *module)
+{
+ WASMSharedMemNode *node;
+
+ os_mutex_lock(&shared_memory_list_lock);
+ node = bh_list_first_elem(shared_memory_list);
+
+ while (node) {
+ if (module == node->module) {
+ os_mutex_unlock(&shared_memory_list_lock);
+ return node;
+ }
+ node = bh_list_elem_next(node);
+ }
+
+ os_mutex_unlock(&shared_memory_list_lock);
+ return NULL;
+}
+
+WASMSharedMemNode *
+wasm_module_get_shared_memory(WASMModuleCommon *module)
+{
+ return search_module(module);
+}
+
+int32
+shared_memory_inc_reference(WASMModuleCommon *module)
+{
+ WASMSharedMemNode *node = search_module(module);
+ uint32 ref_count = -1;
+ if (node) {
+ os_mutex_lock(&node->lock);
+ ref_count = ++node->ref_count;
+ os_mutex_unlock(&node->lock);
+ }
+ return ref_count;
+}
+
+int32
+shared_memory_dec_reference(WASMModuleCommon *module)
+{
+ WASMSharedMemNode *node = search_module(module);
+ uint32 ref_count = 0;
+ if (node) {
+ os_mutex_lock(&node->lock);
+ ref_count = --node->ref_count;
+ os_mutex_unlock(&node->lock);
+ if (ref_count == 0) {
+ os_mutex_lock(&shared_memory_list_lock);
+ bh_list_remove(shared_memory_list, node);
+ os_mutex_unlock(&shared_memory_list_lock);
+
+ os_mutex_destroy(&node->shared_mem_lock);
+ os_mutex_destroy(&node->lock);
+ wasm_runtime_free(node);
+ }
+ return ref_count;
+ }
+
+ return -1;
+}
+
+WASMMemoryInstanceCommon *
+shared_memory_get_memory_inst(WASMSharedMemNode *node)
+{
+ return node->memory_inst;
+}
+
+WASMSharedMemNode *
+shared_memory_set_memory_inst(WASMModuleCommon *module,
+ WASMMemoryInstanceCommon *memory)
+{
+ WASMSharedMemNode *node;
+ bh_list_status ret;
+
+ if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode))))
+ return NULL;
+
+ node->module = module;
+ node->memory_inst = memory;
+ node->ref_count = 1;
+
+ if (os_mutex_init(&node->shared_mem_lock) != 0) {
+ wasm_runtime_free(node);
+ return NULL;
+ }
+
+ if (os_mutex_init(&node->lock) != 0) {
+ os_mutex_destroy(&node->shared_mem_lock);
+ wasm_runtime_free(node);
+ return NULL;
+ }
+
+ os_mutex_lock(&shared_memory_list_lock);
+ ret = bh_list_insert(shared_memory_list, node);
+ bh_assert(ret == BH_LIST_SUCCESS);
+ os_mutex_unlock(&shared_memory_list_lock);
+
+ (void)ret;
+ return node;
+}
+
+/* Atomics wait && notify APIs */
+static uint32
+wait_address_hash(void *address)
+{
+ return (uint32)(uintptr_t)address;
+}
+
+static bool
+wait_address_equal(void *h1, void *h2)
+{
+ return h1 == h2 ? true : false;
+}
+
+static bool
+is_wait_node_exists(bh_list *wait_list, AtomicWaitNode *node)
+{
+ AtomicWaitNode *curr;
+ curr = bh_list_first_elem(wait_list);
+
+ while (curr) {
+ if (curr == node) {
+ return true;
+ }
+ curr = bh_list_elem_next(curr);
+ }
+
+ return false;
+}
+
+static uint32
+notify_wait_list(bh_list *wait_list, uint32 count)
+{
+ AtomicWaitNode *node, *next;
+ uint32 i, notify_count = count;
+
+ if (count > wait_list->len)
+ notify_count = wait_list->len;
+
+ node = bh_list_first_elem(wait_list);
+ if (!node)
+ return 0;
+
+ for (i = 0; i < notify_count; i++) {
+ bh_assert(node);
+ next = bh_list_elem_next(node);
+
+ node->status = S_NOTIFIED;
+ /* wakeup */
+ os_cond_signal(&node->wait_cond);
+
+ node = next;
+ }
+
+ return notify_count;
+}
+
+static AtomicWaitInfo *
+acquire_wait_info(void *address, AtomicWaitNode *wait_node)
+{
+ AtomicWaitInfo *wait_info = NULL;
+ bh_list_status ret;
+
+ if (address)
+ wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address);
+
+ if (!wait_node) {
+ return wait_info;
+ }
+
+ /* No wait info on this address, create new info */
+ if (!wait_info) {
+ if (!(wait_info = (AtomicWaitInfo *)wasm_runtime_malloc(
+ sizeof(AtomicWaitInfo)))) {
+ return NULL;
+ }
+ memset(wait_info, 0, sizeof(AtomicWaitInfo));
+
+ /* init wait list */
+ wait_info->wait_list = &wait_info->wait_list_head;
+ ret = bh_list_init(wait_info->wait_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+ (void)ret;
+
+ if (!bh_hash_map_insert(wait_map, address, (void *)wait_info)) {
+ wasm_runtime_free(wait_info);
+ return NULL;
+ }
+ }
+
+ ret = bh_list_insert(wait_info->wait_list, wait_node);
+ bh_assert(ret == BH_LIST_SUCCESS);
+ (void)ret;
+
+ return wait_info;
+}
+
+static void
+destroy_wait_info(void *wait_info)
+{
+ AtomicWaitNode *node, *next;
+
+ if (wait_info) {
+
+ node = bh_list_first_elem(((AtomicWaitInfo *)wait_info)->wait_list);
+
+ while (node) {
+ next = bh_list_elem_next(node);
+ os_cond_destroy(&node->wait_cond);
+ wasm_runtime_free(node);
+ node = next;
+ }
+
+ wasm_runtime_free(wait_info);
+ }
+}
+
+static void
+map_try_release_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info,
+ void *address)
+{
+ if (wait_info->wait_list->len > 0) {
+ return;
+ }
+
+ bh_hash_map_remove(wait_map_, address, NULL, NULL);
+ destroy_wait_info(wait_info);
+}
+
+uint32
+wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
+ uint64 expect, int64 timeout, bool wait64)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
+ AtomicWaitInfo *wait_info;
+ AtomicWaitNode *wait_node;
+ WASMSharedMemNode *node;
+#if WASM_ENABLE_THREAD_MGR != 0
+ WASMExecEnv *exec_env;
+#endif
+ uint64 timeout_left, timeout_wait, timeout_1sec;
+ bool check_ret, is_timeout, no_wait;
+
+ bh_assert(module->module_type == Wasm_Module_Bytecode
+ || module->module_type == Wasm_Module_AoT);
+
+ if (wasm_copy_exception(module_inst, NULL)) {
+ return -1;
+ }
+
+ /* Currently we have only one memory instance */
+ if (!module_inst->memories[0]->is_shared) {
+ wasm_runtime_set_exception(module, "expected shared memory");
+ return -1;
+ }
+
+ if ((uint8 *)address < module_inst->memories[0]->memory_data
+ || (uint8 *)address + (wait64 ? 8 : 4)
+ > module_inst->memories[0]->memory_data_end) {
+ wasm_runtime_set_exception(module, "out of bounds memory access");
+ return -1;
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ exec_env =
+ wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
+ bh_assert(exec_env);
+#endif
+
+ node = search_module((WASMModuleCommon *)module_inst->module);
+ bh_assert(node);
+
+ /* Lock the shared_mem_lock for the whole atomic wait process,
+ and use it to os_cond_reltimedwait */
+ os_mutex_lock(&node->shared_mem_lock);
+
+ no_wait = (!wait64 && *(uint32 *)address != (uint32)expect)
+ || (wait64 && *(uint64 *)address != expect);
+
+ if (no_wait) {
+ os_mutex_unlock(&node->shared_mem_lock);
+ return 1;
+ }
+
+ if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
+ os_mutex_unlock(&node->shared_mem_lock);
+ wasm_runtime_set_exception(module, "failed to create wait node");
+ return -1;
+ }
+ memset(wait_node, 0, sizeof(AtomicWaitNode));
+
+ if (0 != os_cond_init(&wait_node->wait_cond)) {
+ os_mutex_unlock(&node->shared_mem_lock);
+ wasm_runtime_free(wait_node);
+ wasm_runtime_set_exception(module, "failed to init wait cond");
+ return -1;
+ }
+
+ wait_node->status = S_WAITING;
+
+ /* Acquire the wait info, create new one if not exists */
+ wait_info = acquire_wait_info(address, wait_node);
+
+ if (!wait_info) {
+ os_mutex_unlock(&node->shared_mem_lock);
+ os_cond_destroy(&wait_node->wait_cond);
+ wasm_runtime_free(wait_node);
+ wasm_runtime_set_exception(module, "failed to acquire wait_info");
+ return -1;
+ }
+
+ /* unit of timeout is nsec, convert it to usec */
+ timeout_left = (uint64)timeout / 1000;
+ timeout_1sec = (uint64)1e6;
+
+ while (1) {
+ if (timeout < 0) {
+ /* wait forever until it is notified or terminatied
+ here we keep waiting and checking every second */
+ os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock,
+ (uint64)timeout_1sec);
+ if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* terminated by other thread */
+ || wasm_cluster_is_thread_terminated(exec_env)
+#endif
+ ) {
+ break;
+ }
+ }
+ else {
+ timeout_wait =
+ timeout_left < timeout_1sec ? timeout_left : timeout_1sec;
+ os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock,
+ timeout_wait);
+ if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */
+ || timeout_left <= timeout_wait /* time out */
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* terminated by other thread */
+ || wasm_cluster_is_thread_terminated(exec_env)
+#endif
+ ) {
+ break;
+ }
+ timeout_left -= timeout_wait;
+ }
+ }
+
+ is_timeout = wait_node->status == S_WAITING ? true : false;
+
+ check_ret = is_wait_node_exists(wait_info->wait_list, wait_node);
+ bh_assert(check_ret);
+ (void)check_ret;
+
+ /* Remove wait node from wait list */
+ bh_list_remove(wait_info->wait_list, wait_node);
+ os_cond_destroy(&wait_node->wait_cond);
+ wasm_runtime_free(wait_node);
+
+ /* Release wait info if no wait nodes are attached */
+ map_try_release_wait_info(wait_map, wait_info, address);
+
+ os_mutex_unlock(&node->shared_mem_lock);
+
+ return is_timeout ? 2 : 0;
+}
+
+uint32
+wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
+ uint32 count)
+{
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
+ uint32 notify_result;
+ AtomicWaitInfo *wait_info;
+ WASMSharedMemNode *node;
+ bool out_of_bounds;
+
+ bh_assert(module->module_type == Wasm_Module_Bytecode
+ || module->module_type == Wasm_Module_AoT);
+
+ out_of_bounds =
+ ((uint8 *)address < module_inst->memories[0]->memory_data
+ || (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end);
+
+ if (out_of_bounds) {
+ wasm_runtime_set_exception(module, "out of bounds memory access");
+ return -1;
+ }
+
+ /* Currently we have only one memory instance */
+ if (!module_inst->memories[0]->is_shared) {
+ /* Always return 0 for ushared linear memory since there is
+ no way to create a waiter on it */
+ return 0;
+ }
+
+ node = search_module((WASMModuleCommon *)module_inst->module);
+ bh_assert(node);
+
+ /* Lock the shared_mem_lock for the whole atomic notify process,
+ and use it to os_cond_signal */
+ os_mutex_lock(&node->shared_mem_lock);
+
+ wait_info = acquire_wait_info(address, NULL);
+
+ /* Nobody wait on this address */
+ if (!wait_info) {
+ os_mutex_unlock(&node->shared_mem_lock);
+ return 0;
+ }
+
+ /* Notify each wait node in the wait list */
+ notify_result = notify_wait_list(wait_info->wait_list, count);
+
+ os_mutex_unlock(&node->shared_mem_lock);
+
+ return notify_result;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.h
new file mode 100644
index 000000000..6c1c49210
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common/wasm_shared_memory.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_SHARED_MEMORY_H
+#define _WASM_SHARED_MEMORY_H
+
+#include "bh_common.h"
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct WASMSharedMemNode {
+ bh_list_link l;
+ /* Lock */
+ korp_mutex lock;
+ /* The module reference */
+ WASMModuleCommon *module;
+ /* The memory information */
+ WASMMemoryInstanceCommon *memory_inst;
+ /* Lock used for atomic operations */
+ korp_mutex shared_mem_lock;
+
+ /* reference count */
+ uint32 ref_count;
+} WASMSharedMemNode;
+
+bool
+wasm_shared_memory_init();
+
+void
+wasm_shared_memory_destroy();
+
+WASMSharedMemNode *
+wasm_module_get_shared_memory(WASMModuleCommon *module);
+
+int32
+shared_memory_inc_reference(WASMModuleCommon *module);
+
+int32
+shared_memory_dec_reference(WASMModuleCommon *module);
+
+WASMMemoryInstanceCommon *
+shared_memory_get_memory_inst(WASMSharedMemNode *node);
+
+WASMSharedMemNode *
+shared_memory_set_memory_inst(WASMModuleCommon *module,
+ WASMMemoryInstanceCommon *memory);
+
+uint32
+wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
+ uint64 expect, int64 timeout, bool wait64);
+
+uint32
+wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
+ uint32 count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_SHARED_MEMORY_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.c
new file mode 100644
index 000000000..e836df28f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot.h"
+
+static char aot_error[128];
+
+char *
+aot_get_last_error()
+{
+ return aot_error[0] == '\0' ? "" : aot_error;
+}
+
+void
+aot_set_last_error_v(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vsnprintf(aot_error, sizeof(aot_error), format, args);
+ va_end(args);
+}
+
+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_runtime_free(data_list[i]);
+ wasm_runtime_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_runtime_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_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ data_list[i]->is_passive = module->data_segments[i]->is_passive;
+ data_list[i]->memory_index = module->data_segments[i]->memory_index;
+#endif
+ 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_runtime_free(data_list[i]);
+ wasm_runtime_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_runtime_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_runtime_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;
+ data_list[i]->mode = module->table_segments[i].mode;
+ data_list[i]->elem_type = module->table_segments[i].elem_type;
+ /* runtime control it */
+ data_list[i]->is_dropped = false;
+ data_list[i]->table_index = module->table_segments[i].table_index;
+ bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
+ &module->table_segments[i].base_offset,
+ sizeof(AOTInitExpr));
+ data_list[i]->func_index_count =
+ module->table_segments[i].function_count;
+ bh_memcpy_s(data_list[i]->func_indexes,
+ sizeof(uint32) * module->table_segments[i].function_count,
+ 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_runtime_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_runtime_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_runtime_free(func_types[i]);
+ wasm_runtime_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_runtime_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_runtime_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_runtime_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;
+ import_funcs[i].signature = import_func->signature;
+ import_funcs[i].attachment = import_func->attachment;
+ import_funcs[i].call_conv_raw = import_func->call_conv_raw;
+ import_funcs[i].call_conv_wasm_c_api = false;
+ /* 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_runtime_free(funcs[i]);
+ wasm_runtime_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_runtime_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_runtime_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]->param_cell_num = func->param_cell_num;
+ funcs[i]->local_cell_num = func->local_cell_num;
+ funcs[i]->code = func->code;
+ funcs[i]->code_size = func->code_size;
+ }
+
+ return funcs;
+
+fail:
+ aot_destroy_funcs(funcs, module->function_count);
+ return NULL;
+}
+
+AOTCompData *
+aot_create_comp_data(WASMModule *module)
+{
+ AOTCompData *comp_data;
+ uint32 import_global_data_size = 0, global_data_size = 0, i, j;
+ uint64 size;
+
+ /* Allocate memory */
+ if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
+ aot_set_last_error("create compile data failed.\n");
+ return NULL;
+ }
+
+ memset(comp_data, 0, sizeof(AOTCompData));
+
+ comp_data->memory_count =
+ module->import_memory_count + module->memory_count;
+
+ /* TODO: create import memories */
+
+ /* Allocate memory for memory array, reserve one AOTMemory space at least */
+ if (!comp_data->memory_count)
+ comp_data->memory_count = 1;
+
+ size = (uint64)comp_data->memory_count * sizeof(AOTMemory);
+ if (size >= UINT32_MAX
+ || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("create memories array failed.\n");
+ goto fail;
+ }
+ memset(comp_data->memories, 0, size);
+
+ if (!(module->import_memory_count + module->memory_count)) {
+ comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+ }
+
+ /* Set memory page count */
+ for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
+ if (i < module->import_memory_count) {
+ comp_data->memories[i].memory_flags =
+ module->import_memories[i].u.memory.flags;
+ comp_data->memories[i].num_bytes_per_page =
+ module->import_memories[i].u.memory.num_bytes_per_page;
+ comp_data->memories[i].mem_init_page_count =
+ module->import_memories[i].u.memory.init_page_count;
+ comp_data->memories[i].mem_max_page_count =
+ module->import_memories[i].u.memory.max_page_count;
+ comp_data->memories[i].num_bytes_per_page =
+ module->import_memories[i].u.memory.num_bytes_per_page;
+ }
+ else {
+ j = i - module->import_memory_count;
+ comp_data->memories[i].memory_flags = module->memories[j].flags;
+ comp_data->memories[i].num_bytes_per_page =
+ module->memories[j].num_bytes_per_page;
+ comp_data->memories[i].mem_init_page_count =
+ module->memories[j].init_page_count;
+ comp_data->memories[i].mem_max_page_count =
+ module->memories[j].max_page_count;
+ comp_data->memories[i].num_bytes_per_page =
+ module->memories[j].num_bytes_per_page;
+ }
+ }
+
+ /* 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;
+
+ /* Create tables */
+ comp_data->table_count = module->import_table_count + module->table_count;
+
+ if (comp_data->table_count > 0) {
+ size = sizeof(AOTTable) * (uint64)comp_data->table_count;
+ if (size >= UINT32_MAX
+ || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("create memories array failed.\n");
+ goto fail;
+ }
+ memset(comp_data->tables, 0, size);
+ for (i = 0; i < comp_data->table_count; i++) {
+ if (i < module->import_table_count) {
+ comp_data->tables[i].elem_type =
+ module->import_tables[i].u.table.elem_type;
+ comp_data->tables[i].table_flags =
+ module->import_tables[i].u.table.flags;
+ comp_data->tables[i].table_init_size =
+ module->import_tables[i].u.table.init_size;
+ comp_data->tables[i].table_max_size =
+ module->import_tables[i].u.table.max_size;
+ comp_data->tables[i].possible_grow =
+ module->import_tables[i].u.table.possible_grow;
+ }
+ else {
+ j = i - module->import_table_count;
+ comp_data->tables[i].elem_type = module->tables[j].elem_type;
+ comp_data->tables[i].table_flags = module->tables[j].flags;
+ comp_data->tables[i].table_init_size =
+ module->tables[j].init_size;
+ comp_data->tables[i].table_max_size =
+ module->tables[j].max_size;
+ comp_data->tables[i].possible_grow =
+ module->tables[j].possible_grow;
+ }
+ }
+ }
+
+ /* 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;
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ /* Create custom name section */
+ comp_data->name_section_buf = module->name_section_buf;
+ comp_data->name_section_buf_end = module->name_section_buf_end;
+#endif
+
+ /* Create aux data/heap/stack information */
+ comp_data->aux_data_end_global_index = module->aux_data_end_global_index;
+ comp_data->aux_data_end = module->aux_data_end;
+ comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index;
+ comp_data->aux_heap_base = module->aux_heap_base;
+ comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index;
+ comp_data->aux_stack_bottom = module->aux_stack_bottom;
+ comp_data->aux_stack_size = module->aux_stack_size;
+
+ comp_data->start_func_index = module->start_function;
+ comp_data->malloc_func_index = module->malloc_function;
+ comp_data->free_func_index = module->free_function;
+ comp_data->retain_func_index = module->retain_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->import_memories)
+ wasm_runtime_free(comp_data->import_memories);
+
+ if (comp_data->memories)
+ wasm_runtime_free(comp_data->memories);
+
+ 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->import_tables)
+ wasm_runtime_free(comp_data->import_tables);
+
+ if (comp_data->tables)
+ wasm_runtime_free(comp_data->tables);
+
+ 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_runtime_free(comp_data->import_globals);
+
+ if (comp_data->globals)
+ wasm_runtime_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_runtime_free(comp_data->import_funcs);
+
+ if (comp_data->funcs)
+ aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
+
+ if (comp_data->aot_name_section_buf)
+ wasm_runtime_free(comp_data->aot_name_section_buf);
+
+ wasm_runtime_free(comp_data);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.h
new file mode 100644
index 000000000..c67251a6f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot.h
@@ -0,0 +1,335 @@
+/*
+ * 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
+
+#ifndef AOT_FUNC_PREFIX
+#define AOT_FUNC_PREFIX "aot_func#"
+#endif
+
+typedef InitializerExpression AOTInitExpr;
+typedef WASMType AOTFuncType;
+typedef WASMExport AOTExport;
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+typedef void *dwar_extractor_handle_t;
+#endif
+
+typedef enum AOTIntCond {
+ 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
+} AOTIntCond;
+
+typedef enum AOTFloatCond {
+ FLOAT_EQ = 0,
+ FLOAT_NE,
+ FLOAT_LT,
+ FLOAT_GT,
+ FLOAT_LE,
+ FLOAT_GE,
+ FLOAT_UNO
+} AOTFloatCond;
+
+/**
+ * Import memory
+ */
+typedef struct AOTImportMemory {
+ char *module_name;
+ char *memory_name;
+ uint32 memory_flags;
+ uint32 num_bytes_per_page;
+ uint32 mem_init_page_count;
+ uint32 mem_max_page_count;
+} AOTImportMemory;
+
+/**
+ * Memory information
+ */
+typedef struct AOTMemory {
+ /* memory info */
+ uint32 memory_flags;
+ uint32 num_bytes_per_page;
+ uint32 mem_init_page_count;
+ uint32 mem_max_page_count;
+} AOTMemory;
+
+/**
+ * A segment of memory init data
+ */
+typedef struct AOTMemInitData {
+#if WASM_ENABLE_BULK_MEMORY != 0
+ /* Passive flag */
+ bool is_passive;
+ /* memory index */
+ uint32 memory_index;
+#endif
+ /* Start address of init data */
+ AOTInitExpr offset;
+ /* Byte count */
+ uint32 byte_count;
+ /* Byte array */
+ uint8 bytes[1];
+} AOTMemInitData;
+
+/**
+ * Import table
+ */
+typedef struct AOTImportTable {
+ char *module_name;
+ char *table_name;
+ uint32 elem_type;
+ uint32 table_flags;
+ uint32 table_init_size;
+ uint32 table_max_size;
+ bool possible_grow;
+} AOTImportTable;
+
+/**
+ * Table
+ */
+typedef struct AOTTable {
+ uint32 elem_type;
+ uint32 table_flags;
+ uint32 table_init_size;
+ uint32 table_max_size;
+ bool possible_grow;
+} AOTTable;
+
+/**
+ * A segment of table init data
+ */
+typedef struct AOTTableInitData {
+ /* 0 to 7 */
+ uint32 mode;
+ /* funcref or externref, elemkind will be considered as funcref */
+ uint32 elem_type;
+ bool is_dropped;
+ /* optional, only for active */
+ uint32 table_index;
+ /* 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;
+ bool is_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;
+ /* signature from registered native symbols */
+ const char *signature;
+ /* attachment */
+ void *attachment;
+ bool call_conv_raw;
+ bool call_conv_wasm_c_api;
+ bool wasm_c_api_with_env;
+} AOTImportFunc;
+
+/**
+ * Function
+ */
+typedef struct AOTFunc {
+ AOTFuncType *func_type;
+ uint32 func_type_index;
+ uint32 local_count;
+ uint8 *local_types;
+ uint16 param_cell_num;
+ uint16 local_cell_num;
+ uint32 code_size;
+ uint8 *code;
+} AOTFunc;
+
+typedef struct AOTCompData {
+ /* Import memories */
+ uint32 import_memory_count;
+ AOTImportMemory *import_memories;
+
+ /* Memories */
+ uint32 memory_count;
+ AOTMemory *memories;
+
+ /* Memory init data info */
+ uint32 mem_init_data_count;
+ AOTMemInitData **mem_init_data_list;
+
+ /* Import tables */
+ uint32 import_table_count;
+ AOTImportTable *import_tables;
+
+ /* Tables */
+ uint32 table_count;
+ AOTTable *tables;
+
+ /* Table init data info */
+ uint32 table_init_data_count;
+ AOTTableInitData **table_init_data_list;
+
+ /* Import globals */
+ uint32 import_global_count;
+ AOTImportGlobal *import_globals;
+
+ /* Globals */
+ uint32 global_count;
+ AOTGlobal *globals;
+
+ /* Function types */
+ uint32 func_type_count;
+ AOTFuncType **func_types;
+
+ /* Import functions */
+ uint32 import_func_count;
+ AOTImportFunc *import_funcs;
+
+ /* Functions */
+ uint32 func_count;
+ AOTFunc **funcs;
+
+ /* Custom name sections */
+ const uint8 *name_section_buf;
+ const uint8 *name_section_buf_end;
+ uint8 *aot_name_section_buf;
+ uint32 aot_name_section_size;
+
+ uint32 global_data_size;
+
+ uint32 start_func_index;
+ uint32 malloc_func_index;
+ uint32 free_func_index;
+ uint32 retain_func_index;
+
+ uint32 aux_data_end_global_index;
+ uint32 aux_data_end;
+ uint32 aux_heap_base_global_index;
+ uint32 aux_heap_base;
+ uint32 aux_stack_top_global_index;
+ uint32 aux_stack_bottom;
+ uint32 aux_stack_size;
+
+ WASMModule *wasm_module;
+#if WASM_ENABLE_DEBUG_AOT != 0
+ dwar_extractor_handle_t extractor;
+#endif
+} AOTCompData;
+
+typedef struct AOTNativeSymbol {
+ bh_list_link link;
+ char symbol[32];
+ int32 index;
+} AOTNativeSymbol;
+
+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);
+
+void
+aot_set_last_error_v(const char *format, ...);
+
+#if BH_DEBUG != 0
+#define HANDLE_FAILURE(callee) \
+ do { \
+ aot_set_last_error_v("call %s failed in %s:%d", (callee), \
+ __FUNCTION__, __LINE__); \
+ } while (0)
+#else
+#define HANDLE_FAILURE(callee) \
+ do { \
+ aot_set_last_error_v("call %s failed", (callee)); \
+ } while (0)
+#endif
+
+static inline uint32
+aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode)
+{
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (is_jit_mode)
+ return tbl->table_max_size;
+#else
+ (void)is_jit_mode;
+#endif
+ return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
+}
+
+static inline uint32
+aot_get_tbl_data_slots(const AOTTable *tbl, bool is_jit_mode)
+{
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (is_jit_mode)
+ return tbl->table_max_size;
+#else
+ (void)is_jit_mode;
+#endif
+ return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
+}
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.c
new file mode 100644
index 000000000..06235fe31
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.c
@@ -0,0 +1,2921 @@
+/*
+ * 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 "aot_emit_table.h"
+#include "simd/simd_access_lanes.h"
+#include "simd/simd_bitmask_extracts.h"
+#include "simd/simd_bit_shifts.h"
+#include "simd/simd_bitwise_ops.h"
+#include "simd/simd_bool_reductions.h"
+#include "simd/simd_comparisons.h"
+#include "simd/simd_conversions.h"
+#include "simd/simd_construct_values.h"
+#include "simd/simd_conversions.h"
+#include "simd/simd_floating_point.h"
+#include "simd/simd_int_arith.h"
+#include "simd/simd_load_store.h"
+#include "simd/simd_sat_int_arith.h"
+#include "../aot/aot_runtime.h"
+#include "../interpreter/wasm_opcode.h"
+#include <errno.h>
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+#include "debug/dwarf_extractor.h"
+#endif
+
+#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 + 6) / 7) {
+ aot_set_last_error("read leb failed: "
+ "integer representation too long");
+ return false;
+ }
+ if (sign && (shift < maxbits) && (byte & 0x40)) {
+ /* Sign extend */
+ result |= (~((uint64)0)) << 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)
+
+/**
+ * Since Wamrc uses a full feature Wasm loader,
+ * add a post-validator here to run checks according
+ * to options, like enable_tail_call, enable_ref_types,
+ * and so on.
+ */
+static bool
+aot_validate_wasm(AOTCompContext *comp_ctx)
+{
+ if (!comp_ctx->enable_ref_types) {
+ /* Doesn't support multiple tables unless enabling reference type */
+ if (comp_ctx->comp_data->import_table_count
+ + comp_ctx->comp_data->table_count
+ > 1) {
+ aot_set_last_error("multiple tables");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#define COMPILE_ATOMIC_RMW(OP, NAME) \
+ case WASM_OP_ATOMIC_RMW_I32_##NAME: \
+ bytes = 4; \
+ op_type = VALUE_TYPE_I32; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME: \
+ bytes = 8; \
+ op_type = VALUE_TYPE_I64; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I32_##NAME##8_U: \
+ bytes = 1; \
+ op_type = VALUE_TYPE_I32; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I32_##NAME##16_U: \
+ bytes = 2; \
+ op_type = VALUE_TYPE_I32; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME##8_U: \
+ bytes = 1; \
+ op_type = VALUE_TYPE_I64; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME##16_U: \
+ bytes = 2; \
+ op_type = VALUE_TYPE_I64; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME##32_U: \
+ bytes = 4; \
+ op_type = VALUE_TYPE_I64; \
+ OP_ATOMIC_##OP : bin_op = LLVMAtomicRMWBinOp##OP; \
+ goto build_atomic_rmw;
+
+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;
+ uint8 *param_types = NULL;
+ uint8 *result_types = NULL;
+ uint8 value_type;
+ uint16 param_count;
+ uint16 result_count;
+ uint32 br_depth, *br_depths, br_count;
+ uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i;
+ uint32 bytes = 4, align, offset;
+ uint32 type_index;
+ bool sign = true;
+ int32 i32_const;
+ int64 i64_const;
+ float32 f32_const;
+ float64 f64_const;
+ AOTFuncType *func_type = NULL;
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMMetadataRef location;
+#endif
+
+ /* 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++;
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ location = dwarf_gen_location(
+ comp_ctx, func_ctx,
+ (frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
+ LLVMSetCurrentDebugLocation2(comp_ctx->builder, location);
+#endif
+
+ 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:
+ {
+ value_type = *frame_ip++;
+ if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_I64
+ || value_type == VALUE_TYPE_F32
+ || value_type == VALUE_TYPE_F64
+ || value_type == VALUE_TYPE_V128
+ || value_type == VALUE_TYPE_VOID
+ || value_type == VALUE_TYPE_FUNCREF
+ || value_type == VALUE_TYPE_EXTERNREF) {
+ param_count = 0;
+ param_types = NULL;
+ if (value_type == VALUE_TYPE_VOID) {
+ result_count = 0;
+ result_types = NULL;
+ }
+ else {
+ result_count = 1;
+ result_types = &value_type;
+ }
+ }
+ else {
+ frame_ip--;
+ read_leb_uint32(frame_ip, frame_ip_end, type_index);
+ func_type = comp_ctx->comp_data->func_types[type_index];
+ param_count = func_type->param_count;
+ param_types = func_type->types;
+ result_count = func_type->result_count;
+ result_types = func_type->types + param_count;
+ }
+ if (!aot_compile_op_block(
+ comp_ctx, func_ctx, &frame_ip, frame_ip_end,
+ (uint32)(LABEL_TYPE_BLOCK + opcode - WASM_OP_BLOCK),
+ param_count, param_types, result_count, result_types))
+ return false;
+ break;
+ }
+
+ case EXT_OP_BLOCK:
+ case EXT_OP_LOOP:
+ case EXT_OP_IF:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, type_index);
+ func_type = comp_ctx->comp_data->func_types[type_index];
+ param_count = func_type->param_count;
+ param_types = func_type->types;
+ result_count = func_type->result_count;
+ result_types = func_type->types + param_count;
+ if (!aot_compile_op_block(
+ comp_ctx, func_ctx, &frame_ip, frame_ip_end,
+ (uint32)(LABEL_TYPE_BLOCK + opcode - EXT_OP_BLOCK),
+ param_count, param_types, result_count, result_types))
+ 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_runtime_malloc((uint32)sizeof(uint32)
+ * (br_count + 1)))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ for (i = 0; i <= br_count; i++)
+ read_leb_uint32(frame_ip, frame_ip_end, br_depths[i]);
+#else
+ for (i = 0; i <= br_count; i++)
+ br_depths[i] = *frame_ip++;
+#endif
+
+ if (!aot_compile_op_br_table(comp_ctx, func_ctx, br_depths,
+ br_count, &frame_ip)) {
+ wasm_runtime_free(br_depths);
+ return false;
+ }
+
+ wasm_runtime_free(br_depths);
+ break;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ case EXT_OP_BR_TABLE_CACHE:
+ {
+ BrTableCache *node = bh_list_first_elem(
+ comp_ctx->comp_data->wasm_module->br_table_cache_list);
+ BrTableCache *node_next;
+ uint8 *p_opcode = frame_ip - 1;
+
+ read_leb_uint32(frame_ip, frame_ip_end, br_count);
+
+ while (node) {
+ node_next = bh_list_elem_next(node);
+ if (node->br_table_op_addr == p_opcode) {
+ br_depths = node->br_depths;
+ if (!aot_compile_op_br_table(comp_ctx, func_ctx,
+ br_depths, br_count,
+ &frame_ip)) {
+ return false;
+ }
+ break;
+ }
+ node = node_next;
+ }
+ bh_assert(node);
+
+ break;
+ }
+#endif
+
+ 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, false))
+ return false;
+ break;
+
+ case WASM_OP_CALL_INDIRECT:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, type_idx);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (comp_ctx->enable_ref_types) {
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ }
+ else
+#endif
+ {
+ frame_ip++;
+ tbl_idx = 0;
+ }
+
+ if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx,
+ tbl_idx))
+ return false;
+ break;
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL:
+ if (!comp_ctx->enable_tail_call) {
+ aot_set_last_error("unsupported opcode");
+ return false;
+ }
+ read_leb_uint32(frame_ip, frame_ip_end, func_idx);
+ if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, true))
+ return false;
+ if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_RETURN_CALL_INDIRECT:
+ {
+ uint32 tbl_idx;
+
+ if (!comp_ctx->enable_tail_call) {
+ aot_set_last_error("unsupported opcode");
+ return false;
+ }
+
+ read_leb_uint32(frame_ip, frame_ip_end, type_idx);
+#if WASM_ENABLE_REF_TYPES != 0
+ if (comp_ctx->enable_ref_types) {
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ }
+ else
+#endif
+ {
+ frame_ip++;
+ tbl_idx = 0;
+ }
+
+ if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx,
+ tbl_idx))
+ return false;
+ if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip))
+ return false;
+ break;
+ }
+#endif /* end of WASM_ENABLE_TAIL_CALL */
+
+ case WASM_OP_DROP:
+ 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:
+ 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;
+
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_SELECT_T:
+ {
+ uint32 vec_len;
+
+ if (!comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+
+ read_leb_uint32(frame_ip, frame_ip_end, vec_len);
+ bh_assert(vec_len == 1);
+ (void)vec_len;
+
+ type_idx = *frame_ip++;
+ if (!aot_compile_op_select(comp_ctx, func_ctx,
+ (type_idx != VALUE_TYPE_I64)
+ && (type_idx != VALUE_TYPE_F64)))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_GET:
+ {
+ uint32 tbl_idx;
+
+ if (!comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!aot_compile_op_table_get(comp_ctx, func_ctx, tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_SET:
+ {
+ uint32 tbl_idx;
+
+ if (!comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!aot_compile_op_table_set(comp_ctx, func_ctx, tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_REF_NULL:
+ {
+ uint32 type;
+
+ if (!comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+
+ read_leb_uint32(frame_ip, frame_ip_end, type);
+
+ if (!aot_compile_op_ref_null(comp_ctx, func_ctx))
+ return false;
+
+ (void)type;
+ break;
+ }
+ case WASM_OP_REF_IS_NULL:
+ {
+ if (!comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+
+ if (!aot_compile_op_ref_is_null(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+ case WASM_OP_REF_FUNC:
+ {
+ if (!comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+
+ read_leb_uint32(frame_ip, frame_ip_end, func_idx);
+ if (!aot_compile_op_ref_func(comp_ctx, func_ctx, func_idx))
+ return false;
+ break;
+ }
+#endif
+
+ 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:
+ case WASM_OP_GET_GLOBAL_64:
+ 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:
+ case WASM_OP_SET_GLOBAL_64:
+ case WASM_OP_SET_GLOBAL_AUX_STACK:
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ if (!aot_compile_op_set_global(
+ comp_ctx, func_ctx, global_idx,
+ opcode == WASM_OP_SET_GLOBAL_AUX_STACK ? true : false))
+ 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, false))
+ 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, false))
+ 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, false))
+ 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, false))
+ 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,
+ false))
+ 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,
+ false))
+ 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,
+ false))
+ 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,
+ false))
+ 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;
+
+ case WASM_OP_I32_EXTEND8_S:
+ if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 8))
+ return false;
+ break;
+
+ case WASM_OP_I32_EXTEND16_S:
+ if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 16))
+ return false;
+ break;
+
+ case WASM_OP_I64_EXTEND8_S:
+ if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 8))
+ return false;
+ break;
+
+ case WASM_OP_I64_EXTEND16_S:
+ if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 16))
+ return false;
+ break;
+
+ case WASM_OP_I64_EXTEND32_S:
+ if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 32))
+ return false;
+ break;
+
+ case WASM_OP_MISC_PREFIX:
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(frame_ip, frame_ip_end, opcode1);
+ opcode = (uint32)opcode1;
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if (WASM_OP_MEMORY_INIT <= opcode
+ && opcode <= WASM_OP_MEMORY_FILL
+ && !comp_ctx->enable_bulk_memory) {
+ goto unsupport_bulk_memory;
+ }
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (WASM_OP_TABLE_INIT <= opcode && opcode <= WASM_OP_TABLE_FILL
+ && !comp_ctx->enable_ref_types) {
+ goto unsupport_ref_types;
+ }
+#endif
+
+ switch (opcode) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F32) ? true
+ : false;
+ if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx,
+ sign, true))
+ return false;
+ break;
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F64) ? true
+ : false;
+ if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx,
+ sign, true))
+ return false;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F32) ? true
+ : false;
+ if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx,
+ sign, true))
+ return false;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F64) ? true
+ : false;
+ if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx,
+ sign, true))
+ return false;
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ {
+ uint32 seg_index;
+ read_leb_uint32(frame_ip, frame_ip_end, seg_index);
+ frame_ip++;
+ if (!aot_compile_op_memory_init(comp_ctx, func_ctx,
+ seg_index))
+ return false;
+ break;
+ }
+ case WASM_OP_DATA_DROP:
+ {
+ uint32 seg_index;
+ read_leb_uint32(frame_ip, frame_ip_end, seg_index);
+ if (!aot_compile_op_data_drop(comp_ctx, func_ctx,
+ seg_index))
+ return false;
+ break;
+ }
+ case WASM_OP_MEMORY_COPY:
+ {
+ frame_ip += 2;
+ if (!aot_compile_op_memory_copy(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+ case WASM_OP_MEMORY_FILL:
+ {
+ frame_ip++;
+ if (!aot_compile_op_memory_fill(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ {
+ uint32 tbl_idx, tbl_seg_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx);
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!aot_compile_op_table_init(comp_ctx, func_ctx,
+ tbl_idx, tbl_seg_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_ELEM_DROP:
+ {
+ uint32 tbl_seg_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx);
+ if (!aot_compile_op_elem_drop(comp_ctx, func_ctx,
+ tbl_seg_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_COPY:
+ {
+ uint32 src_tbl_idx, dst_tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
+ read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx);
+ if (!aot_compile_op_table_copy(
+ comp_ctx, func_ctx, src_tbl_idx, dst_tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_GROW:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!aot_compile_op_table_grow(comp_ctx, func_ctx,
+ tbl_idx))
+ return false;
+ break;
+ }
+
+ case WASM_OP_TABLE_SIZE:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!aot_compile_op_table_size(comp_ctx, func_ctx,
+ tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_FILL:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!aot_compile_op_table_fill(comp_ctx, func_ctx,
+ tbl_idx))
+ return false;
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ aot_set_last_error("unsupported opcode");
+ return false;
+ }
+ break;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case WASM_OP_ATOMIC_PREFIX:
+ {
+ uint8 bin_op, op_type;
+
+ if (frame_ip < frame_ip_end) {
+ opcode = *frame_ip++;
+ }
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ }
+ switch (opcode) {
+ case WASM_OP_ATOMIC_WAIT32:
+ if (!aot_compile_op_atomic_wait(comp_ctx, func_ctx,
+ VALUE_TYPE_I32, align,
+ offset, 4))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_WAIT64:
+ if (!aot_compile_op_atomic_wait(comp_ctx, func_ctx,
+ VALUE_TYPE_I64, align,
+ offset, 8))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_NOTIFY:
+ if (!aot_compiler_op_atomic_notify(
+ comp_ctx, func_ctx, align, offset, bytes))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_FENCE:
+ /* Skip memory index */
+ frame_ip++;
+ if (!aot_compiler_op_atomic_fence(comp_ctx, func_ctx))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_I32_LOAD:
+ bytes = 4;
+ goto op_atomic_i32_load;
+ case WASM_OP_ATOMIC_I32_LOAD8_U:
+ bytes = 1;
+ goto op_atomic_i32_load;
+ case WASM_OP_ATOMIC_I32_LOAD16_U:
+ bytes = 2;
+ op_atomic_i32_load:
+ if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align,
+ offset, bytes, sign, true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_I64_LOAD:
+ bytes = 8;
+ goto op_atomic_i64_load;
+ case WASM_OP_ATOMIC_I64_LOAD8_U:
+ bytes = 1;
+ goto op_atomic_i64_load;
+ case WASM_OP_ATOMIC_I64_LOAD16_U:
+ bytes = 2;
+ goto op_atomic_i64_load;
+ case WASM_OP_ATOMIC_I64_LOAD32_U:
+ bytes = 4;
+ op_atomic_i64_load:
+ if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align,
+ offset, bytes, sign, true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_I32_STORE:
+ bytes = 4;
+ goto op_atomic_i32_store;
+ case WASM_OP_ATOMIC_I32_STORE8:
+ bytes = 1;
+ goto op_atomic_i32_store;
+ case WASM_OP_ATOMIC_I32_STORE16:
+ bytes = 2;
+ op_atomic_i32_store:
+ if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align,
+ offset, bytes, true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_I64_STORE:
+ bytes = 8;
+ goto op_atomic_i64_store;
+ case WASM_OP_ATOMIC_I64_STORE8:
+ bytes = 1;
+ goto op_atomic_i64_store;
+ case WASM_OP_ATOMIC_I64_STORE16:
+ bytes = 2;
+ goto op_atomic_i64_store;
+ case WASM_OP_ATOMIC_I64_STORE32:
+ bytes = 4;
+ op_atomic_i64_store:
+ if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align,
+ offset, bytes, true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
+ bytes = 4;
+ op_type = VALUE_TYPE_I32;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
+ bytes = 8;
+ op_type = VALUE_TYPE_I64;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U:
+ bytes = 1;
+ op_type = VALUE_TYPE_I32;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
+ bytes = 2;
+ op_type = VALUE_TYPE_I32;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U:
+ bytes = 1;
+ op_type = VALUE_TYPE_I64;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U:
+ bytes = 2;
+ op_type = VALUE_TYPE_I64;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
+ bytes = 4;
+ op_type = VALUE_TYPE_I64;
+ op_atomic_cmpxchg:
+ if (!aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx,
+ op_type, align,
+ offset, bytes))
+ return false;
+ break;
+
+ COMPILE_ATOMIC_RMW(Add, ADD);
+ COMPILE_ATOMIC_RMW(Sub, SUB);
+ COMPILE_ATOMIC_RMW(And, AND);
+ COMPILE_ATOMIC_RMW(Or, OR);
+ COMPILE_ATOMIC_RMW(Xor, XOR);
+ COMPILE_ATOMIC_RMW(Xchg, XCHG);
+
+ build_atomic_rmw:
+ if (!aot_compile_op_atomic_rmw(comp_ctx, func_ctx,
+ bin_op, op_type, align,
+ offset, bytes))
+ return false;
+ break;
+
+ default:
+ aot_set_last_error("unsupported opcode");
+ return false;
+ }
+ break;
+ }
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
+
+#if WASM_ENABLE_SIMD != 0
+ case WASM_OP_SIMD_PREFIX:
+ {
+ if (!comp_ctx->enable_simd) {
+ goto unsupport_simd;
+ }
+
+ opcode = *frame_ip++;
+ /* follow the order of enum WASMSimdEXTOpcode in
+ wasm_opcode.h */
+ switch (opcode) {
+ /* Memory instruction */
+ case SIMD_v128_load:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_v128_load(comp_ctx, func_ctx,
+ align, offset))
+ return false;
+ break;
+ }
+
+ case SIMD_v128_load8x8_s:
+ case SIMD_v128_load8x8_u:
+ case SIMD_v128_load16x4_s:
+ case SIMD_v128_load16x4_u:
+ case SIMD_v128_load32x2_s:
+ case SIMD_v128_load32x2_u:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_load_extend(
+ comp_ctx, func_ctx, opcode, align, offset))
+ return false;
+ break;
+ }
+
+ case SIMD_v128_load8_splat:
+ case SIMD_v128_load16_splat:
+ case SIMD_v128_load32_splat:
+ case SIMD_v128_load64_splat:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_load_splat(comp_ctx, func_ctx,
+ opcode, align, offset))
+ return false;
+ break;
+ }
+
+ case SIMD_v128_store:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_v128_store(comp_ctx, func_ctx,
+ align, offset))
+ return false;
+ break;
+ }
+
+ /* Basic operation */
+ case SIMD_v128_const:
+ {
+ if (!aot_compile_simd_v128_const(comp_ctx, func_ctx,
+ frame_ip))
+ return false;
+ frame_ip += 16;
+ break;
+ }
+
+ case SIMD_v8x16_shuffle:
+ {
+ if (!aot_compile_simd_shuffle(comp_ctx, func_ctx,
+ frame_ip))
+ return false;
+ frame_ip += 16;
+ break;
+ }
+
+ case SIMD_v8x16_swizzle:
+ {
+ if (!aot_compile_simd_swizzle(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ /* Splat operation */
+ case SIMD_i8x16_splat:
+ case SIMD_i16x8_splat:
+ case SIMD_i32x4_splat:
+ case SIMD_i64x2_splat:
+ case SIMD_f32x4_splat:
+ case SIMD_f64x2_splat:
+ {
+ if (!aot_compile_simd_splat(comp_ctx, func_ctx, opcode))
+ return false;
+ break;
+ }
+
+ /* Lane operation */
+ case SIMD_i8x16_extract_lane_s:
+ case SIMD_i8x16_extract_lane_u:
+ {
+ if (!aot_compile_simd_extract_i8x16(
+ comp_ctx, func_ctx, *frame_ip++,
+ SIMD_i8x16_extract_lane_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_replace_lane:
+ {
+ if (!aot_compile_simd_replace_i8x16(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_extract_lane_s:
+ case SIMD_i16x8_extract_lane_u:
+ {
+ if (!aot_compile_simd_extract_i16x8(
+ comp_ctx, func_ctx, *frame_ip++,
+ SIMD_i16x8_extract_lane_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_replace_lane:
+ {
+ if (!aot_compile_simd_replace_i16x8(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_extract_lane:
+ {
+ if (!aot_compile_simd_extract_i32x4(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_replace_lane:
+ {
+ if (!aot_compile_simd_replace_i32x4(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_extract_lane:
+ {
+ if (!aot_compile_simd_extract_i64x2(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_replace_lane:
+ {
+ if (!aot_compile_simd_replace_i64x2(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_extract_lane:
+ {
+ if (!aot_compile_simd_extract_f32x4(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_replace_lane:
+ {
+ if (!aot_compile_simd_replace_f32x4(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_extract_lane:
+ {
+ if (!aot_compile_simd_extract_f64x2(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_replace_lane:
+ {
+ if (!aot_compile_simd_replace_f64x2(comp_ctx, func_ctx,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ /* i8x16 Cmp */
+ case SIMD_i8x16_eq:
+ case SIMD_i8x16_ne:
+ case SIMD_i8x16_lt_s:
+ case SIMD_i8x16_lt_u:
+ case SIMD_i8x16_gt_s:
+ case SIMD_i8x16_gt_u:
+ case SIMD_i8x16_le_s:
+ case SIMD_i8x16_le_u:
+ case SIMD_i8x16_ge_s:
+ case SIMD_i8x16_ge_u:
+ {
+ if (!aot_compile_simd_i8x16_compare(
+ comp_ctx, func_ctx,
+ INT_EQ + opcode - SIMD_i8x16_eq))
+ return false;
+ break;
+ }
+
+ /* i16x8 Cmp */
+ case SIMD_i16x8_eq:
+ case SIMD_i16x8_ne:
+ case SIMD_i16x8_lt_s:
+ case SIMD_i16x8_lt_u:
+ case SIMD_i16x8_gt_s:
+ case SIMD_i16x8_gt_u:
+ case SIMD_i16x8_le_s:
+ case SIMD_i16x8_le_u:
+ case SIMD_i16x8_ge_s:
+ case SIMD_i16x8_ge_u:
+ {
+ if (!aot_compile_simd_i16x8_compare(
+ comp_ctx, func_ctx,
+ INT_EQ + opcode - SIMD_i16x8_eq))
+ return false;
+ break;
+ }
+
+ /* i32x4 Cmp */
+ case SIMD_i32x4_eq:
+ case SIMD_i32x4_ne:
+ case SIMD_i32x4_lt_s:
+ case SIMD_i32x4_lt_u:
+ case SIMD_i32x4_gt_s:
+ case SIMD_i32x4_gt_u:
+ case SIMD_i32x4_le_s:
+ case SIMD_i32x4_le_u:
+ case SIMD_i32x4_ge_s:
+ case SIMD_i32x4_ge_u:
+ {
+ if (!aot_compile_simd_i32x4_compare(
+ comp_ctx, func_ctx,
+ INT_EQ + opcode - SIMD_i32x4_eq))
+ return false;
+ break;
+ }
+
+ /* f32x4 Cmp */
+ case SIMD_f32x4_eq:
+ case SIMD_f32x4_ne:
+ case SIMD_f32x4_lt:
+ case SIMD_f32x4_gt:
+ case SIMD_f32x4_le:
+ case SIMD_f32x4_ge:
+ {
+ if (!aot_compile_simd_f32x4_compare(
+ comp_ctx, func_ctx,
+ FLOAT_EQ + opcode - SIMD_f32x4_eq))
+ return false;
+ break;
+ }
+
+ /* f64x2 Cmp */
+ case SIMD_f64x2_eq:
+ case SIMD_f64x2_ne:
+ case SIMD_f64x2_lt:
+ case SIMD_f64x2_gt:
+ case SIMD_f64x2_le:
+ case SIMD_f64x2_ge:
+ {
+ if (!aot_compile_simd_f64x2_compare(
+ comp_ctx, func_ctx,
+ FLOAT_EQ + opcode - SIMD_f64x2_eq))
+ return false;
+ break;
+ }
+
+ /* v128 Op */
+ case SIMD_v128_not:
+ case SIMD_v128_and:
+ case SIMD_v128_andnot:
+ case SIMD_v128_or:
+ case SIMD_v128_xor:
+ case SIMD_v128_bitselect:
+ {
+ if (!aot_compile_simd_v128_bitwise(comp_ctx, func_ctx,
+ V128_NOT + opcode
+ - SIMD_v128_not))
+ return false;
+ break;
+ }
+
+ case SIMD_v128_any_true:
+ {
+ if (!aot_compile_simd_v128_any_true(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ /* Load Lane Op */
+ case SIMD_v128_load8_lane:
+ case SIMD_v128_load16_lane:
+ case SIMD_v128_load32_lane:
+ case SIMD_v128_load64_lane:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_load_lane(comp_ctx, func_ctx,
+ opcode, align, offset,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_v128_store8_lane:
+ case SIMD_v128_store16_lane:
+ case SIMD_v128_store32_lane:
+ case SIMD_v128_store64_lane:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_store_lane(comp_ctx, func_ctx,
+ opcode, align, offset,
+ *frame_ip++))
+ return false;
+ break;
+ }
+
+ case SIMD_v128_load32_zero:
+ case SIMD_v128_load64_zero:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ if (!aot_compile_simd_load_zero(comp_ctx, func_ctx,
+ opcode, align, offset))
+ return false;
+ break;
+ }
+
+ /* Float conversion */
+ case SIMD_f32x4_demote_f64x2_zero:
+ {
+ if (!aot_compile_simd_f64x2_demote(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_promote_low_f32x4_zero:
+ {
+ if (!aot_compile_simd_f32x4_promote(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ /* i8x16 Op */
+ case SIMD_i8x16_abs:
+ {
+ if (!aot_compile_simd_i8x16_abs(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_neg:
+ {
+ if (!aot_compile_simd_i8x16_neg(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_popcnt:
+ {
+ if (!aot_compile_simd_i8x16_popcnt(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_all_true:
+ {
+ if (!aot_compile_simd_i8x16_all_true(comp_ctx,
+ func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_bitmask:
+ {
+ if (!aot_compile_simd_i8x16_bitmask(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_narrow_i16x8_s:
+ case SIMD_i8x16_narrow_i16x8_u:
+ {
+ if (!aot_compile_simd_i8x16_narrow_i16x8(
+ comp_ctx, func_ctx,
+ (opcode == SIMD_i8x16_narrow_i16x8_s)))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_ceil:
+ {
+ if (!aot_compile_simd_f32x4_ceil(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_floor:
+ {
+ if (!aot_compile_simd_f32x4_floor(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_trunc:
+ {
+ if (!aot_compile_simd_f32x4_trunc(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_nearest:
+ {
+ if (!aot_compile_simd_f32x4_nearest(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_shl:
+ case SIMD_i8x16_shr_s:
+ case SIMD_i8x16_shr_u:
+ {
+ if (!aot_compile_simd_i8x16_shift(comp_ctx, func_ctx,
+ INT_SHL + opcode
+ - SIMD_i8x16_shl))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_add:
+ {
+ if (!aot_compile_simd_i8x16_arith(comp_ctx, func_ctx,
+ V128_ADD))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_add_sat_s:
+ case SIMD_i8x16_add_sat_u:
+ {
+ if (!aot_compile_simd_i8x16_saturate(
+ comp_ctx, func_ctx, V128_ADD,
+ opcode == SIMD_i8x16_add_sat_s))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_sub:
+ {
+ if (!aot_compile_simd_i8x16_arith(comp_ctx, func_ctx,
+ V128_SUB))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_sub_sat_s:
+ case SIMD_i8x16_sub_sat_u:
+ {
+ if (!aot_compile_simd_i8x16_saturate(
+ comp_ctx, func_ctx, V128_SUB,
+ opcode == SIMD_i8x16_sub_sat_s))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_ceil:
+ {
+ if (!aot_compile_simd_f64x2_ceil(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_floor:
+ {
+ if (!aot_compile_simd_f64x2_floor(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_min_s:
+ case SIMD_i8x16_min_u:
+ {
+ if (!aot_compile_simd_i8x16_cmp(
+ comp_ctx, func_ctx, V128_MIN,
+ opcode == SIMD_i8x16_min_s))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_max_s:
+ case SIMD_i8x16_max_u:
+ {
+ if (!aot_compile_simd_i8x16_cmp(
+ comp_ctx, func_ctx, V128_MAX,
+ opcode == SIMD_i8x16_max_s))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_trunc:
+ {
+ if (!aot_compile_simd_f64x2_trunc(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i8x16_avgr_u:
+ {
+ if (!aot_compile_simd_i8x16_avgr_u(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_extadd_pairwise_i8x16_s:
+ case SIMD_i16x8_extadd_pairwise_i8x16_u:
+ {
+ if (!aot_compile_simd_i16x8_extadd_pairwise_i8x16(
+ comp_ctx, func_ctx,
+ SIMD_i16x8_extadd_pairwise_i8x16_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_extadd_pairwise_i16x8_s:
+ case SIMD_i32x4_extadd_pairwise_i16x8_u:
+ {
+ if (!aot_compile_simd_i32x4_extadd_pairwise_i16x8(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_extadd_pairwise_i16x8_s == opcode))
+ return false;
+ break;
+ }
+
+ /* i16x8 Op */
+ case SIMD_i16x8_abs:
+ {
+ if (!aot_compile_simd_i16x8_abs(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_neg:
+ {
+ if (!aot_compile_simd_i16x8_neg(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_q15mulr_sat_s:
+ {
+ if (!aot_compile_simd_i16x8_q15mulr_sat(comp_ctx,
+ func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_all_true:
+ {
+ if (!aot_compile_simd_i16x8_all_true(comp_ctx,
+ func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_bitmask:
+ {
+ if (!aot_compile_simd_i16x8_bitmask(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_narrow_i32x4_s:
+ case SIMD_i16x8_narrow_i32x4_u:
+ {
+ if (!aot_compile_simd_i16x8_narrow_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_i16x8_narrow_i32x4_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_extend_low_i8x16_s:
+ case SIMD_i16x8_extend_high_i8x16_s:
+ {
+ if (!aot_compile_simd_i16x8_extend_i8x16(
+ comp_ctx, func_ctx,
+ SIMD_i16x8_extend_low_i8x16_s == opcode, true))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_extend_low_i8x16_u:
+ case SIMD_i16x8_extend_high_i8x16_u:
+ {
+ if (!aot_compile_simd_i16x8_extend_i8x16(
+ comp_ctx, func_ctx,
+ SIMD_i16x8_extend_low_i8x16_u == opcode, false))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_shl:
+ case SIMD_i16x8_shr_s:
+ case SIMD_i16x8_shr_u:
+ {
+ if (!aot_compile_simd_i16x8_shift(comp_ctx, func_ctx,
+ INT_SHL + opcode
+ - SIMD_i16x8_shl))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_add:
+ {
+ if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx,
+ V128_ADD))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_add_sat_s:
+ case SIMD_i16x8_add_sat_u:
+ {
+ if (!aot_compile_simd_i16x8_saturate(
+ comp_ctx, func_ctx, V128_ADD,
+ opcode == SIMD_i16x8_add_sat_s ? true : false))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_sub:
+ {
+ if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx,
+ V128_SUB))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_sub_sat_s:
+ case SIMD_i16x8_sub_sat_u:
+ {
+ if (!aot_compile_simd_i16x8_saturate(
+ comp_ctx, func_ctx, V128_SUB,
+ opcode == SIMD_i16x8_sub_sat_s ? true : false))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_nearest:
+ {
+ if (!aot_compile_simd_f64x2_nearest(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_mul:
+ {
+ if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx,
+ V128_MUL))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_min_s:
+ case SIMD_i16x8_min_u:
+ {
+ if (!aot_compile_simd_i16x8_cmp(
+ comp_ctx, func_ctx, V128_MIN,
+ opcode == SIMD_i16x8_min_s))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_max_s:
+ case SIMD_i16x8_max_u:
+ {
+ if (!aot_compile_simd_i16x8_cmp(
+ comp_ctx, func_ctx, V128_MAX,
+ opcode == SIMD_i16x8_max_s))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_avgr_u:
+ {
+ if (!aot_compile_simd_i16x8_avgr_u(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_extmul_low_i8x16_s:
+ case SIMD_i16x8_extmul_high_i8x16_s:
+ {
+ if (!(aot_compile_simd_i16x8_extmul_i8x16(
+ comp_ctx, func_ctx,
+ SIMD_i16x8_extmul_low_i8x16_s == opcode, true)))
+ return false;
+ break;
+ }
+
+ case SIMD_i16x8_extmul_low_i8x16_u:
+ case SIMD_i16x8_extmul_high_i8x16_u:
+ {
+ if (!(aot_compile_simd_i16x8_extmul_i8x16(
+ comp_ctx, func_ctx,
+ SIMD_i16x8_extmul_low_i8x16_u == opcode,
+ false)))
+ return false;
+ break;
+ }
+
+ /* i32x4 Op */
+ case SIMD_i32x4_abs:
+ {
+ if (!aot_compile_simd_i32x4_abs(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_neg:
+ {
+ if (!aot_compile_simd_i32x4_neg(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_all_true:
+ {
+ if (!aot_compile_simd_i32x4_all_true(comp_ctx,
+ func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_bitmask:
+ {
+ if (!aot_compile_simd_i32x4_bitmask(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_narrow_i64x2_s:
+ case SIMD_i32x4_narrow_i64x2_u:
+ {
+ if (!aot_compile_simd_i32x4_narrow_i64x2(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_narrow_i64x2_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_extend_low_i16x8_s:
+ case SIMD_i32x4_extend_high_i16x8_s:
+ {
+ if (!aot_compile_simd_i32x4_extend_i16x8(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_extend_low_i16x8_s == opcode, true))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_extend_low_i16x8_u:
+ case SIMD_i32x4_extend_high_i16x8_u:
+ {
+ if (!aot_compile_simd_i32x4_extend_i16x8(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_extend_low_i16x8_u == opcode, false))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_shl:
+ case SIMD_i32x4_shr_s:
+ case SIMD_i32x4_shr_u:
+ {
+ if (!aot_compile_simd_i32x4_shift(comp_ctx, func_ctx,
+ INT_SHL + opcode
+ - SIMD_i32x4_shl))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_add:
+ {
+ if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
+ V128_ADD))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_add_sat_s:
+ case SIMD_i32x4_add_sat_u:
+ {
+ if (!aot_compile_simd_i32x4_saturate(
+ comp_ctx, func_ctx, V128_ADD,
+ opcode == SIMD_i32x4_add_sat_s))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_sub:
+ {
+ if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
+ V128_SUB))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_sub_sat_s:
+ case SIMD_i32x4_sub_sat_u:
+ {
+ if (!aot_compile_simd_i32x4_saturate(
+ comp_ctx, func_ctx, V128_SUB,
+ opcode == SIMD_i32x4_add_sat_s))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_mul:
+ {
+ if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
+ V128_MUL))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_min_s:
+ case SIMD_i32x4_min_u:
+ {
+ if (!aot_compile_simd_i32x4_cmp(
+ comp_ctx, func_ctx, V128_MIN,
+ SIMD_i32x4_min_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_max_s:
+ case SIMD_i32x4_max_u:
+ {
+ if (!aot_compile_simd_i32x4_cmp(
+ comp_ctx, func_ctx, V128_MAX,
+ SIMD_i32x4_max_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_dot_i16x8_s:
+ {
+ if (!aot_compile_simd_i32x4_dot_i16x8(comp_ctx,
+ func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_avgr_u:
+ {
+ if (!aot_compile_simd_i32x4_avgr_u(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_extmul_low_i16x8_s:
+ case SIMD_i32x4_extmul_high_i16x8_s:
+ {
+ if (!aot_compile_simd_i32x4_extmul_i16x8(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_extmul_low_i16x8_s == opcode, true))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_extmul_low_i16x8_u:
+ case SIMD_i32x4_extmul_high_i16x8_u:
+ {
+ if (!aot_compile_simd_i32x4_extmul_i16x8(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_extmul_low_i16x8_u == opcode, false))
+ return false;
+ break;
+ }
+
+ /* i64x2 Op */
+ case SIMD_i64x2_abs:
+ {
+ if (!aot_compile_simd_i64x2_abs(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_neg:
+ {
+ if (!aot_compile_simd_i64x2_neg(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_all_true:
+ {
+ if (!aot_compile_simd_i64x2_all_true(comp_ctx,
+ func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_bitmask:
+ {
+ if (!aot_compile_simd_i64x2_bitmask(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_extend_low_i32x4_s:
+ case SIMD_i64x2_extend_high_i32x4_s:
+ {
+ if (!aot_compile_simd_i64x2_extend_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_i64x2_extend_low_i32x4_s == opcode, true))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_extend_low_i32x4_u:
+ case SIMD_i64x2_extend_high_i32x4_u:
+ {
+ if (!aot_compile_simd_i64x2_extend_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_i64x2_extend_low_i32x4_u == opcode, false))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_shl:
+ case SIMD_i64x2_shr_s:
+ case SIMD_i64x2_shr_u:
+ {
+ if (!aot_compile_simd_i64x2_shift(comp_ctx, func_ctx,
+ INT_SHL + opcode
+ - SIMD_i64x2_shl))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_add:
+ {
+ if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx,
+ V128_ADD))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_sub:
+ {
+ if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx,
+ V128_SUB))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_mul:
+ {
+ if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx,
+ V128_MUL))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_eq:
+ case SIMD_i64x2_ne:
+ case SIMD_i64x2_lt_s:
+ case SIMD_i64x2_gt_s:
+ case SIMD_i64x2_le_s:
+ case SIMD_i64x2_ge_s:
+ {
+ IntCond icond[] = { INT_EQ, INT_NE, INT_LT_S,
+ INT_GT_S, INT_LE_S, INT_GE_S };
+ if (!aot_compile_simd_i64x2_compare(
+ comp_ctx, func_ctx,
+ icond[opcode - SIMD_i64x2_eq]))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_extmul_low_i32x4_s:
+ case SIMD_i64x2_extmul_high_i32x4_s:
+ {
+ if (!aot_compile_simd_i64x2_extmul_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_i64x2_extmul_low_i32x4_s == opcode, true))
+ return false;
+ break;
+ }
+
+ case SIMD_i64x2_extmul_low_i32x4_u:
+ case SIMD_i64x2_extmul_high_i32x4_u:
+ {
+ if (!aot_compile_simd_i64x2_extmul_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_i64x2_extmul_low_i32x4_u == opcode, false))
+ return false;
+ break;
+ }
+
+ /* f32x4 Op */
+ case SIMD_f32x4_abs:
+ {
+ if (!aot_compile_simd_f32x4_abs(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_neg:
+ {
+ if (!aot_compile_simd_f32x4_neg(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_round:
+ {
+ if (!aot_compile_simd_f32x4_round(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_sqrt:
+ {
+ if (!aot_compile_simd_f32x4_sqrt(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_add:
+ case SIMD_f32x4_sub:
+ case SIMD_f32x4_mul:
+ case SIMD_f32x4_div:
+ {
+ if (!aot_compile_simd_f32x4_arith(comp_ctx, func_ctx,
+ FLOAT_ADD + opcode
+ - SIMD_f32x4_add))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_min:
+ case SIMD_f32x4_max:
+ {
+ if (!aot_compile_simd_f32x4_min_max(
+ comp_ctx, func_ctx, SIMD_f32x4_min == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_pmin:
+ case SIMD_f32x4_pmax:
+ {
+ if (!aot_compile_simd_f32x4_pmin_pmax(
+ comp_ctx, func_ctx, SIMD_f32x4_pmin == opcode))
+ return false;
+ break;
+ }
+
+ /* f64x2 Op */
+
+ case SIMD_f64x2_abs:
+ {
+ if (!aot_compile_simd_f64x2_abs(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_neg:
+ {
+ if (!aot_compile_simd_f64x2_neg(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_round:
+ {
+ if (!aot_compile_simd_f64x2_round(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_sqrt:
+ {
+ if (!aot_compile_simd_f64x2_sqrt(comp_ctx, func_ctx))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_add:
+ case SIMD_f64x2_sub:
+ case SIMD_f64x2_mul:
+ case SIMD_f64x2_div:
+ {
+ if (!aot_compile_simd_f64x2_arith(comp_ctx, func_ctx,
+ FLOAT_ADD + opcode
+ - SIMD_f64x2_add))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_min:
+ case SIMD_f64x2_max:
+ {
+ if (!aot_compile_simd_f64x2_min_max(
+ comp_ctx, func_ctx, SIMD_f64x2_min == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_pmin:
+ case SIMD_f64x2_pmax:
+ {
+ if (!aot_compile_simd_f64x2_pmin_pmax(
+ comp_ctx, func_ctx, SIMD_f64x2_pmin == opcode))
+ return false;
+ break;
+ }
+
+ /* Conversion Op */
+ case SIMD_i32x4_trunc_sat_f32x4_s:
+ case SIMD_i32x4_trunc_sat_f32x4_u:
+ {
+ if (!aot_compile_simd_i32x4_trunc_sat_f32x4(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_trunc_sat_f32x4_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_f32x4_convert_i32x4_s:
+ case SIMD_f32x4_convert_i32x4_u:
+ {
+ if (!aot_compile_simd_f32x4_convert_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_f32x4_convert_i32x4_s == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_i32x4_trunc_sat_f64x2_s_zero:
+ case SIMD_i32x4_trunc_sat_f64x2_u_zero:
+ {
+ if (!aot_compile_simd_i32x4_trunc_sat_f64x2(
+ comp_ctx, func_ctx,
+ SIMD_i32x4_trunc_sat_f64x2_s_zero == opcode))
+ return false;
+ break;
+ }
+
+ case SIMD_f64x2_convert_low_i32x4_s:
+ case SIMD_f64x2_convert_low_i32x4_u:
+ {
+ if (!aot_compile_simd_f64x2_convert_i32x4(
+ comp_ctx, func_ctx,
+ SIMD_f64x2_convert_low_i32x4_s == opcode))
+ return false;
+ break;
+ }
+
+ default:
+ aot_set_last_error("unsupported SIMD opcode");
+ return false;
+ }
+ break;
+ }
+#endif /* end of WASM_ENABLE_SIMD */
+
+ default:
+ aot_set_last_error("unsupported opcode");
+ return false;
+ }
+ }
+
+ /* 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);
+ }
+ return true;
+
+#if WASM_ENABLE_SIMD != 0
+unsupport_simd:
+ aot_set_last_error("SIMD instruction was found, "
+ "try removing --disable-simd option");
+ return false;
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+unsupport_ref_types:
+ aot_set_last_error("reference type instruction was found, "
+ "try removing --disable-ref-types option");
+ return false;
+#endif
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+unsupport_bulk_memory:
+ aot_set_last_error("bulk memory instruction was found, "
+ "try removing --disable-bulk-memory option");
+ return false;
+#endif
+
+fail:
+ return false;
+}
+
+static bool
+verify_module(AOTCompContext *comp_ctx)
+{
+ char *msg = NULL;
+ bool ret;
+
+ 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);
+ }
+
+ return true;
+}
+
+/* Check whether the target supports hardware atomic instructions */
+static bool
+aot_require_lower_atomic_pass(AOTCompContext *comp_ctx)
+{
+ bool ret = false;
+ if (!strncmp(comp_ctx->target_arch, "riscv", 5)) {
+ char *feature =
+ LLVMGetTargetMachineFeatureString(comp_ctx->target_machine);
+
+ if (feature) {
+ if (!strstr(feature, "+a")) {
+ ret = true;
+ }
+ LLVMDisposeMessage(feature);
+ }
+ }
+ return ret;
+}
+
+/* Check whether the target needs to expand switch to if/else */
+static bool
+aot_require_lower_switch_pass(AOTCompContext *comp_ctx)
+{
+ bool ret = false;
+
+ /* IR switch/case will cause .rodata relocation on riscv/xtensa */
+ if (!strncmp(comp_ctx->target_arch, "riscv", 5)
+ || !strncmp(comp_ctx->target_arch, "xtensa", 6)) {
+ ret = true;
+ }
+
+ return ret;
+}
+
+static bool
+apply_passes_for_indirect_mode(AOTCompContext *comp_ctx)
+{
+ LLVMPassManagerRef common_pass_mgr;
+
+ if (!(common_pass_mgr = LLVMCreatePassManager())) {
+ aot_set_last_error("create pass manager failed");
+ return false;
+ }
+
+ aot_add_expand_memory_op_pass(common_pass_mgr);
+
+ if (aot_require_lower_atomic_pass(comp_ctx))
+ LLVMAddLowerAtomicPass(common_pass_mgr);
+
+ if (aot_require_lower_switch_pass(comp_ctx))
+ LLVMAddLowerSwitchPass(common_pass_mgr);
+
+ LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
+
+ LLVMDisposePassManager(common_pass_mgr);
+ return true;
+}
+
+bool
+aot_compile_wasm(AOTCompContext *comp_ctx)
+{
+ uint32 i;
+
+ if (!aot_validate_wasm(comp_ctx)) {
+ return false;
+ }
+
+ bh_print_time("Begin to compile WASM bytecode to LLVM IR");
+ for (i = 0; i < comp_ctx->func_ctx_count; i++) {
+ if (!aot_compile_func(comp_ctx, i)) {
+ return false;
+ }
+ }
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMDIBuilderFinalize(comp_ctx->debug_builder);
+#endif
+
+ /* Disable LLVM module verification for jit mode to speedup
+ the compilation process */
+ if (!comp_ctx->is_jit_mode) {
+ bh_print_time("Begin to verify LLVM module");
+ if (!verify_module(comp_ctx)) {
+ return false;
+ }
+ }
+
+ /* Run IR optimization before feeding in ORCJIT and AOT codegen */
+ if (comp_ctx->optimize) {
+ /* Run passes for AOT/JIT mode.
+ TODO: Apply these passes in the do_ir_transform callback of
+ TransformLayer when compiling each jit function, so as to
+ speedup the launch process. Now there are two issues in the
+ JIT: one is memory leak in do_ir_transform, the other is
+ possible core dump. */
+ bh_print_time("Begin to run llvm optimization passes");
+ aot_apply_llvm_new_pass_manager(comp_ctx, comp_ctx->module);
+
+ /* Run specific passes for AOT indirect mode in last since general
+ optimization may create some intrinsic function calls like
+ llvm.memset, so let's remove these function calls here. */
+ if (!comp_ctx->is_jit_mode && comp_ctx->is_indirect_mode) {
+ bh_print_time("Begin to run optimization passes "
+ "for indirect mode");
+ if (!apply_passes_for_indirect_mode(comp_ctx)) {
+ return false;
+ }
+ }
+ bh_print_time("Finish llvm optimization passes");
+ }
+
+#ifdef DUMP_MODULE
+ LLVMDumpModule(comp_ctx->module);
+ os_printf("\n");
+#endif
+
+ if (comp_ctx->is_jit_mode) {
+ LLVMErrorRef err;
+ LLVMOrcJITDylibRef orc_main_dylib;
+ LLVMOrcThreadSafeModuleRef orc_thread_safe_module;
+
+ orc_main_dylib = LLVMOrcLLLazyJITGetMainJITDylib(comp_ctx->orc_jit);
+ if (!orc_main_dylib) {
+ aot_set_last_error(
+ "failed to get orc orc_jit main dynmaic library");
+ return false;
+ }
+
+ orc_thread_safe_module = LLVMOrcCreateNewThreadSafeModule(
+ comp_ctx->module, comp_ctx->orc_thread_safe_context);
+ if (!orc_thread_safe_module) {
+ aot_set_last_error("failed to create thread safe module");
+ return false;
+ }
+
+ if ((err = LLVMOrcLLLazyJITAddLLVMIRModule(
+ comp_ctx->orc_jit, orc_main_dylib, orc_thread_safe_module))) {
+ /* If adding the ThreadSafeModule fails then we need to clean it up
+ by ourselves, otherwise the orc orc_jit will manage the memory.
+ */
+ LLVMOrcDisposeThreadSafeModule(orc_thread_safe_module);
+ aot_handle_llvm_errmsg("failed to addIRModule", err);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#if !(defined(_WIN32) || defined(_WIN32_))
+char *
+aot_generate_tempfile_name(const char *prefix, const char *extension,
+ char *buffer, uint32 len)
+{
+ int fd, name_len;
+
+ name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
+
+ if ((fd = mkstemp(buffer)) <= 0) {
+ aot_set_last_error("make temp file failed.");
+ return NULL;
+ }
+
+ /* close and remove temp file */
+ close(fd);
+ unlink(buffer);
+
+ /* Check if buffer length is enough */
+ /* name_len + '.' + extension + '\0' */
+ if (name_len + 1 + strlen(extension) + 1 > len) {
+ aot_set_last_error("temp file name too long.");
+ return NULL;
+ }
+
+ snprintf(buffer + name_len, len - name_len, ".%s", extension);
+ return buffer;
+}
+#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
+
+bool
+aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
+{
+ char *err = NULL;
+
+ bh_print_time("Begin to emit LLVM IR file");
+
+ 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;
+ LLVMCodeGenFileType file_type = LLVMObjectFile;
+ LLVMTargetRef target = LLVMGetTargetMachineTarget(comp_ctx->target_machine);
+
+ bh_print_time("Begin to emit object file");
+
+#if !(defined(_WIN32) || defined(_WIN32_))
+ if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
+ char cmd[1024];
+ int ret;
+
+ if (comp_ctx->external_llc_compiler) {
+ char bc_file_name[64];
+
+ if (!aot_generate_tempfile_name("wamrc-bc", "bc", bc_file_name,
+ sizeof(bc_file_name))) {
+ return false;
+ }
+
+ if (LLVMWriteBitcodeToFile(comp_ctx->module, bc_file_name) != 0) {
+ aot_set_last_error("emit llvm bitcode file failed.");
+ return false;
+ }
+
+ snprintf(cmd, sizeof(cmd), "%s %s -o %s %s",
+ comp_ctx->external_llc_compiler,
+ comp_ctx->llc_compiler_flags ? comp_ctx->llc_compiler_flags
+ : "-O3 -c",
+ file_name, bc_file_name);
+ LOG_VERBOSE("invoking external LLC compiler:\n\t%s", cmd);
+
+ ret = system(cmd);
+ /* remove temp bitcode file */
+ unlink(bc_file_name);
+
+ if (ret != 0) {
+ aot_set_last_error("failed to compile LLVM bitcode to obj file "
+ "with external LLC compiler.");
+ return false;
+ }
+ }
+ else if (comp_ctx->external_asm_compiler) {
+ char asm_file_name[64];
+
+ if (!aot_generate_tempfile_name("wamrc-asm", "s", asm_file_name,
+ sizeof(asm_file_name))) {
+ return false;
+ }
+
+ if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
+ comp_ctx->module, asm_file_name,
+ LLVMAssemblyFile, &err)
+ != 0) {
+ if (err) {
+ LLVMDisposeMessage(err);
+ err = NULL;
+ }
+ aot_set_last_error("emit elf to assembly file failed.");
+ return false;
+ }
+
+ snprintf(cmd, sizeof(cmd), "%s %s -o %s %s",
+ comp_ctx->external_asm_compiler,
+ comp_ctx->asm_compiler_flags ? comp_ctx->asm_compiler_flags
+ : "-O3 -c",
+ file_name, asm_file_name);
+ LOG_VERBOSE("invoking external ASM compiler:\n\t%s", cmd);
+
+ ret = system(cmd);
+ /* remove temp assembly file */
+ unlink(asm_file_name);
+
+ if (ret != 0) {
+ aot_set_last_error("failed to compile Assembly file to obj "
+ "file with external ASM compiler.");
+ return false;
+ }
+ }
+
+ return true;
+ }
+#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
+
+ if (!strncmp(LLVMGetTargetName(target), "arc", 3))
+ /* Emit to assmelby file instead for arc target
+ as it cannot emit to object file */
+ file_type = LLVMAssemblyFile;
+
+ if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, comp_ctx->module,
+ file_name, file_type, &err)
+ != 0) {
+ if (err) {
+ LLVMDisposeMessage(err);
+ err = NULL;
+ }
+ aot_set_last_error("emit elf to object file failed.");
+ return false;
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.h
new file mode 100644
index 000000000..e6031ab89
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_compiler.h
@@ -0,0 +1,383 @@
+/*
+ * 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"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef AOTIntCond IntCond;
+typedef AOTFloatCond 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 V128Arithmetic {
+ V128_ADD = 0,
+ V128_SUB,
+ V128_MUL,
+ V128_DIV,
+ V128_NEG,
+ V128_MIN,
+ V128_MAX,
+} V128Arithmetic;
+
+typedef enum IntBitwise {
+ INT_AND = 0,
+ INT_OR,
+ INT_XOR,
+} IntBitwise;
+
+typedef enum V128Bitwise {
+ V128_NOT,
+ V128_AND,
+ V128_ANDNOT,
+ V128_OR,
+ V128_XOR,
+ V128_BITSELECT,
+} V128Bitwise;
+
+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;
+
+static inline bool
+check_type_compatible(uint8 src_type, uint8 dst_type)
+{
+ if (src_type == dst_type) {
+ return true;
+ }
+
+ /* ext i1 to i32 */
+ if (src_type == VALUE_TYPE_I1 && dst_type == VALUE_TYPE_I32) {
+ return true;
+ }
+
+ /* i32 <==> func.ref, i32 <==> extern.ref */
+ if (src_type == VALUE_TYPE_I32
+ && (dst_type == VALUE_TYPE_EXTERNREF
+ || dst_type == VALUE_TYPE_FUNCREF)) {
+ return true;
+ }
+
+ if (dst_type == VALUE_TYPE_I32
+ && (src_type == VALUE_TYPE_FUNCREF
+ || src_type == VALUE_TYPE_EXTERNREF)) {
+ return true;
+ }
+
+ return false;
+}
+
+#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 (!check_type_compatible(aot_value->type, value_type)) { \
+ aot_set_last_error("invalid WASM stack data type."); \
+ wasm_runtime_free(aot_value); \
+ goto fail; \
+ } \
+ if (aot_value->type == value_type) \
+ llvm_value = aot_value->value; \
+ else { \
+ if (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_runtime_free(aot_value); \
+ goto fail; \
+ } \
+ } \
+ else { \
+ bh_assert(aot_value->type == VALUE_TYPE_I32 \
+ || aot_value->type == VALUE_TYPE_FUNCREF \
+ || aot_value->type == VALUE_TYPE_EXTERNREF); \
+ bh_assert(value_type == VALUE_TYPE_I32 \
+ || value_type == VALUE_TYPE_FUNCREF \
+ || value_type == VALUE_TYPE_EXTERNREF); \
+ llvm_value = aot_value->value; \
+ } \
+ } \
+ wasm_runtime_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_V128(v) POP(v, VALUE_TYPE_V128)
+#define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
+#define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)
+
+#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_runtime_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_runtime_free(aot_value); \
+ goto fail; \
+ } \
+ } \
+ wasm_runtime_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_runtime_malloc(sizeof(AOTValue)); \
+ if (!aot_value) { \
+ aot_set_last_error("allocate memory failed."); \
+ goto fail; \
+ } \
+ memset(aot_value, 0, sizeof(AOTValue)); \
+ 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_V128(v) PUSH(v, VALUE_TYPE_V128)
+#define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1)
+#define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
+#define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
+
+#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 FUNC_REF_TYPE comp_ctx->basic_types.funcref_type
+#define EXTERN_REF_TYPE comp_ctx->basic_types.externref_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 LLVM_CONST(name) (comp_ctx->llvm_consts.name)
+#define I8_ZERO LLVM_CONST(i8_zero)
+#define I32_ZERO LLVM_CONST(i32_zero)
+#define I64_ZERO LLVM_CONST(i64_zero)
+#define F32_ZERO LLVM_CONST(f32_zero)
+#define F64_ZERO LLVM_CONST(f64_zero)
+#define I32_ONE LLVM_CONST(i32_one)
+#define I32_TWO LLVM_CONST(i32_two)
+#define I32_THREE LLVM_CONST(i32_three)
+#define I32_FOUR LLVM_CONST(i32_four)
+#define I32_FIVE LLVM_CONST(i32_five)
+#define I32_SIX LLVM_CONST(i32_six)
+#define I32_SEVEN LLVM_CONST(i32_seven)
+#define I32_EIGHT LLVM_CONST(i32_eight)
+#define I32_NINE LLVM_CONST(i32_nine)
+#define I32_NEG_ONE LLVM_CONST(i32_neg_one)
+#define I64_NEG_ONE LLVM_CONST(i64_neg_one)
+#define I32_MIN LLVM_CONST(i32_min)
+#define I64_MIN LLVM_CONST(i64_min)
+#define I32_31 LLVM_CONST(i32_31)
+#define I32_32 LLVM_CONST(i32_32)
+#define I64_63 LLVM_CONST(i64_63)
+#define I64_64 LLVM_CONST(i64_64)
+#define REF_NULL I32_NEG_ONE
+
+#define V128_TYPE comp_ctx->basic_types.v128_type
+#define V128_PTR_TYPE comp_ctx->basic_types.v128_ptr_type
+#define V128_i8x16_TYPE comp_ctx->basic_types.i8x16_vec_type
+#define V128_i16x8_TYPE comp_ctx->basic_types.i16x8_vec_type
+#define V128_i32x4_TYPE comp_ctx->basic_types.i32x4_vec_type
+#define V128_i64x2_TYPE comp_ctx->basic_types.i64x2_vec_type
+#define V128_f32x4_TYPE comp_ctx->basic_types.f32x4_vec_type
+#define V128_f64x2_TYPE comp_ctx->basic_types.f64x2_vec_type
+
+#define V128_i8x16_ZERO LLVM_CONST(i8x16_vec_zero)
+#define V128_i16x8_ZERO LLVM_CONST(i16x8_vec_zero)
+#define V128_i32x4_ZERO LLVM_CONST(i32x4_vec_zero)
+#define V128_i64x2_ZERO LLVM_CONST(i64x2_vec_zero)
+#define V128_f32x4_ZERO LLVM_CONST(f32x4_vec_zero)
+#define V128_f64x2_ZERO LLVM_CONST(f64x2_vec_zero)
+
+#define TO_V128_i8x16(v) \
+ LLVMBuildBitCast(comp_ctx->builder, v, V128_i8x16_TYPE, "i8x16_val")
+#define TO_V128_i16x8(v) \
+ LLVMBuildBitCast(comp_ctx->builder, v, V128_i16x8_TYPE, "i16x8_val")
+#define TO_V128_i32x4(v) \
+ LLVMBuildBitCast(comp_ctx->builder, v, V128_i32x4_TYPE, "i32x4_val")
+#define TO_V128_i64x2(v) \
+ LLVMBuildBitCast(comp_ctx->builder, v, V128_i64x2_TYPE, "i64x2_val")
+#define TO_V128_f32x4(v) \
+ LLVMBuildBitCast(comp_ctx->builder, v, V128_f32x4_TYPE, "f32x4_val")
+#define TO_V128_f64x2(v) \
+ LLVMBuildBitCast(comp_ctx->builder, v, V128_f64x2_TYPE, "f64x2_val")
+
+#define CHECK_LLVM_CONST(v) \
+ do { \
+ if (!v) { \
+ aot_set_last_error("create llvm const failed."); \
+ goto fail; \
+ } \
+ } while (0)
+
+#define GET_AOT_FUNCTION(name, argc) \
+ do { \
+ if (!(func_type = \
+ LLVMFunctionType(ret_type, param_types, argc, false))) { \
+ aot_set_last_error("llvm add function type failed."); \
+ goto fail; \
+ } \
+ 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."); \
+ goto fail; \
+ } \
+ if (!(value = I64_CONST((uint64)(uintptr_t)name)) \
+ || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { \
+ aot_set_last_error("create LLVM value failed."); \
+ goto fail; \
+ } \
+ } \
+ else if (comp_ctx->is_indirect_mode) { \
+ int32 func_index; \
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \
+ aot_set_last_error("create LLVM function type failed."); \
+ goto fail; \
+ } \
+ \
+ func_index = aot_get_native_symbol_index(comp_ctx, #name); \
+ if (func_index < 0) { \
+ goto fail; \
+ } \
+ if (!(func = aot_get_func_from_table( \
+ comp_ctx, func_ctx->native_symbol, func_ptr_type, \
+ func_index))) { \
+ goto fail; \
+ } \
+ } \
+ else { \
+ char *func_name = #name; \
+ /* AOT mode, delcare the function */ \
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name)) \
+ && !(func = LLVMAddFunction(func_ctx->module, func_name, \
+ func_type))) { \
+ aot_set_last_error("llvm add function 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);
+
+uint8 *
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ uint32 *p_aot_file_size);
+
+bool
+aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
+
+char *
+aot_generate_tempfile_name(const char *prefix, const char *extension,
+ char *buffer, uint32 len);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_COMPILER_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_aot_file.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_aot_file.c
new file mode 100644
index 000000000..62bb809da
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_aot_file.c
@@ -0,0 +1,2930 @@
+/*
+ * 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)
+
+static bool
+check_utf8_str(const uint8 *str, uint32 len)
+{
+ /* The valid ranges are taken from page 125, below link
+ https://www.unicode.org/versions/Unicode9.0.0/ch03.pdf */
+ const uint8 *p = str, *p_end = str + len;
+ uint8 chr;
+
+ while (p < p_end) {
+ chr = *p;
+ if (chr < 0x80) {
+ p++;
+ }
+ else if (chr >= 0xC2 && chr <= 0xDF && p + 1 < p_end) {
+ if (p[1] < 0x80 || p[1] > 0xBF) {
+ return false;
+ }
+ p += 2;
+ }
+ else if (chr >= 0xE0 && chr <= 0xEF && p + 2 < p_end) {
+ if (chr == 0xE0) {
+ if (p[1] < 0xA0 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr == 0xED) {
+ if (p[1] < 0x80 || p[1] > 0x9F || p[2] < 0x80 || p[2] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr >= 0xE1 && chr <= 0xEF) {
+ if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) {
+ return false;
+ }
+ }
+ p += 3;
+ }
+ else if (chr >= 0xF0 && chr <= 0xF4 && p + 3 < p_end) {
+ if (chr == 0xF0) {
+ if (p[1] < 0x90 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF
+ || p[3] < 0x80 || p[3] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr >= 0xF1 && chr <= 0xF3) {
+ if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF
+ || p[3] < 0x80 || p[3] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr == 0xF4) {
+ if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF
+ || p[3] < 0x80 || p[3] > 0xBF) {
+ return false;
+ }
+ }
+ p += 4;
+ }
+ else {
+ return false;
+ }
+ }
+ return (p == p_end);
+}
+
+/* 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;
+
+ /* literal data and size */
+ void *literal;
+ uint32 literal_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(const AOTObjectData *obj_data)
+{
+ /* bit 1: 0 is 32-bit, 1 is 64-bit */
+ return obj_data->target_info.bin_type & 2 ? false : true;
+}
+
+static bool
+is_little_endian_binary(const AOTObjectData *obj_data)
+{
+ /* bit 0: 0 is little-endian, 1 is big-endian */
+ return obj_data->target_info.bin_type & 1 ? false : true;
+}
+
+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(AOTCompContext *comp_ctx, const char *s)
+{
+ /* string size (2 bytes) + string content */
+ return (uint32)sizeof(uint16) + (uint32)strlen(s) +
+ /* emit string with '\0' only in XIP mode */
+ (comp_ctx->is_indirect_mode ? 1 : 0);
+}
+
+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 */
+ uint32 total_size = (uint32)(sizeof(uint32) + sizeof(uint64)
+ + sizeof(uint32) + mem_init_data->byte_count);
+
+ /* bulk_memory enabled:
+ is_passive (4 bytes) + memory_index (4 bytes)
+ bulk memory disabled:
+ placeholder (4 bytes) + placeholder (4 bytes)
+ */
+ total_size += (sizeof(uint32) + sizeof(uint32));
+
+ return total_size;
+}
+
+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_import_memory_size(AOTCompData *comp_data)
+{
+ /* currently we only emit import_memory_count = 0 */
+ return sizeof(uint32);
+}
+
+static uint32
+get_memory_size(AOTCompData *comp_data)
+{
+ /* memory_count + count * (memory_flags + num_bytes_per_page +
+ init_page_count + max_page_count) */
+ return (uint32)(sizeof(uint32)
+ + comp_data->memory_count * sizeof(uint32) * 4);
+}
+
+static uint32
+get_mem_info_size(AOTCompData *comp_data)
+{
+ /* import_memory_size + memory_size
+ + init_data_count + init_data_list */
+ return get_import_memory_size(comp_data) + get_memory_size(comp_data)
+ + (uint32)sizeof(uint32)
+ + get_mem_init_data_list_size(comp_data->mem_init_data_list,
+ comp_data->mem_init_data_count);
+}
+
+static uint32
+get_table_init_data_size(AOTTableInitData *table_init_data)
+{
+ /*
+ * mode (4 bytes), elem_type (4 bytes), do not need is_dropped field
+ *
+ * table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
+ * bytes)
+ * + func index count (4 bytes) + func indexes
+ */
+ return (uint32)(sizeof(uint32) * 2 + sizeof(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)
+{
+ /*
+ * ------------------------------
+ * | table_init_data_count
+ * ------------------------------
+ * | | U32 mode
+ * | AOTTableInitData[N] | U32 elem_type
+ * | | U32 table_index
+ * | | U32 offset.init_expr_type
+ * | | U64 offset.u.i64
+ * | | U32 func_index_count
+ * | | U32[func_index_count]
+ * ------------------------------
+ */
+ AOTTableInitData **table_init_data = table_init_data_list;
+ uint32 size = 0, i;
+
+ size = (uint32)sizeof(uint32);
+
+ 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_import_table_size(AOTCompData *comp_data)
+{
+ /*
+ * ------------------------------
+ * | import_table_count
+ * ------------------------------
+ * | | U32 table_init_size
+ * | | ----------------------
+ * | AOTImpotTable[N] | U32 table_init_size
+ * | | ----------------------
+ * | | U32 possible_grow (convenient than U8)
+ * ------------------------------
+ */
+ return (uint32)(sizeof(uint32)
+ + comp_data->import_table_count * (sizeof(uint32) * 3));
+}
+
+static uint32
+get_table_size(AOTCompData *comp_data)
+{
+ /*
+ * ------------------------------
+ * | table_count
+ * ------------------------------
+ * | | U32 elem_type
+ * | AOTTable[N] | U32 table_flags
+ * | | U32 table_init_size
+ * | | U32 table_max_size
+ * | | U32 possible_grow (convenient than U8)
+ * ------------------------------
+ */
+ return (uint32)(sizeof(uint32)
+ + comp_data->table_count * (sizeof(uint32) * 5));
+}
+
+static uint32
+get_table_info_size(AOTCompData *comp_data)
+{
+ /*
+ * ------------------------------
+ * | import_table_count
+ * ------------------------------
+ * |
+ * | AOTImportTable[import_table_count]
+ * |
+ * ------------------------------
+ * | table_count
+ * ------------------------------
+ * |
+ * | AOTTable[table_count]
+ * |
+ * ------------------------------
+ * | table_init_data_count
+ * ------------------------------
+ * |
+ * | AOTTableInitData*[table_init_data_count]
+ * |
+ * ------------------------------
+ */
+ return get_import_table_size(comp_data) + get_table_size(comp_data)
+ + 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(AOTCompContext *comp_ctx, AOTImportGlobal *import_global)
+{
+ /* type (1 byte) + is_mutable (1 byte) + module_name + global_name */
+ uint32 size = (uint32)sizeof(uint8) * 2
+ + get_string_size(comp_ctx, import_global->module_name);
+ size = align_uint(size, 2);
+ size += get_string_size(comp_ctx, import_global->global_name);
+ return size;
+}
+
+static uint32
+get_import_globals_size(AOTCompContext *comp_ctx,
+ 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(comp_ctx, import_global);
+ }
+ return size;
+}
+
+static uint32
+get_import_global_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
+{
+ /* import global count + import globals */
+ return (uint32)sizeof(uint32)
+ + get_import_globals_size(comp_ctx, comp_data->import_globals,
+ comp_data->import_global_count);
+}
+
+static uint32
+get_global_size(AOTGlobal *global)
+{
+ if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
+ /* 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);
+ else
+ /* type (1 byte) + is_mutable (1 byte)
+ + init expr type (2 byes) + v128 value (16 byes) */
+ return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64) * 2;
+}
+
+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(AOTCompContext *comp_ctx, AOTImportFunc *import_func)
+{
+ /* type index (2 bytes) + module_name + func_name */
+ uint32 size = (uint32)sizeof(uint16)
+ + get_string_size(comp_ctx, import_func->module_name);
+ size = align_uint(size, 2);
+ size += get_string_size(comp_ctx, import_func->func_name);
+ return size;
+}
+
+static uint32
+get_import_funcs_size(AOTCompContext *comp_ctx, 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(comp_ctx, import_func);
+ }
+ return size;
+}
+
+static uint32
+get_import_func_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
+{
+ /* import func count + import funcs */
+ return (uint32)sizeof(uint32)
+ + get_import_funcs_size(comp_ctx, comp_data->import_funcs,
+ comp_data->import_func_count);
+}
+
+static uint32
+get_object_data_sections_size(AOTCompContext *comp_ctx,
+ 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++) {
+ /* name + size + data */
+ size = align_uint(size, 2);
+ size += get_string_size(comp_ctx, data_section->name);
+ size = align_uint(size, 4);
+ size += (uint32)sizeof(uint32);
+ size += data_section->size;
+ }
+ return size;
+}
+
+static uint32
+get_object_data_section_info_size(AOTCompContext *comp_ctx,
+ AOTObjectData *obj_data)
+{
+ /* data sections count + data sections */
+ return (uint32)sizeof(uint32)
+ + get_object_data_sections_size(comp_ctx, obj_data->data_sections,
+ obj_data->data_sections_count);
+}
+
+static uint32
+get_init_data_section_size(AOTCompContext *comp_ctx, 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_ctx, 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_ctx, comp_data);
+
+ /* func count + start func index */
+ size = align_uint(size, 4);
+ size += (uint32)sizeof(uint32) * 2;
+
+ /* aux data/heap/stack data */
+ size += sizeof(uint32) * 7;
+
+ size += get_object_data_section_info_size(comp_ctx, obj_data);
+ return size;
+}
+
+static uint32
+get_text_section_size(AOTObjectData *obj_data)
+{
+ return (sizeof(uint32) + obj_data->literal_size + obj_data->text_size + 3)
+ & ~3;
+}
+
+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))
+ 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_size(AOTCompContext *comp_ctx, AOTExport *export)
+{
+ /* export index + export kind + 1 byte padding + export name */
+ return (uint32)sizeof(uint32) + sizeof(uint8) + 1
+ + get_string_size(comp_ctx, export->name);
+}
+
+static uint32
+get_exports_size(AOTCompContext *comp_ctx, AOTExport *exports,
+ uint32 export_count)
+{
+ AOTExport *export = exports;
+ uint32 size = 0, i;
+
+ for (i = 0; i < export_count; i++, export ++) {
+ size = align_uint(size, 4);
+ size += get_export_size(comp_ctx, export);
+ }
+ return size;
+}
+
+static uint32
+get_export_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
+{
+ /* export count + exports */
+ return (uint32)sizeof(uint32)
+ + get_exports_size(comp_ctx, comp_data->wasm_module->exports,
+ comp_data->wasm_module->export_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 = wasm_runtime_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(AOTCompContext *comp_ctx, 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 += get_string_size(comp_ctx, relocation->symbol_name);
+ size = align_uint(size, 2);
+ }
+
+ relocation->symbol_index = index;
+ return size;
+}
+
+static uint32
+get_relocations_symbol_size(AOTCompContext *comp_ctx,
+ 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(comp_ctx, relocation, symbol_list);
+ CHECK_SIZE(curr_size);
+
+ size += curr_size;
+ }
+ return size;
+}
+
+static uint32
+get_relocation_group_symbol_size(AOTCompContext *comp_ctx,
+ 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 += get_string_size(comp_ctx, relocation_group->section_name);
+ size = align_uint(size, 2);
+ }
+
+ relocation_group->name_index = index;
+
+ curr_size = get_relocations_symbol_size(
+ comp_ctx, 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(AOTCompContext *comp_ctx,
+ 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(comp_ctx, relocation_group,
+ symbol_list);
+ CHECK_SIZE(curr_size);
+ size += curr_size;
+ }
+ return size;
+}
+
+static uint32
+get_symbol_size_from_symbol_list(AOTCompContext *comp_ctx,
+ AOTSymbolList *symbol_list)
+{
+ AOTSymbolNode *sym;
+ uint32 size = 0;
+
+ sym = symbol_list->head;
+ while (sym) {
+ /* (uint16)str_len + str */
+ size += get_string_size(comp_ctx, sym->symbol);
+ size = align_uint(size, 2);
+ sym = sym->next;
+ }
+
+ return size;
+}
+
+static uint32
+get_relocation_section_symbol_size(AOTCompContext *comp_ctx,
+ 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(comp_ctx, &obj_data->symbol_list);
+ }
+ else {
+ symbol_table_size = get_relocation_groups_symbol_size(
+ comp_ctx, 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(AOTCompContext *comp_ctx, 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(comp_ctx, 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));
+}
+
+static uint32
+get_native_symbol_list_size(AOTCompContext *comp_ctx)
+{
+ uint32 len = 0;
+ AOTNativeSymbol *sym = NULL;
+
+ sym = bh_list_first_elem(&comp_ctx->native_symbols);
+
+ while (sym) {
+ len = align_uint(len, 2);
+ len += get_string_size(comp_ctx, sym->symbol);
+ sym = bh_list_elem_next(sym);
+ }
+
+ return len;
+}
+
+static uint32
+get_name_section_size(AOTCompData *comp_data);
+
+static uint32
+get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data);
+
+static uint32
+get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ AOTObjectData *obj_data)
+{
+ uint32 size = 0;
+ uint32 size_custom_section = 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_ctx, 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_ctx, comp_data);
+
+ /* relocation section */
+ size = align_uint(size, 4);
+ /* section id + section size */
+ size += (uint32)sizeof(uint32) * 2;
+ size += get_relocation_section_size(comp_ctx, obj_data);
+
+ if (get_native_symbol_list_size(comp_ctx) > 0) {
+ /* emit only when there are native symbols */
+ size = align_uint(size, 4);
+ /* section id + section size + sub section id + symbol count */
+ size += (uint32)sizeof(uint32) * 4;
+ size += get_native_symbol_list_size(comp_ctx);
+ }
+
+ if (comp_ctx->enable_aux_stack_frame) {
+ /* custom name section */
+ size = align_uint(size, 4);
+ /* section id + section size + sub section id */
+ size += (uint32)sizeof(uint32) * 3;
+ size += (comp_data->aot_name_section_size =
+ get_name_section_size(comp_data));
+ }
+
+ size_custom_section = get_custom_sections_size(comp_ctx, comp_data);
+ if (size_custom_section > 0) {
+ size = align_uint(size, 4);
+ size += size_custom_section;
+ }
+
+ 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)
+{
+ uint32 value;
+
+ value = *(uint32 *)pData;
+ *(uint32 *)pData = *(uint32 *)(pData + 4);
+ *(uint32 *)(pData + 4) = value;
+ exchange_uint32(pData);
+ exchange_uint32(pData + 4);
+}
+
+static void
+exchange_uint128(uint8 *pData)
+{
+ /* swap high 64bit and low 64bit */
+ uint64 value = *(uint64 *)pData;
+ *(uint64 *)pData = *(uint64 *)(pData + 8);
+ *(uint64 *)(pData + 8) = value;
+ /* exchange high 64bit */
+ exchange_uint64(pData);
+ /* exchange low 64bit */
+ exchange_uint64(pData + 8);
+}
+
+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_V128(v) \
+ do { \
+ uint64 *t = (uint64 *)v.i64x2; \
+ CHECK_BUF(16); \
+ if (!is_little_endian()) \
+ exchange_uint128((uint8 *)t); \
+ PUT_U64_TO_ADDR(buf + offset, t[0]); \
+ offset += (uint32)sizeof(uint64); \
+ PUT_U64_TO_ADDR(buf + offset, t[1]); \
+ 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); \
+ if (str_len > INT16_MAX) { \
+ aot_set_last_error("emit string failed: " \
+ "string too long"); \
+ return false; \
+ } \
+ if (comp_ctx->is_indirect_mode) \
+ /* emit '\0' only in XIP mode */ \
+ str_len++; \
+ EMIT_U16(str_len); \
+ EMIT_BUF(s, str_len); \
+ } while (0)
+
+static bool
+read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
+ uint64 *p_result)
+{
+ const uint8 *buf = *p_buf;
+ uint64 result = 0;
+ uint32 shift = 0;
+ uint32 offset = 0, bcnt = 0;
+ uint64 byte;
+
+ while (true) {
+ /* uN or SN must not exceed ceil(N/7) bytes */
+ if (bcnt + 1 > (maxbits + 6) / 7) {
+ aot_set_last_error("integer representation too long");
+ return false;
+ }
+
+ if (buf + offset + 1 > buf_end) {
+ aot_set_last_error("unexpected end of section or function");
+ return false;
+ }
+ byte = buf[offset];
+ offset += 1;
+ result |= ((byte & 0x7f) << shift);
+ shift += 7;
+ bcnt += 1;
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ }
+
+ if (!sign && maxbits == 32 && shift >= maxbits) {
+ /* The top bits set represent values > 32 bits */
+ if (((uint8)byte) & 0xf0)
+ goto fail_integer_too_large;
+ }
+ else if (sign && maxbits == 32) {
+ if (shift < maxbits) {
+ /* Sign extend, second highest bit is the sign bit */
+ if ((uint8)byte & 0x40)
+ result |= (~((uint64)0)) << shift;
+ }
+ else {
+ /* The top bits should be a sign-extension of the sign bit */
+ bool sign_bit_set = ((uint8)byte) & 0x8;
+ int top_bits = ((uint8)byte) & 0xf0;
+ if ((sign_bit_set && top_bits != 0x70)
+ || (!sign_bit_set && top_bits != 0))
+ goto fail_integer_too_large;
+ }
+ }
+ else if (sign && maxbits == 64) {
+ if (shift < maxbits) {
+ /* Sign extend, second highest bit is the sign bit */
+ if ((uint8)byte & 0x40)
+ result |= (~((uint64)0)) << shift;
+ }
+ else {
+ /* The top bits should be a sign-extension of the sign bit */
+ bool sign_bit_set = ((uint8)byte) & 0x1;
+ int top_bits = ((uint8)byte) & 0xfe;
+
+ if ((sign_bit_set && top_bits != 0x7e)
+ || (!sign_bit_set && top_bits != 0))
+ goto fail_integer_too_large;
+ }
+ }
+
+ *p_buf += offset;
+ *p_result = result;
+ return true;
+
+fail_integer_too_large:
+ aot_set_last_error("integer too large");
+ return false;
+}
+
+#define read_leb_uint32(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ if (!read_leb((uint8 **)&p, p_end, 32, false, &res64)) \
+ goto fail; \
+ res = (uint32)res64; \
+ } while (0)
+
+static uint32
+get_name_section_size(AOTCompData *comp_data)
+{
+ const uint8 *p = comp_data->name_section_buf,
+ *p_end = comp_data->name_section_buf_end;
+ uint8 *buf, *buf_end;
+ uint32 name_type, subsection_size;
+ uint32 previous_name_type = 0;
+ uint32 num_func_name;
+ uint32 func_index;
+ uint32 previous_func_index = ~0U;
+ uint32 func_name_len;
+ uint32 name_index;
+ int i = 0;
+ uint32 name_len;
+ uint32 offset = 0;
+ uint32 max_aot_buf_size = 0;
+
+ if (p >= p_end) {
+ aot_set_last_error("unexpected end");
+ return 0;
+ }
+
+ max_aot_buf_size = 4 * (uint32)(p_end - p);
+ if (!(buf = comp_data->aot_name_section_buf =
+ wasm_runtime_malloc(max_aot_buf_size))) {
+ aot_set_last_error("allocate memory for custom name section failed.");
+ return 0;
+ }
+ buf_end = buf + max_aot_buf_size;
+
+ read_leb_uint32(p, p_end, name_len);
+ offset = align_uint(offset, 4);
+ EMIT_U32(name_len);
+
+ if (name_len == 0 || p + name_len > p_end) {
+ aot_set_last_error("unexpected end");
+ return 0;
+ }
+
+ if (!check_utf8_str(p, name_len)) {
+ aot_set_last_error("invalid UTF-8 encoding");
+ return 0;
+ }
+
+ if (memcmp(p, "name", 4) != 0) {
+ aot_set_last_error("invalid custom name section");
+ return 0;
+ }
+ EMIT_BUF(p, name_len);
+ p += name_len;
+
+ while (p < p_end) {
+ read_leb_uint32(p, p_end, name_type);
+ if (i != 0) {
+ if (name_type == previous_name_type) {
+ aot_set_last_error("duplicate sub-section");
+ return 0;
+ }
+ if (name_type < previous_name_type) {
+ aot_set_last_error("out-of-order sub-section");
+ return 0;
+ }
+ }
+ previous_name_type = name_type;
+ read_leb_uint32(p, p_end, subsection_size);
+ switch (name_type) {
+ case SUB_SECTION_TYPE_FUNC:
+ if (subsection_size) {
+ offset = align_uint(offset, 4);
+ EMIT_U32(name_type);
+ EMIT_U32(subsection_size);
+
+ read_leb_uint32(p, p_end, num_func_name);
+ EMIT_U32(num_func_name);
+
+ for (name_index = 0; name_index < num_func_name;
+ name_index++) {
+ read_leb_uint32(p, p_end, func_index);
+ offset = align_uint(offset, 4);
+ EMIT_U32(func_index);
+ if (func_index == previous_func_index) {
+ aot_set_last_error("duplicate function name");
+ return 0;
+ }
+ if (func_index < previous_func_index
+ && previous_func_index != ~0U) {
+ aot_set_last_error("out-of-order function index ");
+ return 0;
+ }
+ previous_func_index = func_index;
+ read_leb_uint32(p, p_end, func_name_len);
+ offset = align_uint(offset, 2);
+ EMIT_U16(func_name_len);
+ EMIT_BUF(p, func_name_len);
+ p += func_name_len;
+ }
+ }
+ break;
+ case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection
+ */
+ case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */
+ default:
+ p = p + subsection_size;
+ break;
+ }
+ i++;
+ }
+
+ return offset;
+fail:
+ return 0;
+}
+
+static uint32
+get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
+{
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ uint32 size = 0, i;
+
+ for (i = 0; i < comp_ctx->custom_sections_count; i++) {
+ const char *section_name = comp_ctx->custom_sections_wp[i];
+ const uint8 *content = NULL;
+ uint32 length = 0;
+
+ content = wasm_loader_get_custom_section(comp_data->wasm_module,
+ section_name, &length);
+ if (!content) {
+ LOG_WARNING("Can't find custom section [%s], ignore it",
+ section_name);
+ continue;
+ }
+
+ size = align_uint(size, 4);
+ /* section id + section size + sub section id */
+ size += (uint32)sizeof(uint32) * 3;
+ /* section name and len */
+ size += get_string_size(comp_ctx, section_name);
+ /* section content */
+ size += length;
+ }
+
+ return size;
+#else
+ return 0;
+#endif
+}
+
+static bool
+aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+ AOTCompData *comp_data, AOTObjectData *obj_data)
+{
+ uint32 offset = *p_offset;
+ uint32 aot_curr_version = AOT_CURRENT_VERSION;
+
+ EMIT_U8('\0');
+ EMIT_U8('a');
+ EMIT_U8('o');
+ EMIT_U8('t');
+
+ EMIT_U32(aot_curr_version);
+
+ *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_U16(target_info->bin_type);
+ EMIT_U16(target_info->abi_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,
+ AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ AOTObjectData *obj_data)
+{
+ uint32 offset = *p_offset, i;
+ AOTMemInitData **init_datas = comp_data->mem_init_data_list;
+
+ *p_offset = offset = align_uint(offset, 4);
+
+ /* Emit import memory count, only emit 0 currently.
+ TODO: emit the actual import memory count and
+ the full import memory info. */
+ EMIT_U32(0);
+
+ /* Emit memory count */
+ EMIT_U32(comp_data->memory_count);
+ /* Emit memory items */
+ for (i = 0; i < comp_data->memory_count; i++) {
+ EMIT_U32(comp_data->memories[i].memory_flags);
+ EMIT_U32(comp_data->memories[i].num_bytes_per_page);
+ EMIT_U32(comp_data->memories[i].mem_init_page_count);
+ EMIT_U32(comp_data->memories[i].mem_max_page_count);
+ }
+
+ /* Emit mem init data count */
+ EMIT_U32(comp_data->mem_init_data_count);
+ /* Emit mem init data items */
+ for (i = 0; i < comp_data->mem_init_data_count; i++) {
+ offset = align_uint(offset, 4);
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if (comp_ctx->enable_bulk_memory) {
+ EMIT_U32(init_datas[i]->is_passive);
+ EMIT_U32(init_datas[i]->memory_index);
+ }
+ else
+#endif
+ {
+ /* emit two placeholder to keep the same size */
+ EMIT_U32(0);
+ EMIT_U32(0);
+ }
+ 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,
+ AOTCompContext *comp_ctx, 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 import table count */
+ EMIT_U32(comp_data->import_table_count);
+ /* Emit table items */
+ for (i = 0; i < comp_data->import_table_count; i++) {
+ /* TODO:
+ * EMIT_STR(comp_data->import_tables[i].module_name );
+ * EMIT_STR(comp_data->import_tables[i].table_name);
+ */
+ EMIT_U32(comp_data->import_tables[i].elem_type);
+ EMIT_U32(comp_data->import_tables[i].table_init_size);
+ EMIT_U32(comp_data->import_tables[i].table_max_size);
+ EMIT_U32(comp_data->import_tables[i].possible_grow & 0x000000FF);
+ }
+
+ /* Emit table count */
+ EMIT_U32(comp_data->table_count);
+ /* Emit table items */
+ for (i = 0; i < comp_data->table_count; i++) {
+ EMIT_U32(comp_data->tables[i].elem_type);
+ EMIT_U32(comp_data->tables[i].table_flags);
+ EMIT_U32(comp_data->tables[i].table_init_size);
+ EMIT_U32(comp_data->tables[i].table_max_size);
+ EMIT_U32(comp_data->tables[i].possible_grow & 0x000000FF);
+ }
+
+ /* Emit table init data count */
+ EMIT_U32(comp_data->table_init_data_count);
+ /* Emit table init data items */
+ for (i = 0; i < comp_data->table_init_data_count; i++) {
+ offset = align_uint(offset, 4);
+ EMIT_U32(init_datas[i]->mode);
+ EMIT_U32(init_datas[i]->elem_type);
+ EMIT_U32(init_datas[i]->table_index);
+ 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,
+ AOTCompContext *comp_ctx, 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_ctx, 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);
+ if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
+ EMIT_U64(global->init_expr.u.i64);
+ else
+ EMIT_V128(global->init_expr.u.v128);
+ }
+
+ 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,
+ AOTCompContext *comp_ctx, 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_ctx, 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,
+ AOTCompContext *comp_ctx,
+ 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(comp_ctx, 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,
+ AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ AOTObjectData *obj_data)
+{
+ uint32 section_size =
+ get_init_data_section_size(comp_ctx, 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_ctx, comp_data, obj_data)
+ || !aot_emit_table_info(buf, buf_end, &offset, comp_ctx, 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_ctx,
+ 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_ctx,
+ comp_data, obj_data))
+ return false;
+
+ offset = align_uint(offset, 4);
+ EMIT_U32(comp_data->func_count);
+ EMIT_U32(comp_data->start_func_index);
+
+ EMIT_U32(comp_data->aux_data_end_global_index);
+ EMIT_U32(comp_data->aux_data_end);
+ EMIT_U32(comp_data->aux_heap_base_global_index);
+ EMIT_U32(comp_data->aux_heap_base);
+ EMIT_U32(comp_data->aux_stack_top_global_index);
+ EMIT_U32(comp_data->aux_stack_bottom);
+ EMIT_U32(comp_data->aux_stack_size);
+
+ if (!aot_emit_object_data_section_info(buf, buf_end, &offset, comp_ctx,
+ 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;
+ uint8 placeholder = 0;
+
+ *p_offset = offset = align_uint(offset, 4);
+
+ EMIT_U32(AOT_SECTION_TYPE_TEXT);
+ EMIT_U32(section_size);
+ EMIT_U32(obj_data->literal_size);
+ if (obj_data->literal_size > 0)
+ EMIT_BUF(obj_data->literal, obj_data->literal_size);
+ EMIT_BUF(obj_data->text, obj_data->text_size);
+
+ while (offset & 3)
+ EMIT_BUF(&placeholder, 1);
+
+ 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))
+ 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,
+ AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ AOTObjectData *obj_data)
+{
+ uint32 section_size = get_export_section_size(comp_ctx, comp_data);
+ AOTExport *export = comp_data->wasm_module->exports;
+ uint32 export_count = comp_data->wasm_module->export_count;
+ uint32 i, offset = *p_offset;
+
+ *p_offset = offset = align_uint(offset, 4);
+
+ EMIT_U32(AOT_SECTION_TYPE_EXPORT);
+ EMIT_U32(section_size);
+ EMIT_U32(export_count);
+
+ for (i = 0; i < export_count; i++, export ++) {
+ offset = align_uint(offset, 4);
+ EMIT_U32(export->index);
+ EMIT_U8(export->kind);
+ EMIT_U8(0);
+ EMIT_STR(export->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,
+ AOTCompContext *comp_ctx,
+ 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 += get_string_size(comp_ctx, sym->symbol);
+ 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,
+ AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ AOTObjectData *obj_data)
+{
+ uint32 section_size = get_relocation_section_size(comp_ctx, 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_ctx, 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)) {
+ 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;
+}
+
+static bool
+aot_emit_native_symbol(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+ AOTCompContext *comp_ctx)
+{
+ uint32 offset = *p_offset;
+ AOTNativeSymbol *sym = NULL;
+
+ if (bh_list_length(&comp_ctx->native_symbols) == 0)
+ /* emit only when there are native symbols */
+ return true;
+
+ *p_offset = offset = align_uint(offset, 4);
+
+ EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
+ /* sub section id + symbol count + symbol list */
+ EMIT_U32(sizeof(uint32) * 2 + get_native_symbol_list_size(comp_ctx));
+ EMIT_U32(AOT_CUSTOM_SECTION_NATIVE_SYMBOL);
+ EMIT_U32(bh_list_length(&comp_ctx->native_symbols));
+
+ sym = bh_list_first_elem(&comp_ctx->native_symbols);
+
+ while (sym) {
+ offset = align_uint(offset, 2);
+ EMIT_STR(sym->symbol);
+ sym = bh_list_elem_next(sym);
+ }
+
+ *p_offset = offset;
+
+ return true;
+}
+
+static bool
+aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+ AOTCompData *comp_data, AOTCompContext *comp_ctx)
+{
+ if (comp_ctx->enable_aux_stack_frame) {
+ uint32 offset = *p_offset;
+
+ *p_offset = offset = align_uint(offset, 4);
+
+ EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
+ /* sub section id + name section size */
+ EMIT_U32(sizeof(uint32) * 1 + comp_data->aot_name_section_size);
+ EMIT_U32(AOT_CUSTOM_SECTION_NAME);
+ bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf),
+ comp_data->aot_name_section_buf,
+ (uint32)comp_data->aot_name_section_size);
+ offset += comp_data->aot_name_section_size;
+
+ *p_offset = offset;
+ }
+
+ return true;
+}
+
+static bool
+aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+ AOTCompData *comp_data, AOTCompContext *comp_ctx)
+{
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ uint32 offset = *p_offset, i;
+
+ for (i = 0; i < comp_ctx->custom_sections_count; i++) {
+ const char *section_name = comp_ctx->custom_sections_wp[i];
+ const uint8 *content = NULL;
+ uint32 length = 0;
+
+ content = wasm_loader_get_custom_section(comp_data->wasm_module,
+ section_name, &length);
+ if (!content) {
+ /* Warning has been reported during calculating size */
+ continue;
+ }
+
+ offset = align_uint(offset, 4);
+ EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
+ /* sub section id + content */
+ EMIT_U32(sizeof(uint32) * 1 + get_string_size(comp_ctx, section_name)
+ + length);
+ EMIT_U32(AOT_CUSTOM_SECTION_RAW);
+ EMIT_STR(section_name);
+ bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf), content,
+ length);
+ offset += length;
+ }
+
+ *p_offset = offset;
+#endif
+
+ return true;
+}
+
+typedef uint32 U32;
+typedef int32 I32;
+typedef uint16 U16;
+typedef uint8 U8;
+
+struct coff_hdr {
+ U16 u16Machine;
+ U16 u16NumSections;
+ U32 u32DateTimeStamp;
+ U32 u32SymTblPtr;
+ U32 u32NumSymbols;
+ U16 u16PeHdrSize;
+ U16 u16Characs;
+};
+
+#define E_TYPE_REL 1
+#define E_TYPE_XIP 4
+
+#define IMAGE_FILE_MACHINE_AMD64 0x8664
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_IA64 0x0200
+
+#define AOT_COFF32_BIN_TYPE 4 /* 32-bit little endian */
+#define AOT_COFF64_BIN_TYPE 6 /* 64-bit little endian */
+
+#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 != LLVMBinaryTypeCOFF && bin_type != LLVMBinaryTypeELF32L
+ && bin_type != LLVMBinaryTypeELF32B && bin_type != LLVMBinaryTypeELF64L
+ && bin_type != LLVMBinaryTypeELF64B
+ && bin_type != LLVMBinaryTypeMachO32L
+ && bin_type != LLVMBinaryTypeMachO32B
+ && bin_type != LLVMBinaryTypeMachO64L
+ && bin_type != LLVMBinaryTypeMachO64B) {
+ aot_set_last_error("invaid llvm binary bin_type.");
+ return false;
+ }
+
+ obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L;
+
+ if (bin_type == LLVMBinaryTypeCOFF) {
+ struct coff_hdr *coff_header;
+
+ if (!elf_buf || elf_size < sizeof(struct coff_hdr)) {
+ aot_set_last_error("invalid coff_hdr buffer.");
+ return false;
+ }
+ coff_header = (struct coff_hdr *)elf_buf;
+
+ /* Emit eXecute In Place file type while in indirect mode */
+ if (comp_ctx->is_indirect_mode)
+ obj_data->target_info.e_type = E_TYPE_XIP;
+ else
+ obj_data->target_info.e_type = E_TYPE_REL;
+
+ obj_data->target_info.e_machine = coff_header->u16Machine;
+ obj_data->target_info.e_version = 1;
+ obj_data->target_info.e_flags = 0;
+
+ if (coff_header->u16Machine == IMAGE_FILE_MACHINE_AMD64
+ || coff_header->u16Machine == IMAGE_FILE_MACHINE_IA64)
+ obj_data->target_info.bin_type = AOT_COFF64_BIN_TYPE;
+ else if (coff_header->u16Machine == IMAGE_FILE_MACHINE_I386)
+ obj_data->target_info.bin_type = AOT_COFF32_BIN_TYPE;
+ }
+ else 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;
+
+ /* Emit eXecute In Place file type while in indirect mode */
+ if (comp_ctx->is_indirect_mode)
+ elf_header->e_type = E_TYPE_XIP;
+
+ 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 if (bin_type == LLVMBinaryTypeELF64L
+ || bin_type == LLVMBinaryTypeELF64B) {
+ 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;
+
+ /* Emit eXecute In Place file type while in indirect mode */
+ if (comp_ctx->is_indirect_mode)
+ elf_header->e_type = E_TYPE_XIP;
+
+ 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 if (bin_type == LLVMBinaryTypeMachO32L
+ || bin_type == LLVMBinaryTypeMachO32B) {
+ /* TODO: parse file type of Mach-O 32 */
+ aot_set_last_error("invaid llvm binary bin_type.");
+ return false;
+ }
+ else if (bin_type == LLVMBinaryTypeMachO64L
+ || bin_type == LLVMBinaryTypeMachO64B) {
+ /* TODO: parse file type of Mach-O 64 */
+ aot_set_last_error("invaid llvm binary bin_type.");
+ return false;
+ }
+
+ bh_assert(sizeof(obj_data->target_info.arch)
+ == sizeof(comp_ctx->target_arch));
+ bh_memcpy_s(obj_data->target_info.arch, sizeof(obj_data->target_info.arch),
+ comp_ctx->target_arch, sizeof(comp_ctx->target_arch));
+
+ return true;
+}
+
+static bool
+aot_resolve_text(AOTObjectData *obj_data)
+{
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMBinaryType bin_type = LLVMBinaryGetType(obj_data->binary);
+ if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF64L) {
+ obj_data->text = (char *)LLVMGetBufferStart(obj_data->mem_buf);
+ obj_data->text_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
+ }
+ else
+#endif
+ {
+ 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
+aot_resolve_literal(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, ".literal")) {
+ obj_data->literal = (char *)LLVMGetSectionContents(sec_itr);
+ obj_data->literal_size = (uint32)LLVMGetSectionSize(sec_itr);
+ break;
+ }
+ LLVMMoveToNextSection(sec_itr);
+ }
+ LLVMDisposeSectionIterator(sec_itr);
+
+ return true;
+}
+
+static bool
+get_relocations_count(LLVMSectionIteratorRef sec_itr, uint32 *p_count);
+
+static bool
+is_data_section(LLVMSectionIteratorRef sec_itr, char *section_name)
+{
+ uint32 relocation_count = 0;
+
+ return (!strcmp(section_name, ".data") || !strcmp(section_name, ".sdata")
+ || !strcmp(section_name, ".rodata")
+ /* ".rodata.cst4/8/16/.." */
+ || !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst"))
+ /* ".rodata.strn.m" */
+ || !strncmp(section_name, ".rodata.str", strlen(".rodata.str"))
+ || (!strcmp(section_name, ".rdata")
+ && get_relocations_count(sec_itr, &relocation_count)
+ && relocation_count > 0));
+}
+
+static bool
+get_object_data_sections_count(AOTObjectData *obj_data, uint32 *p_count)
+{
+ 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 false;
+ }
+ while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
+ if ((name = (char *)LLVMGetSectionName(sec_itr))
+ && (is_data_section(sec_itr, name))) {
+ count++;
+ }
+ LLVMMoveToNextSection(sec_itr);
+ }
+ LLVMDisposeSectionIterator(sec_itr);
+
+ *p_count = count;
+ return true;
+}
+
+static bool
+aot_resolve_object_data_sections(AOTObjectData *obj_data)
+{
+ LLVMSectionIteratorRef sec_itr;
+ char *name;
+ AOTObjectDataSection *data_section;
+ uint32 sections_count;
+ uint32 size;
+
+ if (!get_object_data_sections_count(obj_data, &sections_count)) {
+ return false;
+ }
+
+ if (sections_count > 0) {
+ size = (uint32)sizeof(AOTObjectDataSection) * sections_count;
+ if (!(data_section = obj_data->data_sections =
+ wasm_runtime_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(sec_itr, 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, total_size;
+
+ /* allocate memory for aot function */
+ obj_data->func_count = comp_ctx->comp_data->func_count;
+ if (obj_data->func_count) {
+ total_size = (uint32)sizeof(AOTObjectFunc) * obj_data->func_count;
+ if (!(obj_data->funcs = wasm_runtime_malloc(total_size))) {
+ aot_set_last_error("allocate memory for functions failed.");
+ return false;
+ }
+ memset(obj_data->funcs, 0, total_size);
+ }
+
+ 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);
+ bool is_binary_little_endian = is_little_endian_binary(obj_data);
+ bool has_addend = str_starts_with(group->section_name, ".rela");
+ uint8 *rela_content = NULL;
+
+ /* calculate relocations count and allocate 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 = wasm_runtime_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) {
+ int32 addend =
+ (int32)(((struct elf32_rela *)rela_content)->r_addend);
+ if (is_binary_little_endian != is_little_endian())
+ exchange_uint32((uint8 *)&addend);
+ relocation->relocation_addend = (int64)addend;
+ rela_content += sizeof(struct elf32_rela);
+ }
+ else {
+ int64 addend =
+ (int64)(((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", ".LJTIxxx", ".LBBxxx" and switch lookup table
+ * relocation, transform the symbol name to real section name and set
+ * addend to the offset of the symbol in the real section */
+ if (relocation->symbol_name
+ && (str_starts_with(relocation->symbol_name, ".LCPI")
+ || str_starts_with(relocation->symbol_name, ".LJTI")
+ || str_starts_with(relocation->symbol_name, ".LBB")
+ || str_starts_with(relocation->symbol_name,
+ ".Lswitch.table."))) {
+ /* 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_name(char *section_name)
+{
+ return (!strcmp(section_name, ".rela.text")
+ || !strcmp(section_name, ".rel.text")
+ || !strcmp(section_name, ".rela.literal")
+ || !strcmp(section_name, ".rela.data")
+ || !strcmp(section_name, ".rel.data")
+ || !strcmp(section_name, ".rela.sdata")
+ || !strcmp(section_name, ".rel.sdata")
+ || !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
+is_relocation_section(LLVMSectionIteratorRef sec_itr)
+{
+ uint32 count = 0;
+ char *name = (char *)LLVMGetSectionName(sec_itr);
+ if (name) {
+ if (is_relocation_section_name(name))
+ return true;
+ else if ((!strcmp(name, ".text") || !strcmp(name, ".rdata"))
+ && get_relocations_count(sec_itr, &count) && count > 0)
+ return true;
+ }
+ return false;
+}
+
+static bool
+get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count)
+{
+ uint32 count = 0;
+ LLVMSectionIteratorRef sec_itr;
+
+ 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 (is_relocation_section(sec_itr)) {
+ 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 allocate 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 =
+ wasm_runtime_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 (is_relocation_section(sec_itr)) {
+ name = (char *)LLVMGetSectionName(sec_itr);
+ 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)
+ wasm_runtime_free(relocation_group->relocations);
+ wasm_runtime_free(relocation_groups);
+}
+
+static void
+destroy_relocation_symbol_list(AOTSymbolList *symbol_list)
+{
+ AOTSymbolNode *elem;
+
+ elem = symbol_list->head;
+ while (elem) {
+ AOTSymbolNode *next = elem->next;
+ wasm_runtime_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)
+ wasm_runtime_free(obj_data->funcs);
+ if (obj_data->data_sections)
+ wasm_runtime_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);
+ wasm_runtime_free(obj_data);
+}
+
+static AOTObjectData *
+aot_obj_data_create(AOTCompContext *comp_ctx)
+{
+ char *err = NULL;
+ AOTObjectData *obj_data;
+ LLVMTargetRef target = LLVMGetTargetMachineTarget(comp_ctx->target_machine);
+
+ bh_print_time("Begin to emit object file to buffer");
+
+ if (!(obj_data = wasm_runtime_malloc(sizeof(AOTObjectData)))) {
+ aot_set_last_error("allocate memory failed.");
+ return false;
+ }
+ memset(obj_data, 0, sizeof(AOTObjectData));
+
+ bh_print_time("Begin to emit object file");
+ if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
+#if defined(_WIN32) || defined(_WIN32_)
+ aot_set_last_error("external toolchain not supported on Windows");
+ goto fail;
+#else
+ /* Generate a temp file name */
+ int ret;
+ char obj_file_name[64];
+
+ if (!aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name,
+ sizeof(obj_file_name))) {
+ goto fail;
+ }
+
+ if (!aot_emit_object_file(comp_ctx, obj_file_name)) {
+ goto fail;
+ }
+
+ /* create memory buffer from object file */
+ ret = LLVMCreateMemoryBufferWithContentsOfFile(
+ obj_file_name, &obj_data->mem_buf, &err);
+ /* remove temp object file */
+ unlink(obj_file_name);
+
+ if (ret != 0) {
+ if (err) {
+ LLVMDisposeMessage(err);
+ err = NULL;
+ }
+ aot_set_last_error("create mem buffer with file failed.");
+ goto fail;
+ }
+#endif /* end of defined(_WIN32) || defined(_WIN32_) */
+ }
+ else if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
+#if defined(_WIN32) || defined(_WIN32_)
+ aot_set_last_error("emit object file on Windows is unsupported.");
+ goto fail;
+#else
+ /* Emit to assmelby file instead for arc target
+ as it cannot emit to object file */
+ char file_name[] = "wasm-XXXXXX", buf[128];
+ int fd, ret;
+
+ if ((fd = mkstemp(file_name)) <= 0) {
+ aot_set_last_error("make temp file failed.");
+ goto fail;
+ }
+
+ /* close and remove temp file */
+ close(fd);
+ unlink(file_name);
+
+ snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
+ if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
+ comp_ctx->module, buf, LLVMAssemblyFile,
+ &err)
+ != 0) {
+ if (err) {
+ LLVMDisposeMessage(err);
+ err = NULL;
+ }
+ aot_set_last_error("emit elf to object file failed.");
+ goto fail;
+ }
+
+ /* call arc gcc to compile assembly file to object file */
+ /* TODO: get arc gcc from environment variable firstly
+ and check whether the toolchain exists actually */
+ snprintf(buf, sizeof(buf), "%s%s%s%s%s%s",
+ "/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ",
+ "-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s");
+ /* TODO: use try..catch to handle possible exceptions */
+ ret = system(buf);
+ /* remove temp assembly file */
+ snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
+ unlink(buf);
+
+ if (ret != 0) {
+ aot_set_last_error("failed to compile asm file to obj file "
+ "with arc gcc toolchain.");
+ goto fail;
+ }
+
+ /* create memory buffer from object file */
+ snprintf(buf, sizeof(buf), "%s%s", file_name, ".o");
+ ret = LLVMCreateMemoryBufferWithContentsOfFile(buf, &obj_data->mem_buf,
+ &err);
+ /* remove temp object file */
+ snprintf(buf, sizeof(buf), "%s%s", file_name, ".o");
+ unlink(buf);
+
+ if (ret != 0) {
+ if (err) {
+ LLVMDisposeMessage(err);
+ err = NULL;
+ }
+ aot_set_last_error("create mem buffer with file failed.");
+ goto fail;
+ }
+#endif /* end of defined(_WIN32) || defined(_WIN32_) */
+ }
+ else {
+ 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;
+ }
+
+ bh_print_time("Begin to resolve object file info");
+
+ /* resolve target info/text/relocations/functions */
+ if (!aot_resolve_target_info(comp_ctx, obj_data)
+ || !aot_resolve_text(obj_data) || !aot_resolve_literal(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;
+}
+
+uint8 *
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ uint32 *p_aot_file_size)
+{
+ AOTObjectData *obj_data = aot_obj_data_create(comp_ctx);
+ uint8 *aot_file_buf, *buf, *buf_end;
+ uint32 aot_file_size, offset = 0;
+
+ if (!obj_data)
+ return NULL;
+
+ aot_file_size = get_aot_file_size(comp_ctx, comp_data, obj_data);
+
+ if (!(buf = aot_file_buf = wasm_runtime_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_ctx,
+ 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_ctx, comp_data,
+ obj_data)
+ || !aot_emit_relocation_section(buf, buf_end, &offset, comp_ctx,
+ comp_data, obj_data)
+ || !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx)
+ || !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx)
+ || !aot_emit_custom_sections(buf, buf_end, &offset, comp_data,
+ comp_ctx))
+ 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;
+ }
+
+ *p_aot_file_size = aot_file_size;
+
+ aot_obj_data_destroy(obj_data);
+ return aot_file_buf;
+
+fail2:
+ wasm_runtime_free(aot_file_buf);
+
+fail1:
+ aot_obj_data_destroy(obj_data);
+ return NULL;
+}
+
+bool
+aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+ const char *file_name)
+{
+ uint8 *aot_file_buf;
+ uint32 aot_file_size;
+ bool ret = false;
+ FILE *file;
+
+ bh_print_time("Begin to emit AOT file");
+
+ if (!(aot_file_buf =
+ aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size))) {
+ return false;
+ }
+
+ /* write buffer to file */
+ if (!(file = fopen(file_name, "wb"))) {
+ aot_set_last_error("open or create aot file failed.");
+ goto fail1;
+ }
+ if (!fwrite(aot_file_buf, aot_file_size, 1, file)) {
+ aot_set_last_error("write to aot file failed.");
+ goto fail2;
+ }
+
+ ret = true;
+
+fail2:
+ fclose(file);
+
+fail1:
+ wasm_runtime_free(aot_file_buf);
+
+ return ret;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.c
new file mode 100644
index 000000000..a38263264
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_emit_compare.h"
+#include "../aot/aot_intrinsic.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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, "f32_cmp")) {
+ LLVMTypeRef param_types[3];
+ LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true);
+ param_types[0] = I32_TYPE;
+ param_types[1] = F32_TYPE;
+ param_types[2] = F32_TYPE;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_cmp", I32_TYPE,
+ param_types, 3, opcond, lhs, rhs);
+ if (!res) {
+ goto fail;
+ }
+ res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast");
+ }
+ else {
+ res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f32_cmp");
+ }
+
+ if (!res) {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, "f64_cmp")) {
+ LLVMTypeRef param_types[3];
+ LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true);
+ param_types[0] = I32_TYPE;
+ param_types[1] = F64_TYPE;
+ param_types[2] = F64_TYPE;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f64_cmp", I32_TYPE,
+ param_types, 3, opcond, lhs, rhs);
+ if (!res) {
+ goto fail;
+ }
+ res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast");
+ }
+ else {
+ res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f64_cmp");
+ }
+
+ if (!res) {
+ aot_set_last_error("llvm build compare failed.");
+ return false;
+ }
+
+ PUSH_COND(res);
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.h
new file mode 100644
index 000000000..6ac37794c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_compare.h
@@ -0,0 +1,35 @@
+/*
+ * 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.c
new file mode 100644
index 000000000..4b38aa962
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_emit_const.h"
+#include "../aot/aot_intrinsic.h"
+
+bool
+aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ int32 i32_const)
+{
+ LLVMValueRef value;
+
+ if (comp_ctx->is_indirect_mode
+ && aot_intrinsic_check_capability(comp_ctx, "i32.const")) {
+ WASMValue wasm_value;
+ wasm_value.i32 = i32_const;
+ value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol,
+ &wasm_value, VALUE_TYPE_I32);
+ if (!value) {
+ return false;
+ }
+ }
+ else {
+ 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;
+
+ if (comp_ctx->is_indirect_mode
+ && aot_intrinsic_check_capability(comp_ctx, "i64.const")) {
+ WASMValue wasm_value;
+ wasm_value.i64 = i64_const;
+ value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol,
+ &wasm_value, VALUE_TYPE_I64);
+ if (!value) {
+ return false;
+ }
+ }
+ else {
+ 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)) {
+ if (comp_ctx->is_indirect_mode
+ && aot_intrinsic_check_capability(comp_ctx, "f32.const")) {
+ WASMValue wasm_value;
+ memcpy(&wasm_value.f32, &f32_const, sizeof(float32));
+ value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol,
+ &wasm_value, VALUE_TYPE_F32);
+ if (!value) {
+ return false;
+ }
+ PUSH_F32(value);
+ }
+ else {
+ 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, I32_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 =
+ LLVMBuildLoad2(comp_ctx->builder, F32_TYPE, 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)) {
+ if (comp_ctx->is_indirect_mode
+ && aot_intrinsic_check_capability(comp_ctx, "f64.const")) {
+ WASMValue wasm_value;
+ memcpy(&wasm_value.f64, &f64_const, sizeof(float64));
+ value = aot_load_const_from_table(comp_ctx, func_ctx->native_symbol,
+ &wasm_value, VALUE_TYPE_F64);
+ if (!value) {
+ return false;
+ }
+ PUSH_F64(value);
+ }
+ else {
+ 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 =
+ LLVMBuildLoad2(comp_ctx->builder, F64_TYPE, alloca, ""))) {
+ aot_set_last_error("llvm build load failed.");
+ return false;
+ }
+ PUSH_F64(value);
+ }
+
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.h
new file mode 100644
index 000000000..0b56cb13b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_const.h
@@ -0,0 +1,35 @@
+/*
+ * 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.c
new file mode 100644
index 000000000..2cf51cf67
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.c
@@ -0,0 +1,1155 @@
+/*
+ * 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"
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+#include "debug/dwarf_extractor.h"
+#endif
+
+static char *block_name_prefix[] = { "block", "loop", "if" };
+static char *block_name_suffix[] = { "begin", "else", "end" };
+
+/* clang-format off */
+enum {
+ LABEL_BEGIN = 0,
+ LABEL_ELSE,
+ LABEL_END
+};
+/* clang-format on */
+
+static void
+format_block_name(char *name, uint32 name_size, uint32 block_index,
+ uint32 label_type, uint32 label_id)
+{
+ if (label_type != LABEL_TYPE_FUNCTION)
+ snprintf(name, name_size, "%s%d%s%s", block_name_prefix[label_type],
+ block_index, "_", block_name_suffix[label_id]);
+ 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_RESULT_VALUE_PHIS(block) \
+ do { \
+ if (block->result_count && !block->result_phis) { \
+ uint32 _i; \
+ uint64 _size; \
+ LLVMBasicBlockRef _block_curr = CURR_BLOCK(); \
+ /* Allocate memory */ \
+ _size = sizeof(LLVMValueRef) * (uint64)block->result_count; \
+ if (_size >= UINT32_MAX \
+ || !(block->result_phis = \
+ wasm_runtime_malloc((uint32)_size))) { \
+ aot_set_last_error("allocate memory failed."); \
+ goto fail; \
+ } \
+ SET_BUILDER_POS(block->llvm_end_block); \
+ for (_i = 0; _i < block->result_count; _i++) { \
+ if (!(block->result_phis[_i] = LLVMBuildPhi( \
+ comp_ctx->builder, \
+ TO_LLVM_TYPE(block->result_types[_i]), "phi"))) { \
+ aot_set_last_error("llvm build phi failed."); \
+ goto fail; \
+ } \
+ } \
+ SET_BUILDER_POS(_block_curr); \
+ } \
+ } while (0)
+
+#define ADD_TO_RESULT_PHIS(block, value, idx) \
+ do { \
+ LLVMBasicBlockRef _block_curr = CURR_BLOCK(); \
+ LLVMTypeRef phi_ty = LLVMTypeOf(block->result_phis[idx]); \
+ LLVMTypeRef value_ty = LLVMTypeOf(value); \
+ bh_assert(LLVMGetTypeKind(phi_ty) == LLVMGetTypeKind(value_ty)); \
+ bh_assert(LLVMGetTypeContext(phi_ty) == LLVMGetTypeContext(value_ty)); \
+ LLVMAddIncoming(block->result_phis[idx], &value, &_block_curr, 1); \
+ (void)phi_ty; \
+ (void)value_ty; \
+ } while (0)
+
+#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 ADD_TO_PARAM_PHIS(block, value, idx) \
+ do { \
+ LLVMBasicBlockRef _block_curr = CURR_BLOCK(); \
+ LLVMAddIncoming(block->param_phis[idx], &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 = NULL;
+ uint32 i;
+ AOTFuncType *func_type;
+ LLVMValueRef ret;
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMMetadataRef return_location;
+#endif
+
+ aot_checked_addr_list_destroy(func_ctx);
+ bh_assert(block);
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ return_location = dwarf_gen_location(
+ comp_ctx, func_ctx,
+ (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
+#endif
+ if (block->label_type == LABEL_TYPE_IF && block->llvm_else_block
+ && *p_frame_ip <= block->wasm_code_else) {
+ /* Clear value stack and start to translate else branch */
+ aot_value_stack_destroy(&block->value_stack);
+ /* Recover parameters of else branch */
+ for (i = 0; i < block->param_count; i++)
+ PUSH(block->else_param_phis[i], block->param_types[i]);
+ 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->label_type == LABEL_TYPE_IF) {
+ 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;
+ /* Push back the block */
+ aot_block_stack_push(&func_ctx->block_stack, block);
+ return true;
+ }
+ else if (block->llvm_end_block) {
+ /* Remove unreachable basic 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);
+ func_type = func_ctx->aot_func->func_type;
+ for (i = 0; i < block->result_count; i++) {
+ bh_assert(block->result_phis[i]);
+ if (block->label_type != LABEL_TYPE_FUNCTION) {
+ PUSH(block->result_phis[i], block->result_types[i]);
+ }
+ else {
+ /* Store extra return values to function parameters */
+ if (i != 0) {
+ uint32 param_index = func_type->param_count + i;
+ if (!LLVMBuildStore(
+ comp_ctx->builder, block->result_phis[i],
+ LLVMGetParam(func_ctx->func, param_index))) {
+ aot_set_last_error("llvm build store failed.");
+ goto fail;
+ }
+ }
+ }
+ }
+ if (block->label_type == LABEL_TYPE_FUNCTION) {
+ if (block->result_count) {
+ /* Return the first return value */
+ if (!(ret =
+ LLVMBuildRet(comp_ctx->builder, block->result_phis[0]))) {
+ aot_set_last_error("llvm build return failed.");
+ goto fail;
+ }
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMInstructionSetDebugLoc(ret, return_location);
+#endif
+ }
+ else {
+ if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
+ aot_set_last_error("llvm build return void failed.");
+ goto fail;
+ }
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMInstructionSetDebugLoc(ret, return_location);
+#endif
+ }
+ }
+ aot_block_destroy(block);
+ return true;
+fail:
+ return false;
+}
+
+static bool
+push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ AOTBlock *block)
+{
+ uint32 i, param_index;
+ LLVMValueRef value;
+ uint64 size;
+ char name[32];
+ LLVMBasicBlockRef block_curr = CURR_BLOCK();
+
+ if (block->param_count) {
+ size = sizeof(LLVMValueRef) * (uint64)block->param_count;
+ if (size >= UINT32_MAX
+ || !(block->param_phis = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ return false;
+ }
+
+ if (block->label_type == LABEL_TYPE_IF && !block->skip_wasm_code_else
+ && !(block->else_param_phis = wasm_runtime_malloc((uint32)size))) {
+ wasm_runtime_free(block->param_phis);
+ block->param_phis = NULL;
+ aot_set_last_error("allocate memory failed.");
+ return false;
+ }
+
+ /* Create param phis */
+ for (i = 0; i < block->param_count; i++) {
+ SET_BUILDER_POS(block->llvm_entry_block);
+ snprintf(name, sizeof(name), "%s%d_phi%d",
+ block_name_prefix[block->label_type], block->block_index,
+ i);
+ if (!(block->param_phis[i] = LLVMBuildPhi(
+ comp_ctx->builder, TO_LLVM_TYPE(block->param_types[i]),
+ name))) {
+ aot_set_last_error("llvm build phi failed.");
+ goto fail;
+ }
+
+ if (block->label_type == LABEL_TYPE_IF
+ && !block->skip_wasm_code_else && block->llvm_else_block) {
+ /* Build else param phis */
+ SET_BUILDER_POS(block->llvm_else_block);
+ snprintf(name, sizeof(name), "else%d_phi%d", block->block_index,
+ i);
+ if (!(block->else_param_phis[i] = LLVMBuildPhi(
+ comp_ctx->builder,
+ TO_LLVM_TYPE(block->param_types[i]), name))) {
+ aot_set_last_error("llvm build phi failed.");
+ goto fail;
+ }
+ }
+ }
+ SET_BUILDER_POS(block_curr);
+
+ /* Pop param values from current block's
+ * value stack and add to param phis.
+ */
+ for (i = 0; i < block->param_count; i++) {
+ param_index = block->param_count - 1 - i;
+ POP(value, block->param_types[param_index]);
+ ADD_TO_PARAM_PHIS(block, value, param_index);
+ if (block->label_type == LABEL_TYPE_IF
+ && !block->skip_wasm_code_else) {
+ if (block->llvm_else_block) {
+ /* has else branch, add to else param phis */
+ LLVMAddIncoming(block->else_param_phis[param_index], &value,
+ &block_curr, 1);
+ }
+ else {
+ /* no else branch, add to result phis */
+ CREATE_RESULT_VALUE_PHIS(block);
+ ADD_TO_RESULT_PHIS(block, value, param_index);
+ }
+ }
+ }
+ }
+
+ /* Push the new block to block stack */
+ aot_block_stack_push(&func_ctx->block_stack, block);
+
+ /* Push param phis to the new block */
+ for (i = 0; i < block->param_count; i++) {
+ PUSH(block->param_phis[i], block->param_types[i]);
+ }
+
+ return true;
+
+fail:
+ if (block->param_phis) {
+ wasm_runtime_free(block->param_phis);
+ block->param_phis = NULL;
+ }
+ if (block->else_param_phis) {
+ wasm_runtime_free(block->else_param_phis);
+ block->else_param_phis = NULL;
+ }
+ return false;
+}
+
+bool
+aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 **p_frame_ip, uint8 *frame_ip_end, uint32 label_type,
+ uint32 param_count, uint8 *param_types,
+ uint32 result_count, uint8 *result_types)
+{
+ BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
+ 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;
+ }
+
+ memset(block_addr_cache, 0, sizeof(block_addr_cache));
+
+ /* Get block info */
+ if (!(wasm_loader_find_block_addr(
+ NULL, (BlockAddr *)block_addr_cache, *p_frame_ip, frame_ip_end,
+ (uint8)label_type, &else_addr, &end_addr))) {
+ aot_set_last_error("find block end addr failed.");
+ return false;
+ }
+
+ /* Allocate memory */
+ if (!(block = wasm_runtime_malloc(sizeof(AOTBlock)))) {
+ aot_set_last_error("allocate memory failed.");
+ return false;
+ }
+ memset(block, 0, sizeof(AOTBlock));
+ if (param_count
+ && !(block->param_types = wasm_runtime_malloc(param_count))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ if (result_count) {
+ if (!(block->result_types = wasm_runtime_malloc(result_count))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ }
+
+ /* Init aot block data */
+ block->label_type = label_type;
+ block->param_count = param_count;
+ if (param_count) {
+ bh_memcpy_s(block->param_types, param_count, param_types, param_count);
+ }
+ block->result_count = result_count;
+ if (result_count) {
+ bh_memcpy_s(block->result_types, result_count, result_types,
+ result_count);
+ }
+ block->wasm_code_else = else_addr;
+ block->wasm_code_end = end_addr;
+ block->block_index = func_ctx->block_stack.block_index[label_type];
+ func_ctx->block_stack.block_index[label_type]++;
+
+ if (label_type == LABEL_TYPE_BLOCK || label_type == LABEL_TYPE_LOOP) {
+ /* Create block */
+ format_block_name(name, sizeof(name), block->block_index, label_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);
+ if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
+ goto fail;
+ /* Start to translate the block */
+ SET_BUILDER_POS(block->llvm_entry_block);
+ if (label_type == LABEL_TYPE_LOOP)
+ aot_checked_addr_list_destroy(func_ctx);
+ }
+ else if (label_type == LABEL_TYPE_IF) {
+ POP_COND(value);
+
+ if (LLVMIsUndef(value)
+#if LLVM_VERSION_NUMBER >= 12
+ || LLVMIsPoison(value)
+#endif
+ ) {
+ if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
+ false, NULL, NULL))) {
+ goto fail;
+ }
+ aot_block_destroy(block);
+ return aot_handle_next_reachable_block(comp_ctx, func_ctx,
+ p_frame_ip);
+ }
+
+ if (!LLVMIsConstant(value)) {
+ /* Compare value is not constant, create condition br IR */
+ /* Create entry block */
+ format_block_name(name, sizeof(name), block->block_index,
+ label_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,
+ label_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,
+ label_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;
+ }
+ if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx,
+ block))
+ goto fail;
+ /* Start to translate if branch of BLOCK if */
+ SET_BUILDER_POS(block->llvm_entry_block);
+ }
+ else {
+ if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
+ /* Compare value is not 0, condition 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,
+ label_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);
+ if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx,
+ block))
+ goto fail;
+ /* Start to translate the if branch */
+ SET_BUILDER_POS(block->llvm_entry_block);
+ }
+ else {
+ /* Compare value is not 0, condition 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,
+ label_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);
+ if (!push_aot_block_to_stack_and_pass_params(
+ comp_ctx, func_ctx, block))
+ goto fail;
+ /* Start to translate the else branch */
+ SET_BUILDER_POS(block->llvm_else_block);
+ *p_frame_ip = else_addr + 1;
+ }
+ else {
+ /* skip the block */
+ aot_block_destroy(block);
+ *p_frame_ip = end_addr + 1;
+ }
+ }
+ }
+ }
+ else {
+ aot_set_last_error("Invalid block type.");
+ goto fail;
+ }
+
+ return true;
+fail:
+ aot_block_destroy(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];
+ uint32 i, result_index;
+
+ /* Check block */
+ if (!block) {
+ aot_set_last_error("WASM block stack underflow.");
+ return false;
+ }
+ if (block->label_type != LABEL_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->label_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 */
+ CREATE_RESULT_VALUE_PHIS(block);
+ for (i = 0; i < block->result_count; i++) {
+ result_index = block->result_count - 1 - i;
+ POP(value, block->result_types[result_index]);
+ ADD_TO_RESULT_PHIS(block, value, result_index);
+ }
+
+ /* Jump to end block */
+ BUILD_BR(block->llvm_end_block);
+
+ if (!block->skip_wasm_code_else && block->llvm_else_block) {
+ /* Clear value stack, recover param values
+ * and start to translate else branch.
+ */
+ aot_value_stack_destroy(&block->value_stack);
+ for (i = 0; i < block->param_count; i++)
+ PUSH(block->else_param_phis[i], block->param_types[i]);
+ SET_BUILDER_POS(block->llvm_else_block);
+ aot_checked_addr_list_destroy(func_ctx);
+ 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];
+ uint32 i, result_index;
+
+ /* 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->label_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 result values */
+ CREATE_RESULT_VALUE_PHIS(block);
+ for (i = 0; i < block->result_count; i++) {
+ value = NULL;
+ result_index = block->result_count - 1 - i;
+ POP(value, block->result_types[result_index]);
+ bh_assert(value);
+ ADD_TO_RESULT_PHIS(block, value, result_index);
+ }
+
+ /* 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;
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
+ LLVMBasicBlockRef terminate_block, non_terminate_block;
+ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+ bool is_shared_memory =
+ comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false;
+
+ /* Only need to check the suspend flags when memory is shared since
+ shared memory must be enabled for multi-threading */
+ if (!is_shared_memory) {
+ return true;
+ }
+
+ /* Offset of suspend_flags */
+ offset = I32_FIVE;
+
+ if (!(terminate_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
+ "terminate_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(terminate_addr =
+ LLVMBuildBitCast(comp_ctx->builder, terminate_addr,
+ INT32_PTR_TYPE, "terminate_addr_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+
+ if (!(terminate_flags =
+ LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, terminate_addr,
+ "terminate_flags"))) {
+ aot_set_last_error("llvm build LOAD failed");
+ return false;
+ }
+ /* Set terminate_flags memory accecc to volatile, so that the value
+ will always be loaded from memory rather than register */
+ LLVMSetVolatile(terminate_flags, true);
+
+ if (!(flag = LLVMBuildAnd(comp_ctx->builder, terminate_flags, I32_ONE,
+ "termination_flag"))) {
+ aot_set_last_error("llvm build AND failed");
+ return false;
+ }
+
+ CREATE_BLOCK(non_terminate_block, "non_terminate");
+ MOVE_BLOCK_AFTER_CURR(non_terminate_block);
+
+ CREATE_BLOCK(terminate_block, "terminate");
+ MOVE_BLOCK_AFTER_CURR(terminate_block);
+
+ BUILD_ICMP(LLVMIntEQ, flag, I32_ZERO, res, "flag_terminate");
+ BUILD_COND_BR(res, non_terminate_block, terminate_block);
+
+ /* Move builder to terminate block */
+ SET_BUILDER_POS(terminate_block);
+ if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
+ goto fail;
+ }
+
+ /* Move builder to non terminate block */
+ SET_BUILDER_POS(non_terminate_block);
+ return true;
+
+fail:
+ return false;
+}
+#endif /* End of WASM_ENABLE_THREAD_MGR */
+
+bool
+aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 br_depth, uint8 **p_frame_ip)
+{
+ AOTBlock *block_dst;
+ LLVMValueRef value_ret, value_param;
+ LLVMBasicBlockRef next_llvm_end_block;
+ char name[32];
+ uint32 i, param_index, result_index;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ return false;
+ }
+#endif
+
+ if (!(block_dst = get_target_block(func_ctx, br_depth))) {
+ return false;
+ }
+
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
+ /* Dest block is Loop block */
+ /* Handle Loop parameters */
+ for (i = 0; i < block_dst->param_count; i++) {
+ param_index = block_dst->param_count - 1 - i;
+ POP(value_param, block_dst->param_types[param_index]);
+ ADD_TO_PARAM_PHIS(block_dst, value_param, param_index);
+ }
+ 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->label_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 result values */
+ CREATE_RESULT_VALUE_PHIS(block_dst);
+ for (i = 0; i < block_dst->result_count; i++) {
+ result_index = block_dst->result_count - 1 - i;
+ POP(value_ret, block_dst->result_types[result_index]);
+ ADD_TO_RESULT_PHIS(block_dst, value_ret, result_index);
+ }
+ /* 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, *values = NULL;
+ LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
+ char name[32];
+ uint32 i, param_index, result_index;
+ uint64 size;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ return false;
+ }
+#endif
+
+ POP_COND(value_cmp);
+
+ if (LLVMIsUndef(value_cmp)
+#if LLVM_VERSION_NUMBER >= 12
+ || LLVMIsPoison(value_cmp)
+#endif
+ ) {
+ if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
+ false, NULL, NULL))) {
+ goto fail;
+ }
+ return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
+ }
+
+ 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->label_type == LABEL_TYPE_LOOP) {
+ /* Dest block is Loop block */
+ /* Handle Loop parameters */
+ if (block_dst->param_count) {
+ size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
+ if (size >= UINT32_MAX
+ || !(values = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ for (i = 0; i < block_dst->param_count; i++) {
+ param_index = block_dst->param_count - 1 - i;
+ POP(value, block_dst->param_types[param_index]);
+ ADD_TO_PARAM_PHIS(block_dst, value, param_index);
+ values[param_index] = value;
+ }
+ for (i = 0; i < block_dst->param_count; i++) {
+ PUSH(values[i], block_dst->param_types[i]);
+ }
+ wasm_runtime_free(values);
+ values = NULL;
+ }
+
+ 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->label_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 condition br IR */
+ block_dst->is_reachable = true;
+
+ /* Handle result values */
+ if (block_dst->result_count) {
+ size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
+ if (size >= UINT32_MAX
+ || !(values = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ CREATE_RESULT_VALUE_PHIS(block_dst);
+ for (i = 0; i < block_dst->result_count; i++) {
+ result_index = block_dst->result_count - 1 - i;
+ POP(value, block_dst->result_types[result_index]);
+ values[result_index] = value;
+ ADD_TO_RESULT_PHIS(block_dst, value, result_index);
+ }
+ for (i = 0; i < block_dst->result_count; i++) {
+ PUSH(values[i], block_dst->result_types[i]);
+ }
+ wasm_runtime_free(values);
+ values = NULL;
+ }
+
+ /* 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, condition 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, condition is false, skip br_if */
+ return true;
+ }
+ }
+ return true;
+fail:
+ if (values)
+ wasm_runtime_free(values);
+ 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, j;
+ LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL;
+ LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
+ LLVMBasicBlockRef next_llvm_end_block;
+ AOTBlock *target_block;
+ uint32 br_depth, depth_idx;
+ uint32 param_index, result_index;
+ uint64 size;
+ char name[32];
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ return false;
+ }
+#endif
+
+ POP_I32(value_cmp);
+
+ if (LLVMIsUndef(value_cmp)
+#if LLVM_VERSION_NUMBER >= 12
+ || LLVMIsPoison(value_cmp)
+#endif
+ ) {
+ if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
+ false, NULL, NULL))) {
+ goto fail;
+ }
+ return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
+ }
+
+ 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->label_type != LABEL_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->label_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 result values */
+ if (target_block->result_count) {
+ size = sizeof(LLVMValueRef)
+ * (uint64)target_block->result_count;
+ if (size >= UINT32_MAX
+ || !(values = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ CREATE_RESULT_VALUE_PHIS(target_block);
+ for (j = 0; j < target_block->result_count; j++) {
+ result_index = target_block->result_count - 1 - j;
+ POP(value, target_block->result_types[result_index]);
+ values[result_index] = value;
+ ADD_TO_RESULT_PHIS(target_block, value, result_index);
+ }
+ for (j = 0; j < target_block->result_count; j++) {
+ PUSH(values[j], target_block->result_types[j]);
+ }
+ wasm_runtime_free(values);
+ }
+ target_block->is_reachable = true;
+ if (i == br_count)
+ default_llvm_block = target_block->llvm_end_block;
+ }
+ else {
+ /* Handle Loop parameters */
+ if (target_block->param_count) {
+ size = sizeof(LLVMValueRef)
+ * (uint64)target_block->param_count;
+ if (size >= UINT32_MAX
+ || !(values = wasm_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ for (j = 0; j < target_block->param_count; j++) {
+ param_index = target_block->param_count - 1 - j;
+ POP(value, target_block->param_types[param_index]);
+ values[param_index] = value;
+ ADD_TO_PARAM_PHIS(target_block, value, param_index);
+ }
+ for (j = 0; j < target_block->param_count; j++) {
+ PUSH(values[j], target_block->param_types[j]);
+ }
+ wasm_runtime_free(values);
+ }
+ 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->label_type != LABEL_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:
+ if (values)
+ wasm_runtime_free(values);
+ 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;
+ LLVMValueRef ret;
+ AOTFuncType *func_type;
+ uint32 i, param_index, result_index;
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMMetadataRef return_location;
+#endif
+
+ bh_assert(block_func);
+ func_type = func_ctx->aot_func->func_type;
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ return_location = dwarf_gen_location(
+ comp_ctx, func_ctx,
+ (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
+#endif
+ if (block_func->result_count) {
+ /* Store extra result values to function parameters */
+ for (i = 0; i < block_func->result_count - 1; i++) {
+ result_index = block_func->result_count - 1 - i;
+ POP(value, block_func->result_types[result_index]);
+ param_index = func_type->param_count + result_index;
+ if (!LLVMBuildStore(comp_ctx->builder, value,
+ LLVMGetParam(func_ctx->func, param_index))) {
+ aot_set_last_error("llvm build store failed.");
+ goto fail;
+ }
+ }
+ /* Return the first result value */
+ POP(value, block_func->result_types[0]);
+ if (!(ret = LLVMBuildRet(comp_ctx->builder, value))) {
+ aot_set_last_error("llvm build return failed.");
+ goto fail;
+ }
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMInstructionSetDebugLoc(ret, return_location);
+#endif
+ }
+ else {
+ if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
+ aot_set_last_error("llvm build return void failed.");
+ goto fail;
+ }
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMInstructionSetDebugLoc(ret, return_location);
+#endif
+ }
+
+ 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.h
new file mode 100644
index 000000000..a203876c1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_control.h
@@ -0,0 +1,62 @@
+/*
+ * 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 label_type,
+ uint32 param_count, uint8 *param_types,
+ uint32 result_count, uint8 *result_types);
+
+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);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_EMIT_CONTROL_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.c
new file mode 100644
index 000000000..c3dfa6bf1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.c
@@ -0,0 +1,939 @@
+/*
+ * 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_intrinsic.h"
+#include "../aot/aot_runtime.h"
+
+static LLVMValueRef
+call_fcmp_intrinsic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ enum AOTFloatCond cond, LLVMRealPredicate op,
+ LLVMValueRef lhs, LLVMValueRef rhs, LLVMTypeRef src_type,
+ const char *name)
+{
+ LLVMValueRef res = NULL;
+ if (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(
+ comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) {
+ LLVMTypeRef param_types[3];
+ LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true);
+ param_types[0] = I32_TYPE;
+ param_types[1] = src_type;
+ param_types[2] = src_type;
+ res = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
+ I32_TYPE, param_types, 3, opcond, lhs, rhs);
+ if (!res) {
+ goto fail;
+ }
+ res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast");
+ }
+ else {
+ res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, name);
+ }
+fail:
+ return res;
+}
+
+static bool
+trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef operand, LLVMTypeRef src_type,
+ 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;
+
+ res = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO,
+ operand, operand, src_type, "fcmp_is_nan");
+
+ if (!res) {
+ 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;
+
+ is_less =
+ call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE, LLVMRealOLE, operand,
+ min_value, src_type, "fcmp_min_value");
+
+ if (!is_less) {
+ aot_set_last_error("llvm build fcmp failed.");
+ goto fail;
+ }
+
+ is_greater =
+ call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE, LLVMRealOGE, operand,
+ max_value, src_type, "fcmp_min_value");
+
+ if (!is_greater) {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, name)) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = src_type;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, name, dest_type,
+ param_types, 1, operand);
+ }
+ else {
+ 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;
+}
+
+#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)
+
+static bool
+trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef operand, LLVMTypeRef src_type,
+ LLVMTypeRef dest_type, LLVMValueRef min_value,
+ LLVMValueRef max_value, char *name, bool sign)
+{
+ LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ;
+ LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block;
+ LLVMValueRef is_less, is_greater, res, phi;
+ LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
+ LLVMValueRef vmin, vmax;
+
+ if (!(res =
+ call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO,
+ operand, operand, src_type, "fcmp_is_nan"))) {
+ aot_set_last_error("llvm build fcmp failed.");
+ goto fail;
+ }
+
+ ADD_BASIC_BLOCK(check_nan_succ, "check_nan_succ");
+ ADD_BASIC_BLOCK(is_nan_block, "is_nan_block");
+ ADD_BASIC_BLOCK(check_less_succ, "check_less_succ");
+ ADD_BASIC_BLOCK(is_less_block, "is_less_block");
+ ADD_BASIC_BLOCK(check_greater_succ, "check_greater_succ");
+ ADD_BASIC_BLOCK(is_greater_block, "is_greater_block");
+ ADD_BASIC_BLOCK(res_block, "res_block");
+
+ if (!LLVMBuildCondBr(comp_ctx->builder, res, is_nan_block,
+ check_nan_succ)) {
+ aot_set_last_error("llvm build cond br failed.");
+ goto fail;
+ }
+
+ /* Start to translate is_nan block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, is_nan_block);
+ if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+ aot_set_last_error("llvm build br failed.");
+ goto fail;
+ }
+
+ /* Start to translate check_nan_succ block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
+ if (!(is_less = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE,
+ LLVMRealOLE, operand, min_value,
+ src_type, "fcmp_min_value"))) {
+ aot_set_last_error("llvm build fcmp failed.");
+ goto fail;
+ }
+ if (!LLVMBuildCondBr(comp_ctx->builder, is_less, is_less_block,
+ check_less_succ)) {
+ aot_set_last_error("llvm build cond br failed.");
+ goto fail;
+ }
+
+ /* Start to translate is_less block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, is_less_block);
+ if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+ aot_set_last_error("llvm build br failed.");
+ goto fail;
+ }
+
+ /* Start to translate check_less_succ block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
+ if (!(is_greater = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE,
+ LLVMRealOGE, operand, max_value,
+ src_type, "fcmp_max_value"))) {
+ aot_set_last_error("llvm build fcmp failed.");
+ goto fail;
+ }
+ if (!LLVMBuildCondBr(comp_ctx->builder, is_greater, is_greater_block,
+ check_greater_succ)) {
+ aot_set_last_error("llvm build cond br failed.");
+ goto fail;
+ }
+
+ /* Start to translate is_greater block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, is_greater_block);
+ if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+ aot_set_last_error("llvm build br failed.");
+ goto fail;
+ }
+
+ /* Start to translate check_greater_succ block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ);
+
+ if (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, name)) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = src_type;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, name, dest_type,
+ param_types, 1, operand);
+ }
+ else {
+ char intrinsic[128];
+
+ /* Integer width is always 32 or 64 here. */
+
+ snprintf(intrinsic, sizeof(intrinsic), "i%d_trunc_f%d_%c",
+ LLVMGetIntTypeWidth(dest_type),
+ LLVMGetTypeKind(src_type) == LLVMFloatTypeKind ? 32 : 64,
+ sign ? 's' : 'u');
+
+ if (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, intrinsic)) {
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+ dest_type, &src_type, 1, operand);
+ }
+ else {
+ 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 (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+ aot_set_last_error("llvm build br failed.");
+ goto fail;
+ }
+
+ /* Start to translate res_block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block);
+ /* Create result phi */
+ if (!(phi = LLVMBuildPhi(comp_ctx->builder, dest_type,
+ "trunc_sat_result_phi"))) {
+ aot_set_last_error("llvm build phi failed.");
+ return false;
+ }
+
+ /* Add phi incoming values */
+ if (dest_type == I32_TYPE) {
+ if (sign) {
+ vmin = I32_CONST(INT32_MIN);
+ vmax = I32_CONST(INT32_MAX);
+ }
+ else {
+ vmin = I32_CONST(0);
+ vmax = I32_CONST(UINT32_MAX);
+ }
+ }
+ else if (dest_type == I64_TYPE) {
+ if (sign) {
+ vmin = I64_CONST(INT64_MIN);
+ vmax = I64_CONST(INT64_MAX);
+ }
+ else {
+ vmin = I64_CONST(0);
+ vmax = I64_CONST(UINT64_MAX);
+ }
+ }
+ LLVMAddIncoming(phi, &zero, &is_nan_block, 1);
+ LLVMAddIncoming(phi, &vmin, &is_less_block, 1);
+ LLVMAddIncoming(phi, &vmax, &is_greater_block, 1);
+ LLVMAddIncoming(phi, &res, &check_greater_succ, 1);
+
+ if (dest_type == I32_TYPE)
+ PUSH_I32(phi);
+ else if (dest_type == I64_TYPE)
+ PUSH_I64(phi);
+ 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, bool saturating)
+{
+ LLVMValueRef value;
+ LLVMValueRef min_value, max_value;
+
+ POP_F32(value);
+
+ if (!comp_ctx->is_indirect_mode) {
+ 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);
+ }
+ }
+ else {
+ WASMValue wasm_value;
+ if (sign) {
+ wasm_value.f32 = -2147483904.0f;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ wasm_value.f32 = 2147483648.0f;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ }
+ else {
+ wasm_value.f32 = -1.0f;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ wasm_value.f32 = 4294967296.0f;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ }
+ }
+ CHECK_LLVM_CONST(min_value);
+ CHECK_LLVM_CONST(max_value);
+
+ if (!saturating)
+ return trunc_float_to_int(
+ comp_ctx, func_ctx, value, F32_TYPE, I32_TYPE, min_value, max_value,
+ sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
+ else
+ return trunc_sat_float_to_int(
+ comp_ctx, func_ctx, value, F32_TYPE, I32_TYPE, min_value, max_value,
+ sign ? "i32_trunc_sat_f32_s" : "i32_trunc_sat_f32_u", sign);
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool sign, bool saturating)
+{
+ LLVMValueRef value;
+ LLVMValueRef min_value, max_value;
+
+ POP_F64(value);
+
+ if (!comp_ctx->is_indirect_mode) {
+ 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);
+ }
+ }
+ else {
+ WASMValue wasm_value;
+ if (sign) {
+ wasm_value.f64 = -2147483649.0;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ wasm_value.f64 = 2147483648.0;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ }
+ else {
+ wasm_value.f64 = -1.0;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ wasm_value.f64 = 4294967296.0;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ }
+ }
+ CHECK_LLVM_CONST(min_value);
+ CHECK_LLVM_CONST(max_value);
+
+ if (!saturating)
+ return trunc_float_to_int(
+ comp_ctx, func_ctx, value, F64_TYPE, I32_TYPE, min_value, max_value,
+ sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
+ else
+ return trunc_sat_float_to_int(
+ comp_ctx, func_ctx, value, F64_TYPE, I32_TYPE, min_value, max_value,
+ sign ? "i32_trunc_sat_f64_s" : "i32_trunc_sat_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_extend_i64(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, int8 bitwidth)
+{
+ LLVMValueRef value, res, cast_value = NULL;
+
+ POP_I64(value);
+
+ if (bitwidth == 8) {
+ cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT8_TYPE,
+ true, "i8_intcast_i64");
+ }
+ else if (bitwidth == 16) {
+ cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT16_TYPE,
+ true, "i16_intcast_i64");
+ }
+ else if (bitwidth == 32) {
+ cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, I32_TYPE, true,
+ "i32_intcast_i64");
+ }
+
+ if (!cast_value) {
+ aot_set_last_error("llvm build conversion failed.");
+ return false;
+ }
+
+ res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE,
+ "i64_extend_i64_s");
+
+ if (!res) {
+ aot_set_last_error("llvm build conversion failed.");
+ return false;
+ }
+
+ PUSH_I64(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, int8 bitwidth)
+{
+ LLVMValueRef value, res, cast_value = NULL;
+
+ POP_I32(value);
+
+ if (bitwidth == 8) {
+ cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT8_TYPE,
+ true, "i8_intcast_i32");
+ }
+ else if (bitwidth == 16) {
+ cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT16_TYPE,
+ true, "i16_intcast_i32");
+ }
+
+ if (!cast_value) {
+ aot_set_last_error("llvm build conversion failed.");
+ return false;
+ }
+
+ res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE,
+ "i32_extend_i32_s");
+
+ if (!res) {
+ aot_set_last_error("llvm build conversion failed.");
+ return false;
+ }
+
+ PUSH_I32(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool sign, bool saturating)
+{
+ LLVMValueRef value;
+ LLVMValueRef min_value, max_value;
+
+ POP_F32(value);
+
+ if (!comp_ctx->is_indirect_mode) {
+ 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);
+ }
+ }
+ else {
+ WASMValue wasm_value;
+ if (sign) {
+ wasm_value.f32 = -9223373136366403584.0f;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ wasm_value.f32 = 9223372036854775808.0f;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ }
+ else {
+ wasm_value.f32 = -1.0f;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ wasm_value.f32 = 18446744073709551616.0f;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F32);
+ }
+ }
+ CHECK_LLVM_CONST(min_value);
+ CHECK_LLVM_CONST(max_value);
+
+ if (!saturating)
+ return trunc_float_to_int(
+ comp_ctx, func_ctx, value, F32_TYPE, I64_TYPE, min_value, max_value,
+ sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
+ else
+ return trunc_sat_float_to_int(
+ comp_ctx, func_ctx, value, F32_TYPE, I64_TYPE, min_value, max_value,
+ sign ? "i64_trunc_sat_f32_s" : "i64_trunc_sat_f32_u", sign);
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool sign, bool saturating)
+{
+ LLVMValueRef value;
+ LLVMValueRef min_value, max_value;
+
+ POP_F64(value);
+
+ if (!comp_ctx->is_indirect_mode) {
+ 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);
+ }
+ }
+ else {
+ WASMValue wasm_value;
+ if (sign) {
+ wasm_value.f64 = -9223372036854777856.0;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ wasm_value.f64 = 9223372036854775808.0;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ }
+ else {
+ wasm_value.f64 = -1.0;
+ min_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ wasm_value.f64 = 18446744073709551616.0;
+ max_value = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_F64);
+ }
+ }
+ CHECK_LLVM_CONST(min_value);
+ CHECK_LLVM_CONST(max_value);
+
+ if (!saturating)
+ return trunc_float_to_int(
+ comp_ctx, func_ctx, value, F64_TYPE, I64_TYPE, min_value, max_value,
+ sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
+ else
+ return trunc_sat_float_to_int(
+ comp_ctx, func_ctx, value, F64_TYPE, I64_TYPE, min_value, max_value,
+ sign ? "i64_trunc_sat_f64_s" : "i64_trunc_sat_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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(
+ comp_ctx, sign ? "f32_convert_i32_s" : "f32_convert_i32_u")) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = I32_TYPE;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
+ sign ? "f32_convert_i32_s"
+ : "f32_convert_i32_u",
+ F32_TYPE, param_types, 1, value);
+ }
+ else {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(
+ comp_ctx, sign ? "f32_convert_i64_s" : "f32_convert_i64_u")) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = I64_TYPE;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
+ sign ? "f32_convert_i64_s"
+ : "f32_convert_i64_u",
+ F32_TYPE, param_types, 1, value);
+ }
+ else {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, "f32_demote_f64")) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = F64_TYPE;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64",
+ F32_TYPE, param_types, 1, value);
+ }
+ else {
+ res = LLVMBuildFPTrunc(comp_ctx->builder, value, F32_TYPE,
+ "f32_demote_f64");
+ }
+
+ if (!res) {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(
+ comp_ctx, sign ? "f64_convert_i32_s" : "f64_convert_i32_u")) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = I32_TYPE;
+
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
+ sign ? "f64_convert_i32_s"
+ : "f64_convert_i32_u",
+ F64_TYPE, param_types, 1, value);
+ }
+ else {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(
+ comp_ctx, sign ? "f64_convert_i64_s" : "f64_convert_i64_u")) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = I64_TYPE;
+
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
+ sign ? "f64_convert_i64_s"
+ : "f64_convert_i64_u",
+ F64_TYPE, param_types, 1, value);
+ }
+ else {
+ 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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, "f64_promote_f32")) {
+ LLVMTypeRef param_types[1];
+ param_types[0] = F32_TYPE;
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f64_promote_f32",
+ F64_TYPE, param_types, 1, value);
+ }
+ else {
+ res = LLVMBuildFPExt(comp_ctx->builder, value, F64_TYPE,
+ "f64_promote_f32");
+ }
+
+ if (!res) {
+ 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.h
new file mode 100644
index 000000000..a0e2fcb2e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_conversion.h
@@ -0,0 +1,90 @@
+/*
+ * 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 saturating);
+
+bool
+aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool sign, bool saturating);
+
+bool
+aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool sign);
+
+bool
+aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, int8 bitwidth);
+
+bool
+aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, int8 bitwidth);
+
+bool
+aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool sign, bool saturating);
+
+bool
+aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool sign, bool saturating);
+
+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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.c
new file mode 100644
index 000000000..d40ccc6a4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_emit_exception.h"
+#include "../interpreter/wasm_runtime.h"
+#include "../aot/aot_runtime.h"
+
+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 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, I32_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)jit_set_exception_with_id))
+ || !(func = LLVMConstIntToPtr(func_const, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else if (comp_ctx->is_indirect_mode) {
+ int32 func_index;
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+
+ func_index = aot_get_native_symbol_index(
+ comp_ctx, "aot_set_exception_with_id");
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func =
+ aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+ else {
+ /* Create LLVM function with external function pointer */
+ if (!(func = LLVMGetNamedFunction(func_ctx->module,
+ "aot_set_exception_with_id"))
+ && !(func = LLVMAddFunction(func_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 (!LLVMBuildCall2(comp_ctx->builder, func_type, 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_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
+ return false;
+ }
+
+ /* Resume the builder position */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
+ }
+
+ /* Add phi incoming value to got_exception block */
+ LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &block_curr, 1);
+
+ if (!is_cond_br) {
+ /* not condition br, create br IR */
+ if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
+ aot_set_last_error("llvm build br failed.");
+ return false;
+ }
+ }
+ else {
+ /* Create condition br */
+ if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if,
+ func_ctx->got_exception_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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.h
new file mode 100644
index 000000000..91c8bd3cf
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.h
@@ -0,0 +1,24 @@
+/*
+ * 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.c
new file mode 100644
index 000000000..9ba8baa24
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.c
@@ -0,0 +1,1729 @@
+/*
+ * 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_emit_table.h"
+#include "../aot/aot_runtime.h"
+
+#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)
+
+static bool
+create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+
+ /* 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 (!comp_ctx->enable_bound_check) {
+ if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ALREADY_THROWN,
+ false, NULL, NULL)) {
+ return false;
+ }
+ }
+ else if (!aot_build_zero_function_ret(comp_ctx, func_ctx,
+ aot_func_type)) {
+ return false;
+ }
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
+ return true;
+}
+
+/* Check whether there was exception thrown, if yes, return directly */
+static bool
+check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMBasicBlockRef block_curr, check_exce_succ;
+ LLVMValueRef value, cmp;
+
+ /* Create function return block if it isn't created */
+ if (!create_func_return_block(comp_ctx, func_ctx))
+ return false;
+
+ /* Load the first byte of aot_module_inst->cur_exception, and check
+ whether it is '\0'. If yes, no exception was thrown. */
+ if (!(value = LLVMBuildLoad2(comp_ctx->builder, INT8_TYPE,
+ 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);
+
+ 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;
+}
+
+/* Check whether there was exception thrown, if yes, return directly */
+static bool
+check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef res)
+{
+ LLVMBasicBlockRef block_curr, check_call_succ;
+ LLVMValueRef cmp;
+
+ /* Create function return block if it isn't created */
+ if (!create_func_return_block(comp_ctx, func_ctx))
+ return false;
+
+ if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, res, I8_ZERO,
+ "cmp"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ return false;
+ }
+
+ /* Add check exection success block */
+ if (!(check_call_succ = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "check_call_succ"))) {
+ aot_set_last_error("llvm add basic block failed.");
+ return false;
+ }
+
+ block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMMoveBasicBlockAfter(check_call_succ, block_curr);
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
+ /* Create condition br */
+ if (!LLVMBuildCondBr(comp_ctx->builder, cmp, check_call_succ,
+ func_ctx->func_return_block)) {
+ aot_set_last_error("llvm build cond br failed.");
+ return false;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ);
+ return true;
+}
+
+static bool
+call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef func_idx, AOTFuncType *aot_func_type,
+ LLVMTypeRef *param_types,
+ LLVMValueRef *param_values, uint32 param_count,
+ uint32 param_cell_num, LLVMTypeRef ret_type,
+ uint8 wasm_ret_type, LLVMValueRef *p_value_ret,
+ LLVMValueRef *p_res)
+{
+ LLVMTypeRef func_type, func_ptr_type, func_param_types[4];
+ LLVMTypeRef ret_ptr_type, elem_ptr_type;
+ LLVMValueRef func, elem_idx, elem_ptr;
+ LLVMValueRef func_param_values[4], value_ret = NULL, res;
+ char buf[32], *func_name = "aot_invoke_native";
+ uint32 i, cell_num = 0;
+
+ /* prepare function type of aot_invoke_native */
+ func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
+ func_param_types[1] = I32_TYPE; /* func_idx */
+ func_param_types[2] = I32_TYPE; /* argc */
+ func_param_types[3] = INT32_PTR_TYPE; /* argv */
+ if (!(func_type =
+ LLVMFunctionType(INT8_TYPE, func_param_types, 4, false))) {
+ aot_set_last_error("llvm add function type failed.");
+ return false;
+ }
+
+ /* prepare function pointer */
+ if (comp_ctx->is_jit_mode) {
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+
+ /* JIT mode, call the function directly */
+ if (!(func = I64_CONST((uint64)(uintptr_t)llvm_jit_invoke_native))
+ || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else if (comp_ctx->is_indirect_mode) {
+ int32 func_index;
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+ func_index = aot_get_native_symbol_index(comp_ctx, func_name);
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+ else {
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
+ && !(func =
+ LLVMAddFunction(func_ctx->module, func_name, func_type))) {
+ aot_set_last_error("add LLVM function failed.");
+ return false;
+ }
+ }
+
+ if (param_cell_num > 64) {
+ aot_set_last_error("prepare native arguments failed: "
+ "maximum 64 parameter cell number supported.");
+ return false;
+ }
+
+ /* prepare frame_lp */
+ for (i = 0; i < param_count; i++) {
+ if (!(elem_idx = I32_CONST(cell_num))
+ || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
+ aot_set_last_error("llvm add const or pointer type failed.");
+ return false;
+ }
+
+ snprintf(buf, sizeof(buf), "%s%d", "elem", i);
+ if (!(elem_ptr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE,
+ func_ctx->argv_buf, &elem_idx, 1, buf))
+ || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
+ elem_ptr_type, buf))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ return false;
+ }
+
+ if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i],
+ elem_ptr))) {
+ aot_set_last_error("llvm build store failed.");
+ return false;
+ }
+ LLVMSetAlignment(res, 1);
+
+ cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
+ }
+
+ func_param_values[0] = func_ctx->exec_env;
+ func_param_values[1] = func_idx;
+ func_param_values[2] = I32_CONST(param_cell_num);
+ func_param_values[3] = func_ctx->argv_buf;
+
+ if (!func_param_values[2]) {
+ aot_set_last_error("llvm create const failed.");
+ return false;
+ }
+
+ /* call aot_invoke_native() function */
+ if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ func_param_values, 4, "res"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ /* get function return value */
+ if (wasm_ret_type != VALUE_TYPE_VOID) {
+ if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
+ aot_set_last_error("llvm add pointer type failed.");
+ return false;
+ }
+
+ if (!(value_ret =
+ LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
+ ret_ptr_type, "argv_ret"))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ return false;
+ }
+ if (!(*p_value_ret = LLVMBuildLoad2(comp_ctx->builder, ret_type,
+ value_ret, "value_ret"))) {
+ aot_set_last_error("llvm build load failed.");
+ return false;
+ }
+ }
+
+ *p_res = res;
+ return true;
+}
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+static bool
+call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef func_idx)
+{
+ LLVMValueRef param_values[2], ret_value, value, func;
+ LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef frame_alloc_fail, frame_alloc_success;
+ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+
+ param_types[0] = comp_ctx->exec_env_type;
+ param_types[1] = I32_TYPE;
+ ret_type = INT8_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_alloc_frame, 2);
+ else
+ GET_AOT_FUNCTION(aot_alloc_frame, 2);
+
+ param_values[0] = func_ctx->exec_env;
+ param_values[1] = func_idx;
+
+ if (!(ret_value =
+ LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
+ 2, "call_aot_alloc_frame"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ if (!(ret_value = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, ret_value,
+ I8_ZERO, "frame_alloc_ret"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ return false;
+ }
+
+ ADD_BASIC_BLOCK(frame_alloc_fail, "frame_alloc_fail");
+ ADD_BASIC_BLOCK(frame_alloc_success, "frame_alloc_success");
+
+ LLVMMoveBasicBlockAfter(frame_alloc_fail, block_curr);
+ LLVMMoveBasicBlockAfter(frame_alloc_success, block_curr);
+
+ if (!LLVMBuildCondBr(comp_ctx->builder, ret_value, frame_alloc_success,
+ frame_alloc_fail)) {
+ aot_set_last_error("llvm build cond br failed.");
+ return false;
+ }
+
+ /* If frame alloc failed, return this function
+ so the runtime can catch the exception */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, frame_alloc_fail);
+ if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
+ return false;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, frame_alloc_success);
+
+ return true;
+
+fail:
+ return false;
+}
+
+static bool
+call_aot_free_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef param_values[1], ret_value, value, func;
+ LLVMTypeRef param_types[1], ret_type, func_type, func_ptr_type;
+
+ param_types[0] = comp_ctx->exec_env_type;
+ ret_type = INT8_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_free_frame, 1);
+ else
+ GET_AOT_FUNCTION(aot_free_frame, 1);
+
+ param_values[0] = func_ctx->exec_env;
+
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 1, "call_aot_free_frame"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
+ || (WASM_ENABLE_PERF_PROFILING != 0) */
+
+static bool
+record_stack_usage(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 callee_cell_num)
+{
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef block_update;
+ LLVMBasicBlockRef block_after_update;
+ LLVMValueRef callee_local_size, new_sp, cmp;
+ LLVMValueRef native_stack_top_min;
+ LLVMTypeRef ptrdiff_type;
+ if (comp_ctx->pointer_size == sizeof(uint64_t)) {
+ ptrdiff_type = I64_TYPE;
+ }
+ else {
+ ptrdiff_type = I32_TYPE;
+ }
+
+ /*
+ * new_sp = last_alloca - callee_local_size;
+ * if (*native_stack_top_min_addr > new_sp) {
+ * *native_stack_top_min_addr = new_sp;
+ * }
+ */
+
+ if (!(callee_local_size = LLVMConstInt(
+ ptrdiff_type, -(int64_t)callee_cell_num * 4, true))) {
+ aot_set_last_error("llvm build const failed.");
+ return false;
+ }
+ if (!(new_sp = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->last_alloca,
+ &callee_local_size, 1, "new_sp"))) {
+ aot_set_last_error("llvm build gep failed");
+ return false;
+ }
+ if (!(native_stack_top_min = LLVMBuildLoad2(
+ comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->native_stack_top_min_addr, "native_stack_top_min"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, new_sp,
+ native_stack_top_min, "cmp"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ return false;
+ }
+
+ if (!(block_update = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "block_update"))) {
+ aot_set_last_error("llvm add basic block failed.");
+ return false;
+ }
+ if (!(block_after_update = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "block_after_update"))) {
+ aot_set_last_error("llvm add basic block failed.");
+ return false;
+ }
+ LLVMMoveBasicBlockAfter(block_update, block_curr);
+ LLVMMoveBasicBlockAfter(block_after_update, block_update);
+
+ if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_update,
+ block_after_update)) {
+ aot_set_last_error("llvm build cond br failed.");
+ return false;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_update);
+ if (!LLVMBuildStore(comp_ctx->builder, new_sp,
+ func_ctx->native_stack_top_min_addr)) {
+ aot_set_last_error("llvm build store failed");
+ return false;
+ }
+ if (!LLVMBuildBr(comp_ctx->builder, block_after_update)) {
+ aot_set_last_error("llvm build br failed.");
+ return false;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_after_update);
+ return true;
+}
+
+static bool
+check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 callee_cell_num)
+{
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef check_stack;
+ LLVMValueRef callee_local_size, stack_bound, cmp;
+
+ if (!(callee_local_size = I32_CONST(callee_cell_num * 4))) {
+ aot_set_last_error("llvm build const failed.");
+ return false;
+ }
+
+ if (!(stack_bound = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, func_ctx->native_stack_bound,
+ &callee_local_size, 1, "stack_bound"))) {
+ aot_set_last_error("llvm build inbound gep failed.");
+ return false;
+ }
+
+ if (!(check_stack = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "check_stack"))) {
+ aot_set_last_error("llvm add basic block failed.");
+ return false;
+ }
+
+ LLVMMoveBasicBlockAfter(check_stack, block_curr);
+
+ if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT,
+ func_ctx->last_alloca, stack_bound, "cmp"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ return false;
+ }
+
+ if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NATIVE_STACK_OVERFLOW,
+ true, cmp, check_stack)) {
+ return false;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_stack);
+ return true;
+}
+
+static bool
+check_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 callee_cell_num)
+{
+ if (comp_ctx->enable_stack_estimation
+ && !record_stack_usage(comp_ctx, func_ctx, callee_cell_num))
+ return false;
+ if (comp_ctx->enable_stack_bound_check
+ && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
+ return false;
+ return true;
+}
+
+/**
+ * Check whether the app address and its buffer are inside the linear memory,
+ * if no, throw exception
+ */
+static bool
+check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool is_str_arg, LLVMValueRef app_addr,
+ LLVMValueRef buf_size,
+ LLVMValueRef *p_native_addr_converted)
+{
+ LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
+ LLVMValueRef func, func_param_values[5], res, native_addr_ptr;
+ char *func_name = "aot_check_app_addr_and_convert";
+
+ /* prepare function type of aot_check_app_addr_and_convert */
+ func_param_types[0] = comp_ctx->aot_inst_type; /* module_inst */
+ func_param_types[1] = INT8_TYPE; /* is_str_arg */
+ func_param_types[2] = I32_TYPE; /* app_offset */
+ func_param_types[3] = I32_TYPE; /* buf_size */
+ func_param_types[4] =
+ comp_ctx->basic_types.int8_pptr_type; /* p_native_addr */
+ if (!(func_type =
+ LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
+ aot_set_last_error("llvm add function type failed.");
+ return false;
+ }
+
+ /* prepare function pointer */
+ if (comp_ctx->is_jit_mode) {
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+
+ /* JIT mode, call the function directly */
+ if (!(func =
+ I64_CONST((uint64)(uintptr_t)jit_check_app_addr_and_convert))
+ || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else if (comp_ctx->is_indirect_mode) {
+ int32 func_index;
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+ func_index = aot_get_native_symbol_index(comp_ctx, func_name);
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+ else {
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
+ && !(func =
+ LLVMAddFunction(func_ctx->module, func_name, func_type))) {
+ aot_set_last_error("add LLVM function failed.");
+ return false;
+ }
+ }
+
+ if (!(native_addr_ptr = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->argv_buf,
+ comp_ctx->basic_types.int8_pptr_type, "p_native_addr"))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ return false;
+ }
+
+ func_param_values[0] = func_ctx->aot_inst;
+ func_param_values[1] = I8_CONST(is_str_arg);
+ func_param_values[2] = app_addr;
+ func_param_values[3] = buf_size;
+ func_param_values[4] = native_addr_ptr;
+
+ if (!func_param_values[1]) {
+ aot_set_last_error("llvm create const failed.");
+ return false;
+ }
+
+ /* call aot_check_app_addr_and_convert() function */
+ if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ func_param_values, 5, "res"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ /* Check whether exception was thrown when executing the function */
+ if (comp_ctx->enable_bound_check
+ && !check_call_return(comp_ctx, func_ctx, res)) {
+ return false;
+ }
+
+ if (!(*p_native_addr_converted =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, native_addr_ptr,
+ "native_addr"))) {
+ aot_set_last_error("llvm build load failed.");
+ return false;
+ }
+
+ return true;
+}
+
+bool
+aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 func_idx, bool tail_call)
+{
+ 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, param_cell_num = 0;
+ uint32 ext_ret_cell_num = 0, cell_num = 0;
+ AOTFuncContext **func_ctxes = comp_ctx->func_ctxes;
+ AOTFuncType *func_type;
+ AOTFunc *aot_func;
+ LLVMTypeRef *param_types = NULL, ret_type;
+ LLVMTypeRef ext_ret_ptr_type;
+ LLVMValueRef *param_values = NULL, value_ret = NULL, func;
+ LLVMValueRef import_func_idx, res;
+ LLVMValueRef ext_ret, ext_ret_ptr, ext_ret_idx;
+ int32 i, j = 0, param_count, result_count, ext_ret_count;
+ uint64 total_size;
+ uint32 callee_cell_num;
+ uint8 wasm_ret_type;
+ uint8 *ext_ret_types = NULL;
+ const char *signature = NULL;
+ bool ret = false;
+ char buf[32];
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ return false;
+ }
+#endif
+
+ /* 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;
+ signature = import_funcs[func_idx].signature;
+ }
+ else {
+ func_type =
+ func_ctxes[func_idx - import_func_count]->aot_func->func_type;
+ }
+
+ /* Get param cell number */
+ param_cell_num = func_type->param_cell_num;
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (comp_ctx->enable_aux_stack_frame) {
+ LLVMValueRef func_idx_const;
+
+ if (!(func_idx_const = I32_CONST(func_idx))) {
+ aot_set_last_error("llvm build const failed.");
+ return false;
+ }
+ if (!call_aot_alloc_frame_func(comp_ctx, func_ctx, func_idx_const))
+ return false;
+ }
+#endif
+
+ /* Allocate memory for parameters.
+ * Parameters layout:
+ * - exec env
+ * - wasm function's parameters
+ * - extra results'(except the first one) addresses
+ */
+ param_count = (int32)func_type->param_count;
+ result_count = (int32)func_type->result_count;
+ ext_ret_count = result_count > 1 ? result_count - 1 : 0;
+ total_size =
+ sizeof(LLVMValueRef) * (uint64)(param_count + 1 + ext_ret_count);
+ if (total_size >= UINT32_MAX
+ || !(param_values = wasm_runtime_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]);
+
+ /* Set parameters for multiple return values, the first return value
+ is returned by function return value, and the other return values
+ are returned by function parameters with pointer types */
+ if (ext_ret_count > 0) {
+ ext_ret_types = func_type->types + param_count + 1;
+ ext_ret_cell_num = wasm_get_cell_num(ext_ret_types, ext_ret_count);
+ if (ext_ret_cell_num > 64) {
+ aot_set_last_error("prepare extra results's return "
+ "address arguments failed: "
+ "maximum 64 parameter cell number supported.");
+ goto fail;
+ }
+
+ for (i = 0; i < ext_ret_count; i++) {
+ if (!(ext_ret_idx = I32_CONST(cell_num))
+ || !(ext_ret_ptr_type =
+ LLVMPointerType(TO_LLVM_TYPE(ext_ret_types[i]), 0))) {
+ aot_set_last_error("llvm add const or pointer type failed.");
+ goto fail;
+ }
+
+ snprintf(buf, sizeof(buf), "ext_ret%d_ptr", i);
+ if (!(ext_ret_ptr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, I32_TYPE, func_ctx->argv_buf,
+ &ext_ret_idx, 1, buf))) {
+ aot_set_last_error("llvm build GEP failed.");
+ goto fail;
+ }
+ snprintf(buf, sizeof(buf), "ext_ret%d_ptr_cast", i);
+ if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ext_ret_ptr,
+ ext_ret_ptr_type, buf))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ goto fail;
+ }
+ param_values[param_count + 1 + i] = ext_ret_ptr;
+ cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
+ }
+ }
+
+ if (func_idx < import_func_count) {
+ if (!(import_func_idx = I32_CONST(func_idx))) {
+ aot_set_last_error("llvm build inbounds gep failed.");
+ goto fail;
+ }
+
+ /* Initialize parameter types of the LLVM function */
+ total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
+ if (total_size >= UINT32_MAX
+ || !(param_types = wasm_runtime_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++, j++) {
+ param_types[j] = TO_LLVM_TYPE(func_type->types[i]);
+
+ /* If the signature can be gotten, e.g. the signature of the builtin
+ native libraries, just check the app offset and buf size, and
+ then convert app offset to native addr and call the native func
+ directly, no need to call aot_invoke_native to call it */
+ if (signature) {
+ LLVMValueRef native_addr, native_addr_size;
+ if (signature[i + 1] == '*' || signature[i + 1] == '$') {
+ param_types[j] = INT8_PTR_TYPE;
+ }
+ if (signature[i + 1] == '*') {
+ if (signature[i + 2] == '~')
+ native_addr_size = param_values[i + 2];
+ else
+ native_addr_size = I32_ONE;
+ if (!check_app_addr_and_convert(
+ comp_ctx, func_ctx, false, param_values[j],
+ native_addr_size, &native_addr)) {
+ goto fail;
+ }
+ param_values[j] = native_addr;
+ }
+ else if (signature[i + 1] == '$') {
+ native_addr_size = I32_ZERO;
+ if (!check_app_addr_and_convert(
+ comp_ctx, func_ctx, true, param_values[j],
+ native_addr_size, &native_addr)) {
+ goto fail;
+ }
+ param_values[j] = native_addr;
+ }
+ }
+ }
+
+ if (func_type->result_count) {
+ wasm_ret_type = func_type->types[func_type->param_count];
+ ret_type = TO_LLVM_TYPE(wasm_ret_type);
+ }
+ else {
+ wasm_ret_type = VALUE_TYPE_VOID;
+ ret_type = VOID_TYPE;
+ }
+
+ if (!signature) {
+ /* call aot_invoke_native() */
+ if (!call_aot_invoke_native_func(
+ comp_ctx, func_ctx, import_func_idx, func_type,
+ param_types + 1, param_values + 1, param_count,
+ param_cell_num, ret_type, wasm_ret_type, &value_ret, &res))
+ goto fail;
+ /* Check whether there was exception thrown when executing
+ the function */
+ if (comp_ctx->enable_bound_check
+ && !check_call_return(comp_ctx, func_ctx, res))
+ goto fail;
+ }
+ else { /* call native func directly */
+ LLVMTypeRef native_func_type, func_ptr_type;
+ LLVMValueRef func_ptr;
+
+ if (!(native_func_type = LLVMFunctionType(
+ ret_type, param_types, param_count + 1, false))) {
+ aot_set_last_error("llvm add function type failed.");
+ goto fail;
+ }
+
+ if (!(func_ptr_type = LLVMPointerType(native_func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ goto fail;
+ }
+
+ /* Load function pointer */
+ if (!(func_ptr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->func_ptrs,
+ &import_func_idx, 1, "native_func_ptr_tmp"))) {
+ aot_set_last_error("llvm build inbounds gep failed.");
+ goto fail;
+ }
+
+ if (!(func_ptr = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ptr, "native_func_ptr"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+
+ if (!(func = LLVMBuildBitCast(comp_ctx->builder, func_ptr,
+ func_ptr_type, "native_func"))) {
+ aot_set_last_error("llvm bit cast failed.");
+ goto fail;
+ }
+
+ /* Call the function */
+ if (!(value_ret = LLVMBuildCall2(
+ comp_ctx->builder, native_func_type, func, param_values,
+ (uint32)param_count + 1 + ext_ret_count,
+ (func_type->result_count > 0 ? "call" : "")))) {
+ aot_set_last_error("LLVM build call failed.");
+ goto fail;
+ }
+
+ /* Check whether there was exception thrown when executing
+ the function */
+ if (!check_exception_thrown(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+ }
+ }
+ else {
+#if LLVM_VERSION_MAJOR >= 14
+ LLVMTypeRef llvm_func_type;
+#endif
+ bool recursive_call =
+ (func_ctx == func_ctxes[func_idx - import_func_count]) ? true
+ : false;
+
+ if (comp_ctx->is_indirect_mode) {
+ LLVMTypeRef func_ptr_type;
+
+ if (!(func_ptr_type = LLVMPointerType(
+ func_ctxes[func_idx - import_func_count]->func_type,
+ 0))) {
+ aot_set_last_error("construct func ptr type failed.");
+ goto fail;
+ }
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->func_ptrs,
+ func_ptr_type, func_idx))) {
+ goto fail;
+ }
+ }
+ else {
+ if (func_ctxes[func_idx - import_func_count] == func_ctx) {
+ /* recursive call */
+ func = func_ctx->func;
+ }
+ else {
+ if (!comp_ctx->is_jit_mode) {
+ func = func_ctxes[func_idx - import_func_count]->func;
+ }
+ else {
+#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0)
+ func = func_ctxes[func_idx - import_func_count]->func;
+#else
+ /* JIT tier-up, load func ptr from func_ptrs[func_idx] */
+ LLVMValueRef func_ptr, func_idx_const;
+ LLVMTypeRef func_ptr_type;
+
+ if (!(func_idx_const = I32_CONST(func_idx))) {
+ aot_set_last_error("llvm build const failed.");
+ goto fail;
+ }
+
+ if (!(func_ptr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->func_ptrs, &func_idx_const, 1,
+ "func_ptr_tmp"))) {
+ aot_set_last_error("llvm build inbounds gep failed.");
+ goto fail;
+ }
+
+ if (!(func_ptr =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ptr, "func_ptr"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+
+ if (!(func_ptr_type = LLVMPointerType(
+ func_ctxes[func_idx - import_func_count]
+ ->func_type,
+ 0))) {
+ aot_set_last_error("construct func ptr type failed.");
+ goto fail;
+ }
+
+ if (!(func = LLVMBuildBitCast(comp_ctx->builder, func_ptr,
+ func_ptr_type,
+ "indirect_func"))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ goto fail;
+ }
+#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0) */
+ }
+ }
+ }
+
+ aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
+ callee_cell_num =
+ aot_func->param_cell_num + aot_func->local_cell_num + 1;
+
+ if (!check_stack(comp_ctx, func_ctx, callee_cell_num))
+ goto fail;
+
+#if LLVM_VERSION_MAJOR >= 14
+ llvm_func_type = func_ctxes[func_idx - import_func_count]->func_type;
+#endif
+
+ /* Call the function */
+ if (!(value_ret = LLVMBuildCall2(
+ comp_ctx->builder, llvm_func_type, func, param_values,
+ (uint32)param_count + 1 + ext_ret_count,
+ (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 (tail_call)
+ LLVMSetTailCall(value_ret, true);
+
+ /* Check whether there was exception thrown when executing
+ the function */
+ if (!tail_call && !recursive_call && comp_ctx->enable_bound_check
+ && !check_exception_thrown(comp_ctx, func_ctx))
+ goto fail;
+ }
+
+ if (func_type->result_count > 0) {
+ /* Push the first result to stack */
+ PUSH(value_ret, func_type->types[func_type->param_count]);
+ /* Load extra result from its address and push to stack */
+ for (i = 0; i < ext_ret_count; i++) {
+ snprintf(buf, sizeof(buf), "func%d_ext_ret%d", func_idx, i);
+ if (!(ext_ret = LLVMBuildLoad2(
+ comp_ctx->builder, TO_LLVM_TYPE(ext_ret_types[i]),
+ param_values[1 + param_count + i], buf))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+ PUSH(ext_ret, ext_ret_types[i]);
+ }
+ }
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (comp_ctx->enable_aux_stack_frame) {
+ if (!call_aot_free_frame_func(comp_ctx, func_ctx))
+ goto fail;
+ }
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ goto fail;
+ }
+#endif
+
+ ret = true;
+fail:
+ if (param_types)
+ wasm_runtime_free(param_types);
+ if (param_values)
+ wasm_runtime_free(param_values);
+ return ret;
+}
+
+static bool
+call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ AOTFuncType *aot_func_type,
+ LLVMValueRef func_type_idx, LLVMValueRef table_idx,
+ LLVMValueRef table_elem_idx,
+ LLVMTypeRef *param_types,
+ LLVMValueRef *param_values, uint32 param_count,
+ uint32 param_cell_num, uint32 result_count,
+ uint8 *wasm_ret_types, LLVMValueRef *value_rets,
+ LLVMValueRef *p_res)
+{
+ LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
+ LLVMTypeRef ret_type, ret_ptr_type, elem_ptr_type;
+ LLVMValueRef func, ret_idx, ret_ptr, elem_idx, elem_ptr;
+ LLVMValueRef func_param_values[6], res = NULL;
+ char buf[32], *func_name = "aot_call_indirect";
+ uint32 i, cell_num = 0, ret_cell_num, argv_cell_num;
+
+ /* prepare function type of aot_call_indirect */
+ func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
+ func_param_types[1] = I32_TYPE; /* table_idx */
+ func_param_types[2] = I32_TYPE; /* table_elem_idx */
+ func_param_types[3] = I32_TYPE; /* argc */
+ func_param_types[4] = INT32_PTR_TYPE; /* argv */
+ if (!(func_type =
+ LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
+ aot_set_last_error("llvm add function type failed.");
+ return false;
+ }
+
+ /* prepare function pointer */
+ if (comp_ctx->is_jit_mode) {
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+
+ /* JIT mode, call the function directly */
+ if (!(func = I64_CONST((uint64)(uintptr_t)llvm_jit_call_indirect))
+ || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else if (comp_ctx->is_indirect_mode) {
+ int32 func_index;
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+ func_index = aot_get_native_symbol_index(comp_ctx, func_name);
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+ else {
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
+ && !(func =
+ LLVMAddFunction(func_ctx->module, func_name, func_type))) {
+ aot_set_last_error("add LLVM function failed.");
+ return false;
+ }
+ }
+
+ ret_cell_num = wasm_get_cell_num(wasm_ret_types, result_count);
+ argv_cell_num =
+ param_cell_num > ret_cell_num ? param_cell_num : ret_cell_num;
+ if (argv_cell_num > 64) {
+ aot_set_last_error("prepare native arguments failed: "
+ "maximum 64 parameter cell number supported.");
+ return false;
+ }
+
+ /* prepare frame_lp */
+ for (i = 0; i < param_count; i++) {
+ if (!(elem_idx = I32_CONST(cell_num))
+ || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
+ aot_set_last_error("llvm add const or pointer type failed.");
+ return false;
+ }
+
+ snprintf(buf, sizeof(buf), "%s%d", "elem", i);
+ if (!(elem_ptr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE,
+ func_ctx->argv_buf, &elem_idx, 1, buf))
+ || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
+ elem_ptr_type, buf))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ return false;
+ }
+
+ if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i],
+ elem_ptr))) {
+ aot_set_last_error("llvm build store failed.");
+ return false;
+ }
+ LLVMSetAlignment(res, 1);
+
+ cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
+ }
+
+ func_param_values[0] = func_ctx->exec_env;
+ func_param_values[1] = table_idx;
+ func_param_values[2] = table_elem_idx;
+ func_param_values[3] = I32_CONST(param_cell_num);
+ func_param_values[4] = func_ctx->argv_buf;
+
+ if (!func_param_values[3]) {
+ aot_set_last_error("llvm create const failed.");
+ return false;
+ }
+
+ /* call aot_call_indirect() function */
+ if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ func_param_values, 5, "res"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ /* get function result values */
+ cell_num = 0;
+ for (i = 0; i < result_count; i++) {
+ ret_type = TO_LLVM_TYPE(wasm_ret_types[i]);
+ if (!(ret_idx = I32_CONST(cell_num))
+ || !(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
+ aot_set_last_error("llvm add const or pointer type failed.");
+ return false;
+ }
+
+ snprintf(buf, sizeof(buf), "argv_ret%d", i);
+ if (!(ret_ptr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE,
+ func_ctx->argv_buf, &ret_idx, 1, buf))
+ || !(ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ret_ptr,
+ ret_ptr_type, buf))) {
+ aot_set_last_error("llvm build GEP or bit cast failed.");
+ return false;
+ }
+
+ snprintf(buf, sizeof(buf), "ret%d", i);
+ if (!(value_rets[i] =
+ LLVMBuildLoad2(comp_ctx->builder, ret_type, ret_ptr, buf))) {
+ aot_set_last_error("llvm build load failed.");
+ return false;
+ }
+ cell_num += wasm_value_type_cell_num(wasm_ret_types[i]);
+ }
+
+ *p_res = res;
+ return true;
+}
+
+bool
+aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 type_idx, uint32 tbl_idx)
+{
+ AOTFuncType *func_type;
+ LLVMValueRef tbl_idx_value, elem_idx, table_elem, func_idx;
+ LLVMValueRef ftype_idx_ptr, ftype_idx, ftype_idx_const;
+ LLVMValueRef cmp_elem_idx, cmp_func_idx, cmp_ftype_idx;
+ LLVMValueRef func, func_ptr, table_size_const;
+ LLVMValueRef ext_ret_offset, ext_ret_ptr, ext_ret, res;
+ LLVMValueRef *param_values = NULL, *value_rets = NULL;
+ LLVMValueRef *result_phis = NULL, value_ret, import_func_count;
+ LLVMTypeRef *param_types = NULL, ret_type;
+ LLVMTypeRef llvm_func_type, llvm_func_ptr_type;
+ LLVMTypeRef ext_ret_ptr_type;
+ LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ;
+ LLVMBasicBlockRef check_func_idx_succ, block_return, block_curr;
+ LLVMBasicBlockRef block_call_import, block_call_non_import;
+ LLVMValueRef offset;
+ uint32 total_param_count, func_param_count, func_result_count;
+ uint32 ext_cell_num, param_cell_num, i, j;
+ uint8 wasm_ret_type, *wasm_ret_types;
+ uint64 total_size;
+ char buf[32];
+ bool ret = false;
+
+ /* Check function type index */
+ if (type_idx >= comp_ctx->comp_data->func_type_count) {
+ aot_set_last_error("function type index out of range");
+ return false;
+ }
+
+ /* Find the equivalent function type whose type index is the smallest:
+ the callee function's type index is also converted to the smallest
+ one in wasm loader, so we can just check whether the two type indexes
+ are equal (the type index of call_indirect opcode and callee func),
+ we don't need to check whether the whole function types are equal,
+ including param types and result types. */
+ type_idx = wasm_get_smallest_type_idx(comp_ctx->comp_data->func_types,
+ comp_ctx->comp_data->func_type_count,
+ type_idx);
+ ftype_idx_const = I32_CONST(type_idx);
+ CHECK_LLVM_CONST(ftype_idx_const);
+
+ func_type = comp_ctx->comp_data->func_types[type_idx];
+ func_param_count = func_type->param_count;
+ func_result_count = func_type->result_count;
+
+ POP_I32(elem_idx);
+
+ /* get the cur size of the table instance */
+ if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+ + offsetof(AOTTableInstance, cur_size)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(table_size_const = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset,
+ 1, "cur_size_i8p"))) {
+ HANDLE_FAILURE("LLVMBuildGEP");
+ goto fail;
+ }
+
+ if (!(table_size_const =
+ LLVMBuildBitCast(comp_ctx->builder, table_size_const,
+ INT32_PTR_TYPE, "cur_siuze_i32p"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ if (!(table_size_const = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE,
+ table_size_const, "cur_size"))) {
+ HANDLE_FAILURE("LLVMBuildLoad");
+ goto fail;
+ }
+
+ /* 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 data as i32* */
+ if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+ + offsetof(AOTTableInstance, elems)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(table_elem = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "table_elem_i8p"))) {
+ aot_set_last_error("llvm build add failed.");
+ goto fail;
+ }
+
+ if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
+ INT32_PTR_TYPE, "table_elem_i32p"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ /* Load function index */
+ if (!(table_elem =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE, table_elem,
+ &elem_idx, 1, "table_elem"))) {
+ HANDLE_FAILURE("LLVMBuildNUWAdd");
+ goto fail;
+ }
+
+ if (!(func_idx = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, 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 = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, I32_TYPE, 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 = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, ftype_idx_ptr,
+ "ftype_idx"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+
+ /* Check if function type index not equal */
+ if (!(cmp_ftype_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, ftype_idx,
+ ftype_idx_const, "cmp_ftype_idx"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ goto fail;
+ }
+
+ /* Throw exception if ftype_idx != ftype_idx_const */
+ if (!(check_ftype_idx_succ = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "check_ftype_idx_succ"))) {
+ 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,
+ cmp_ftype_idx, check_ftype_idx_succ)))
+ goto fail;
+
+ /* Initialize parameter types of the LLVM function */
+ total_param_count = 1 + func_param_count;
+
+ /* Extra function results' addresses (except the first one) are
+ appended to aot function parameters. */
+ if (func_result_count > 1)
+ total_param_count += func_result_count - 1;
+
+ total_size = sizeof(LLVMTypeRef) * (uint64)total_param_count;
+ if (total_size >= UINT32_MAX
+ || !(param_types = wasm_runtime_malloc((uint32)total_size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+
+ /* Prepare param types */
+ j = 0;
+ param_types[j++] = comp_ctx->exec_env_type;
+ for (i = 0; i < func_param_count; i++)
+ param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
+
+ for (i = 1; i < func_result_count; i++, j++) {
+ param_types[j] = TO_LLVM_TYPE(func_type->types[func_param_count + i]);
+ if (!(param_types[j] = LLVMPointerType(param_types[j], 0))) {
+ aot_set_last_error("llvm get pointer type failed.");
+ goto fail;
+ }
+ }
+
+ /* Resolve return type of the LLVM function */
+ if (func_result_count) {
+ wasm_ret_type = func_type->types[func_param_count];
+ ret_type = TO_LLVM_TYPE(wasm_ret_type);
+ }
+ else {
+ wasm_ret_type = VALUE_TYPE_VOID;
+ ret_type = VOID_TYPE;
+ }
+
+ /* Allocate memory for parameters */
+ total_size = sizeof(LLVMValueRef) * (uint64)total_param_count;
+ if (total_size >= UINT32_MAX
+ || !(param_values = wasm_runtime_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 = func_param_count - 1; (int32)i >= 0; i--)
+ POP(param_values[i + j], func_type->types[i]);
+
+ /* Prepare extra parameters */
+ ext_cell_num = 0;
+ for (i = 1; i < func_result_count; i++) {
+ ext_ret_offset = I32_CONST(ext_cell_num);
+ CHECK_LLVM_CONST(ext_ret_offset);
+
+ snprintf(buf, sizeof(buf), "ext_ret%d_ptr", i - 1);
+ if (!(ext_ret_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE,
+ func_ctx->argv_buf,
+ &ext_ret_offset, 1, buf))) {
+ aot_set_last_error("llvm build GEP failed.");
+ goto fail;
+ }
+
+ ext_ret_ptr_type = param_types[func_param_count + i];
+ snprintf(buf, sizeof(buf), "ext_ret%d_ptr_cast", i - 1);
+ if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ext_ret_ptr,
+ ext_ret_ptr_type, buf))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ goto fail;
+ }
+
+ param_values[func_param_count + i] = ext_ret_ptr;
+ ext_cell_num +=
+ wasm_value_type_cell_num(func_type->types[func_param_count + i]);
+ }
+
+ if (ext_cell_num > 64) {
+ aot_set_last_error("prepare call-indirect arguments failed: "
+ "maximum 64 extra cell number supported.");
+ goto fail;
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ goto fail;
+ }
+#endif
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (comp_ctx->enable_aux_stack_frame) {
+ if (!call_aot_alloc_frame_func(comp_ctx, func_ctx, func_idx))
+ goto fail;
+ }
+#endif
+
+ /* Add basic blocks */
+ block_call_import = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "call_import");
+ block_call_non_import = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func, "call_non_import");
+ block_return = LLVMAppendBasicBlockInContext(comp_ctx->context,
+ func_ctx->func, "func_return");
+ if (!block_call_import || !block_call_non_import || !block_return) {
+ aot_set_last_error("llvm add basic block failed.");
+ goto fail;
+ }
+
+ LLVMMoveBasicBlockAfter(block_call_import,
+ LLVMGetInsertBlock(comp_ctx->builder));
+ LLVMMoveBasicBlockAfter(block_call_non_import, block_call_import);
+ LLVMMoveBasicBlockAfter(block_return, block_call_non_import);
+
+ import_func_count = I32_CONST(comp_ctx->comp_data->import_func_count);
+ CHECK_LLVM_CONST(import_func_count);
+
+ /* Check if func_idx < import_func_count */
+ if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, func_idx,
+ import_func_count, "cmp_func_idx"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ goto fail;
+ }
+
+ /* If func_idx < import_func_count, jump to call import block,
+ else jump to call non-import block */
+ if (!LLVMBuildCondBr(comp_ctx->builder, cmp_func_idx, block_call_import,
+ block_call_non_import)) {
+ aot_set_last_error("llvm build cond br failed.");
+ goto fail;
+ }
+
+ /* Add result phis for return block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_return);
+
+ if (func_result_count > 0) {
+ total_size = sizeof(LLVMValueRef) * (uint64)func_result_count;
+ if (total_size >= UINT32_MAX
+ || !(result_phis = wasm_runtime_malloc((uint32)total_size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ memset(result_phis, 0, (uint32)total_size);
+ for (i = 0; i < func_result_count; i++) {
+ LLVMTypeRef tmp_type =
+ TO_LLVM_TYPE(func_type->types[func_param_count + i]);
+ if (!(result_phis[i] =
+ LLVMBuildPhi(comp_ctx->builder, tmp_type, "phi"))) {
+ aot_set_last_error("llvm build phi failed.");
+ goto fail;
+ }
+ }
+ }
+
+ /* Translate call import block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_import);
+
+ /* Allocate memory for result values */
+ if (func_result_count > 0) {
+ total_size = sizeof(LLVMValueRef) * (uint64)func_result_count;
+ if (total_size >= UINT32_MAX
+ || !(value_rets = wasm_runtime_malloc((uint32)total_size))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ memset(value_rets, 0, (uint32)total_size);
+ }
+
+ param_cell_num = func_type->param_cell_num;
+ wasm_ret_types = func_type->types + func_type->param_count;
+
+ tbl_idx_value = I32_CONST(tbl_idx);
+ if (!tbl_idx_value) {
+ aot_set_last_error("llvm create const failed.");
+ goto fail;
+ }
+
+ if (!call_aot_call_indirect_func(
+ comp_ctx, func_ctx, func_type, ftype_idx, tbl_idx_value, elem_idx,
+ param_types + 1, param_values + 1, func_param_count, param_cell_num,
+ func_result_count, wasm_ret_types, value_rets, &res))
+ goto fail;
+
+ /* Check whether exception was thrown when executing the function */
+ if (comp_ctx->enable_bound_check
+ && !check_call_return(comp_ctx, func_ctx, res))
+ goto fail;
+
+ block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ for (i = 0; i < func_result_count; i++) {
+ LLVMAddIncoming(result_phis[i], &value_rets[i], &block_curr, 1);
+ }
+
+ if (!LLVMBuildBr(comp_ctx->builder, block_return)) {
+ aot_set_last_error("llvm build br failed.");
+ goto fail;
+ }
+
+ /* Translate call non-import block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
+
+ if (!check_stack(comp_ctx, func_ctx,
+ param_cell_num + ext_cell_num
+ + 1
+ /* Reserve some local variables */
+ + 16))
+ goto fail;
+
+ /* Load function pointer */
+ if (!(func_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->func_ptrs, &func_idx, 1,
+ "func_ptr_tmp"))) {
+ aot_set_last_error("llvm build inbounds gep failed.");
+ goto fail;
+ }
+
+ if (!(func_ptr = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, func_ptr,
+ "func_ptr"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+
+ if (!(llvm_func_type =
+ LLVMFunctionType(ret_type, param_types, total_param_count, false))
+ || !(llvm_func_ptr_type = LLVMPointerType(llvm_func_type, 0))) {
+ aot_set_last_error("llvm add function type failed.");
+ goto fail;
+ }
+
+ if (!(func = LLVMBuildBitCast(comp_ctx->builder, func_ptr,
+ llvm_func_ptr_type, "indirect_func"))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ goto fail;
+ }
+
+ if (!(value_ret = LLVMBuildCall2(comp_ctx->builder, llvm_func_type, func,
+ param_values, total_param_count,
+ func_result_count > 0 ? "ret" : ""))) {
+ aot_set_last_error("llvm build call failed.");
+ goto fail;
+ }
+
+ /* Check whether exception was thrown when executing the function */
+ if (comp_ctx->enable_bound_check
+ && !check_exception_thrown(comp_ctx, func_ctx))
+ goto fail;
+
+ if (func_result_count > 0) {
+ block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+
+ /* Push the first result to stack */
+ LLVMAddIncoming(result_phis[0], &value_ret, &block_curr, 1);
+
+ /* Load extra result from its address and push to stack */
+ for (i = 1; i < func_result_count; i++) {
+ ret_type = TO_LLVM_TYPE(func_type->types[func_param_count + i]);
+ snprintf(buf, sizeof(buf), "ext_ret%d", i - 1);
+ if (!(ext_ret = LLVMBuildLoad2(comp_ctx->builder, ret_type,
+ param_values[func_param_count + i],
+ buf))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+ LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1);
+ }
+ }
+
+ if (!LLVMBuildBr(comp_ctx->builder, block_return)) {
+ aot_set_last_error("llvm build br failed.");
+ goto fail;
+ }
+
+ /* Translate function return block */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_return);
+
+ for (i = 0; i < func_result_count; i++) {
+ PUSH(result_phis[i], func_type->types[func_param_count + i]);
+ }
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (comp_ctx->enable_aux_stack_frame) {
+ if (!call_aot_free_frame_func(comp_ctx, func_ctx))
+ goto fail;
+ }
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ goto fail;
+ }
+#endif
+
+ ret = true;
+
+fail:
+ if (param_values)
+ wasm_runtime_free(param_values);
+ if (param_types)
+ wasm_runtime_free(param_types);
+ if (value_rets)
+ wasm_runtime_free(value_rets);
+ if (result_phis)
+ wasm_runtime_free(result_phis);
+ return ret;
+}
+
+bool
+aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ PUSH_I32(REF_NULL);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_ref_is_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef lhs, res;
+
+ POP_I32(lhs);
+
+ if (!(res = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, lhs, REF_NULL,
+ "cmp_w_null"))) {
+ HANDLE_FAILURE("LLVMBuildICmp");
+ goto fail;
+ }
+
+ if (!(res = LLVMBuildZExt(comp_ctx->builder, res, I32_TYPE, "r_i"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ goto fail;
+ }
+
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_ref_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 func_idx)
+{
+ LLVMValueRef ref_idx;
+
+ if (!(ref_idx = I32_CONST(func_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ PUSH_I32(ref_idx);
+
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.h
new file mode 100644
index 000000000..26f09c660
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_function.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_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, bool tail_call);
+
+bool
+aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 type_idx, uint32 tbl_idx);
+
+bool
+aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_ref_is_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_ref_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 func_idx);
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_EMIT_FUNCTION_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.c
new file mode 100644
index 000000000..4da4cc807
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.c
@@ -0,0 +1,1435 @@
+/*
+ * 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"
+#include "aot_intrinsic.h"
+#include "aot_emit_control.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 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
+get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 bytes)
+{
+ LLVMValueRef mem_check_bound = NULL;
+ switch (bytes) {
+ case 1:
+ mem_check_bound = func_ctx->mem_info[0].mem_bound_check_1byte;
+ break;
+ case 2:
+ mem_check_bound = func_ctx->mem_info[0].mem_bound_check_2bytes;
+ break;
+ case 4:
+ mem_check_bound = func_ctx->mem_info[0].mem_bound_check_4bytes;
+ break;
+ case 8:
+ mem_check_bound = func_ctx->mem_info[0].mem_bound_check_8bytes;
+ break;
+ case 16:
+ mem_check_bound = func_ctx->mem_info[0].mem_bound_check_16bytes;
+ break;
+ default:
+ bh_assert(0);
+ return NULL;
+ }
+
+ if (func_ctx->mem_space_unchanged)
+ return mem_check_bound;
+
+ if (!(mem_check_bound = LLVMBuildLoad2(
+ comp_ctx->builder,
+ (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE : I32_TYPE,
+ mem_check_bound, "mem_check_bound"))) {
+ aot_set_last_error("llvm build load failed.");
+ return NULL;
+ }
+ return mem_check_bound;
+}
+
+static LLVMValueRef
+get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+LLVMValueRef
+aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 offset, uint32 bytes)
+{
+ LLVMValueRef offset_const = I32_CONST(offset);
+ LLVMValueRef addr, maddr, offset1, cmp1, cmp2, cmp;
+ LLVMValueRef mem_base_addr, mem_check_bound;
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef check_succ;
+ AOTValue *aot_value_top;
+ uint32 local_idx_of_aot_value = 0;
+ bool is_target_64bit, is_local_of_aot_value = false;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ bool is_shared_memory =
+ comp_ctx->comp_data->memories[0].memory_flags & 0x02;
+#endif
+
+ is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
+
+ if (comp_ctx->is_indirect_mode
+ && aot_intrinsic_check_capability(comp_ctx, "i32.const")) {
+ WASMValue wasm_value;
+ wasm_value.i32 = offset;
+ offset_const = aot_load_const_from_table(
+ comp_ctx, func_ctx->native_symbol, &wasm_value, VALUE_TYPE_I32);
+ if (!offset_const) {
+ return NULL;
+ }
+ }
+ else {
+ CHECK_LLVM_CONST(offset_const);
+ }
+
+ /* Get memory base address and memory data size */
+ if (func_ctx->mem_space_unchanged
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ || is_shared_memory
+#endif
+ ) {
+ mem_base_addr = func_ctx->mem_info[0].mem_base_addr;
+ }
+ else {
+ if (!(mem_base_addr = LLVMBuildLoad2(
+ comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->mem_info[0].mem_base_addr, "mem_base"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+ }
+
+ aot_value_top =
+ func_ctx->block_stack.block_list_end->value_stack.value_list_end;
+ if (aot_value_top) {
+ /* aot_value_top is freed in the following POP_I32(addr),
+ so save its fields here for further use */
+ is_local_of_aot_value = aot_value_top->is_local;
+ local_idx_of_aot_value = aot_value_top->local_idx;
+ }
+
+ POP_I32(addr);
+
+ /*
+ * Note: not throw the integer-overflow-exception here since it must
+ * have been thrown when converting float to integer before
+ */
+ /* return addres directly if constant offset and inside memory space */
+ if (LLVMIsConstant(addr) && !LLVMIsUndef(addr)
+#if LLVM_VERSION_NUMBER >= 12
+ && !LLVMIsPoison(addr)
+#endif
+ ) {
+ uint64 mem_offset =
+ (uint64)LLVMConstIntGetZExtValue(addr) + (uint64)offset;
+ uint32 num_bytes_per_page =
+ comp_ctx->comp_data->memories[0].num_bytes_per_page;
+ uint32 init_page_count =
+ comp_ctx->comp_data->memories[0].mem_init_page_count;
+ uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
+
+ if (mem_offset + bytes <= mem_data_size) {
+ /* inside memory space */
+ offset1 = I32_CONST((uint32)mem_offset);
+ CHECK_LLVM_CONST(offset1);
+ if (!(maddr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ mem_base_addr, &offset1, 1,
+ "maddr"))) {
+ aot_set_last_error("llvm build add failed.");
+ goto fail;
+ }
+ return maddr;
+ }
+ }
+
+ if (is_target_64bit) {
+ if (!(offset_const = LLVMBuildZExt(comp_ctx->builder, offset_const,
+ I64_TYPE, "offset_i64"))
+ || !(addr = LLVMBuildZExt(comp_ctx->builder, addr, I64_TYPE,
+ "addr_i64"))) {
+ aot_set_last_error("llvm build zero extend failed.");
+ goto fail;
+ }
+ }
+
+ /* offset1 = offset + addr; */
+ BUILD_OP(Add, offset_const, addr, offset1, "offset1");
+
+ if (comp_ctx->enable_bound_check
+ && !(is_local_of_aot_value
+ && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value,
+ offset, bytes))) {
+ uint32 init_page_count =
+ comp_ctx->comp_data->memories[0].mem_init_page_count;
+ if (init_page_count == 0) {
+ LLVMValueRef mem_size;
+
+ if (!(mem_size = get_memory_curr_page_count(comp_ctx, func_ctx))) {
+ goto fail;
+ }
+ BUILD_ICMP(LLVMIntEQ, mem_size, I32_ZERO, cmp, "is_zero");
+ ADD_BASIC_BLOCK(check_succ, "check_mem_size_succ");
+ LLVMMoveBasicBlockAfter(check_succ, block_curr);
+ 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);
+ block_curr = check_succ;
+ }
+
+ if (!(mem_check_bound =
+ get_memory_check_bound(comp_ctx, func_ctx, bytes))) {
+ goto fail;
+ }
+
+ if (is_target_64bit) {
+ BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
+ }
+ else {
+ /* Check integer overflow */
+ BUILD_ICMP(LLVMIntULT, offset1, addr, cmp1, "cmp1");
+ BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp2, "cmp2");
+ BUILD_OP(Or, cmp1, cmp2, cmp, "cmp");
+ }
+
+ /* Add basic blocks */
+ ADD_BASIC_BLOCK(check_succ, "check_succ");
+ LLVMMoveBasicBlockAfter(check_succ, block_curr);
+
+ 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);
+
+ if (is_local_of_aot_value) {
+ if (!aot_checked_addr_list_add(func_ctx, local_idx_of_aot_value,
+ offset, bytes))
+ goto fail;
+ }
+ }
+
+ /* maddr = mem_base_addr + offset1 */
+ if (!(maddr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ mem_base_addr, &offset1, 1, "maddr"))) {
+ aot_set_last_error("llvm build add failed.");
+ goto fail;
+ }
+ return maddr;
+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(data_type) \
+ do { \
+ if (!(value = LLVMBuildLoad2(comp_ctx->builder, data_type, maddr, \
+ "data"))) { \
+ aot_set_last_error("llvm build load failed."); \
+ goto fail; \
+ } \
+ LLVMSetAlignment(value, 1); \
+ } while (0)
+
+#define BUILD_TRUNC(value, 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 { \
+ LLVMValueRef res; \
+ if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \
+ aot_set_last_error("llvm build store failed."); \
+ goto fail; \
+ } \
+ LLVMSetAlignment(res, 1); \
+ } 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)
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef addr, uint32 align)
+{
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef check_align_succ;
+ LLVMValueRef align_mask = I32_CONST(((uint32)1 << align) - 1);
+ LLVMValueRef res;
+
+ CHECK_LLVM_CONST(align_mask);
+
+ /* Convert pointer to int */
+ if (!(addr = LLVMBuildPtrToInt(comp_ctx->builder, addr, I32_TYPE,
+ "address"))) {
+ aot_set_last_error("llvm build ptr to int failed.");
+ goto fail;
+ }
+
+ /* The memory address should be aligned */
+ BUILD_OP(And, addr, align_mask, res, "and");
+ BUILD_ICMP(LLVMIntNE, res, I32_ZERO, res, "cmp");
+
+ /* Add basic blocks */
+ ADD_BASIC_BLOCK(check_align_succ, "check_align_succ");
+ LLVMMoveBasicBlockAfter(check_align_succ, block_curr);
+
+ if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNALIGNED_ATOMIC, true,
+ res, check_align_succ)) {
+ goto fail;
+ }
+
+ SET_BUILD_POS(check_align_succ);
+
+ return true;
+fail:
+ return false;
+}
+
+#define BUILD_ATOMIC_LOAD(align, data_type) \
+ do { \
+ if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \
+ goto fail; \
+ } \
+ if (!(value = LLVMBuildLoad2(comp_ctx->builder, data_type, maddr, \
+ "data"))) { \
+ aot_set_last_error("llvm build load failed."); \
+ goto fail; \
+ } \
+ LLVMSetAlignment(value, 1 << align); \
+ LLVMSetVolatile(value, true); \
+ LLVMSetOrdering(value, LLVMAtomicOrderingSequentiallyConsistent); \
+ } while (0)
+
+#define BUILD_ATOMIC_STORE(align) \
+ do { \
+ LLVMValueRef res; \
+ if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \
+ goto fail; \
+ } \
+ if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \
+ aot_set_last_error("llvm build store failed."); \
+ goto fail; \
+ } \
+ LLVMSetAlignment(res, 1 << align); \
+ LLVMSetVolatile(res, true); \
+ LLVMSetOrdering(res, LLVMAtomicOrderingSequentiallyConsistent); \
+ } while (0)
+#endif
+
+bool
+aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset, uint32 bytes, bool sign,
+ bool atomic)
+{
+ LLVMValueRef maddr, value = NULL;
+ LLVMTypeRef data_type;
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+ return false;
+
+ switch (bytes) {
+ case 4:
+ BUILD_PTR_CAST(INT32_PTR_TYPE);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ BUILD_ATOMIC_LOAD(align, I32_TYPE);
+ else
+#endif
+ BUILD_LOAD(I32_TYPE);
+ break;
+ case 2:
+ case 1:
+ if (bytes == 2) {
+ BUILD_PTR_CAST(INT16_PTR_TYPE);
+ data_type = INT16_TYPE;
+ }
+ else {
+ BUILD_PTR_CAST(INT8_PTR_TYPE);
+ data_type = INT8_TYPE;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic) {
+ BUILD_ATOMIC_LOAD(align, data_type);
+ BUILD_ZERO_EXT(I32_TYPE);
+ }
+ else
+#endif
+ {
+ BUILD_LOAD(data_type);
+ if (sign)
+ BUILD_SIGN_EXT(I32_TYPE);
+ else
+ BUILD_ZERO_EXT(I32_TYPE);
+ }
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ PUSH_I32(value);
+ (void)data_type;
+ 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,
+ bool atomic)
+{
+ LLVMValueRef maddr, value = NULL;
+ LLVMTypeRef data_type;
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+ return false;
+
+ switch (bytes) {
+ case 8:
+ BUILD_PTR_CAST(INT64_PTR_TYPE);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ BUILD_ATOMIC_LOAD(align, I64_TYPE);
+ else
+#endif
+ BUILD_LOAD(I64_TYPE);
+ break;
+ case 4:
+ case 2:
+ case 1:
+ if (bytes == 4) {
+ BUILD_PTR_CAST(INT32_PTR_TYPE);
+ data_type = I32_TYPE;
+ }
+ else if (bytes == 2) {
+ BUILD_PTR_CAST(INT16_PTR_TYPE);
+ data_type = INT16_TYPE;
+ }
+ else {
+ BUILD_PTR_CAST(INT8_PTR_TYPE);
+ data_type = INT8_TYPE;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic) {
+ BUILD_ATOMIC_LOAD(align, data_type);
+ BUILD_ZERO_EXT(I64_TYPE);
+ }
+ else
+#endif
+ {
+ BUILD_LOAD(data_type);
+ if (sign)
+ BUILD_SIGN_EXT(I64_TYPE);
+ else
+ BUILD_ZERO_EXT(I64_TYPE);
+ }
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ PUSH_I64(value);
+ (void)data_type;
+ 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 = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
+ return false;
+
+ BUILD_PTR_CAST(F32_PTR_TYPE);
+ BUILD_LOAD(F32_TYPE);
+ 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 = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
+ return false;
+
+ BUILD_PTR_CAST(F64_PTR_TYPE);
+ BUILD_LOAD(F64_TYPE);
+ 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, bool atomic)
+{
+ LLVMValueRef maddr, value;
+
+ POP_I32(value);
+
+ if (!(maddr = aot_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(value, INT16_TYPE);
+ break;
+ case 1:
+ BUILD_PTR_CAST(INT8_PTR_TYPE);
+ BUILD_TRUNC(value, INT8_TYPE);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ BUILD_ATOMIC_STORE(align);
+ else
+#endif
+ 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, bool atomic)
+{
+ LLVMValueRef maddr, value;
+
+ POP_I64(value);
+
+ if (!(maddr = aot_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(value, I32_TYPE);
+ break;
+ case 2:
+ BUILD_PTR_CAST(INT16_PTR_TYPE);
+ BUILD_TRUNC(value, INT16_TYPE);
+ break;
+ case 1:
+ BUILD_PTR_CAST(INT8_PTR_TYPE);
+ BUILD_TRUNC(value, INT8_TYPE);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ BUILD_ATOMIC_STORE(align);
+ else
+#endif
+ 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 = aot_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 = aot_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_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef mem_size;
+
+ if (func_ctx->mem_space_unchanged) {
+ mem_size = func_ctx->mem_info[0].mem_cur_page_count_addr;
+ }
+ else {
+ if (!(mem_size = LLVMBuildLoad2(
+ comp_ctx->builder, I32_TYPE,
+ func_ctx->mem_info[0].mem_cur_page_count_addr, "mem_size"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+ }
+
+ return mem_size;
+fail:
+ return NULL;
+}
+
+bool
+aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef mem_size = get_memory_curr_page_count(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_curr_page_count(comp_ctx, func_ctx);
+ LLVMValueRef delta, param_values[2], ret_value, func, value;
+ LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+ int32 func_index;
+
+ if (!mem_size)
+ return false;
+
+ POP_I32(delta);
+
+ /* Function type of aot_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_enlarge_memory))
+ || !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else if (comp_ctx->is_indirect_mode) {
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+ func_index =
+ aot_get_native_symbol_index(comp_ctx, "aot_enlarge_memory");
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+ else {
+ char *func_name = "aot_enlarge_memory";
+ /* AOT mode, delcare the function */
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
+ && !(func =
+ LLVMAddFunction(func_ctx->module, func_name, func_type))) {
+ aot_set_last_error("llvm add function failed.");
+ return false;
+ }
+ }
+
+ /* Call function aot_enlarge_memory() */
+ param_values[0] = func_ctx->aot_inst;
+ param_values[1] = delta;
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 2, "call"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ BUILD_ICMP(LLVMIntUGT, ret_value, I8_ZERO, ret_value, "mem_grow_ret");
+
+ /* 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);
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+
+static LLVMValueRef
+check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMValueRef offset, LLVMValueRef bytes)
+{
+ LLVMValueRef maddr, max_addr, cmp;
+ LLVMValueRef mem_base_addr;
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef check_succ;
+ LLVMValueRef mem_size;
+
+ /* Get memory base address and memory data size */
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ bool is_shared_memory =
+ comp_ctx->comp_data->memories[0].memory_flags & 0x02;
+
+ if (func_ctx->mem_space_unchanged || is_shared_memory) {
+#else
+ if (func_ctx->mem_space_unchanged) {
+#endif
+ mem_base_addr = func_ctx->mem_info[0].mem_base_addr;
+ }
+ else {
+ if (!(mem_base_addr = LLVMBuildLoad2(
+ comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->mem_info[0].mem_base_addr, "mem_base"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+ }
+
+ /*
+ * Note: not throw the integer-overflow-exception here since it must
+ * have been thrown when converting float to integer before
+ */
+ /* return addres directly if constant offset and inside memory space */
+ if (!LLVMIsUndef(offset) && !LLVMIsUndef(bytes)
+#if LLVM_VERSION_NUMBER >= 12
+ && !LLVMIsPoison(offset) && !LLVMIsPoison(bytes)
+#endif
+ && LLVMIsConstant(offset) && LLVMIsConstant(bytes)) {
+ uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset);
+ uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes);
+ uint32 num_bytes_per_page =
+ comp_ctx->comp_data->memories[0].num_bytes_per_page;
+ uint32 init_page_count =
+ comp_ctx->comp_data->memories[0].mem_init_page_count;
+ uint32 mem_data_size = num_bytes_per_page * init_page_count;
+ if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) {
+ /* inside memory space */
+ /* maddr = mem_base_addr + moffset */
+ if (!(maddr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ mem_base_addr, &offset, 1,
+ "maddr"))) {
+ aot_set_last_error("llvm build add failed.");
+ goto fail;
+ }
+ return maddr;
+ }
+ }
+
+ if (func_ctx->mem_space_unchanged) {
+ mem_size = func_ctx->mem_info[0].mem_data_size_addr;
+ }
+ else {
+ if (!(mem_size = LLVMBuildLoad2(
+ comp_ctx->builder, I32_TYPE,
+ func_ctx->mem_info[0].mem_data_size_addr, "mem_size"))) {
+ aot_set_last_error("llvm build load failed.");
+ goto fail;
+ }
+ }
+
+ ADD_BASIC_BLOCK(check_succ, "check_succ");
+ LLVMMoveBasicBlockAfter(check_succ, block_curr);
+
+ offset =
+ LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset");
+ bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len");
+ mem_size =
+ LLVMBuildZExt(comp_ctx->builder, mem_size, I64_TYPE, "extend_size");
+
+ BUILD_OP(Add, offset, bytes, max_addr, "max_addr");
+ BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, "cmp_max_mem_addr");
+ if (!aot_emit_exception(comp_ctx, func_ctx,
+ EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
+ check_succ)) {
+ goto fail;
+ }
+
+ /* maddr = mem_base_addr + offset */
+ if (!(maddr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ mem_base_addr, &offset, 1, "maddr"))) {
+ aot_set_last_error("llvm build add failed.");
+ goto fail;
+ }
+ return maddr;
+fail:
+ return NULL;
+}
+
+bool
+aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 seg_index)
+{
+ LLVMValueRef seg, offset, dst, len, param_values[5], ret_value, func, value;
+ LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef mem_init_fail, init_success;
+
+ seg = I32_CONST(seg_index);
+
+ POP_I32(len);
+ POP_I32(offset);
+ POP_I32(dst);
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ param_types[2] = I32_TYPE;
+ param_types[3] = I32_TYPE;
+ param_types[4] = I32_TYPE;
+ ret_type = INT8_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_memory_init, 5);
+ else
+ GET_AOT_FUNCTION(aot_memory_init, 5);
+
+ /* Call function aot_memory_init() */
+ param_values[0] = func_ctx->aot_inst;
+ param_values[1] = seg;
+ param_values[2] = offset;
+ param_values[3] = len;
+ param_values[4] = dst;
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 5, "call"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ BUILD_ICMP(LLVMIntUGT, ret_value, I8_ZERO, ret_value, "mem_init_ret");
+
+ ADD_BASIC_BLOCK(mem_init_fail, "mem_init_fail");
+ ADD_BASIC_BLOCK(init_success, "init_success");
+
+ LLVMMoveBasicBlockAfter(mem_init_fail, block_curr);
+ LLVMMoveBasicBlockAfter(init_success, block_curr);
+
+ if (!LLVMBuildCondBr(comp_ctx->builder, ret_value, init_success,
+ mem_init_fail)) {
+ aot_set_last_error("llvm build cond br failed.");
+ goto fail;
+ }
+
+ /* If memory.init failed, return this function
+ so the runtime can catch the exception */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, mem_init_fail);
+ if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
+ goto fail;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, init_success);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 seg_index)
+{
+ LLVMValueRef seg, param_values[2], ret_value, func, value;
+ LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+
+ seg = I32_CONST(seg_index);
+ CHECK_LLVM_CONST(seg);
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ ret_type = INT8_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_data_drop, 2);
+ else
+ GET_AOT_FUNCTION(aot_data_drop, 2);
+
+ /* Call function aot_data_drop() */
+ param_values[0] = func_ctx->aot_inst;
+ param_values[1] = seg;
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 2, "call"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef src, dst, src_addr, dst_addr, len, res;
+ bool call_aot_memmove = false;
+
+ POP_I32(len);
+ POP_I32(src);
+ POP_I32(dst);
+
+ if (!(src_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, src, len)))
+ return false;
+
+ if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
+ return false;
+
+ call_aot_memmove = comp_ctx->is_indirect_mode || comp_ctx->is_jit_mode;
+ if (call_aot_memmove) {
+ LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+ LLVMValueRef func, params[3];
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = INT8_PTR_TYPE;
+ param_types[2] = I32_TYPE;
+ ret_type = INT8_PTR_TYPE;
+
+ if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function pointer type failed.");
+ return false;
+ }
+
+ if (comp_ctx->is_jit_mode) {
+ if (!(func = I64_CONST((uint64)(uintptr_t)aot_memmove))
+ || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else {
+ int32 func_index;
+ func_index = aot_get_native_symbol_index(comp_ctx, "memmove");
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func =
+ aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+
+ params[0] = dst_addr;
+ params[1] = src_addr;
+ params[2] = len;
+ if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func, params,
+ 3, "call_memmove"))) {
+ aot_set_last_error("llvm build memmove failed.");
+ return false;
+ }
+ }
+ else {
+ if (!(res = LLVMBuildMemMove(comp_ctx->builder, dst_addr, 1, src_addr,
+ 1, len))) {
+ aot_set_last_error("llvm build memmove failed.");
+ return false;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static void *
+jit_memset(void *s, int c, size_t n)
+{
+ return memset(s, c, n);
+}
+
+bool
+aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef val, dst, dst_addr, len, res;
+ LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+ LLVMValueRef func, params[3];
+
+ POP_I32(len);
+ POP_I32(val);
+ POP_I32(dst);
+
+ if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
+ return false;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ param_types[2] = I32_TYPE;
+ ret_type = INT8_PTR_TYPE;
+
+ if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))) {
+ aot_set_last_error("create LLVM function type failed.");
+ return false;
+ }
+
+ if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error("create LLVM function pointer type failed.");
+ return false;
+ }
+
+ if (comp_ctx->is_jit_mode) {
+ if (!(func = I64_CONST((uint64)(uintptr_t)jit_memset))
+ || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+ aot_set_last_error("create LLVM value failed.");
+ return false;
+ }
+ }
+ else if (comp_ctx->is_indirect_mode) {
+ int32 func_index;
+ func_index = aot_get_native_symbol_index(comp_ctx, "memset");
+ if (func_index < 0) {
+ return false;
+ }
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_ptr_type, func_index))) {
+ return false;
+ }
+ }
+ else {
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, "memset"))
+ && !(func =
+ LLVMAddFunction(func_ctx->module, "memset", func_type))) {
+ aot_set_last_error("llvm add function failed.");
+ return false;
+ }
+ }
+
+ params[0] = dst_addr;
+ params[1] = val;
+ params[2] = len;
+ if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func, params, 3,
+ "call_memset"))) {
+ aot_set_last_error("llvm build memset failed.");
+ return false;
+ }
+
+ return true;
+fail:
+ return false;
+}
+#endif /* end of WASM_ENABLE_BULK_MEMORY */
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 atomic_op, uint8 op_type, uint32 align,
+ uint32 offset, uint32 bytes)
+{
+ LLVMValueRef maddr, value, result;
+
+ if (op_type == VALUE_TYPE_I32)
+ POP_I32(value);
+ else
+ POP_I64(value);
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+ return false;
+
+ if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+ return false;
+
+ switch (bytes) {
+ case 8:
+ BUILD_PTR_CAST(INT64_PTR_TYPE);
+ break;
+ case 4:
+ BUILD_PTR_CAST(INT32_PTR_TYPE);
+ if (op_type == VALUE_TYPE_I64)
+ BUILD_TRUNC(value, I32_TYPE);
+ break;
+ case 2:
+ BUILD_PTR_CAST(INT16_PTR_TYPE);
+ BUILD_TRUNC(value, INT16_TYPE);
+ break;
+ case 1:
+ BUILD_PTR_CAST(INT8_PTR_TYPE);
+ BUILD_TRUNC(value, INT8_TYPE);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ if (!(result = LLVMBuildAtomicRMW(
+ comp_ctx->builder, atomic_op, maddr, value,
+ LLVMAtomicOrderingSequentiallyConsistent, false))) {
+ goto fail;
+ }
+
+ LLVMSetVolatile(result, true);
+
+ if (op_type == VALUE_TYPE_I32) {
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE,
+ "result_i32"))) {
+ goto fail;
+ }
+ PUSH_I32(result);
+ }
+ else {
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I64_TYPE,
+ "result_i64"))) {
+ goto fail;
+ }
+ PUSH_I64(result);
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 op_type,
+ uint32 align, uint32 offset, uint32 bytes)
+{
+ LLVMValueRef maddr, value, expect, result;
+
+ if (op_type == VALUE_TYPE_I32) {
+ POP_I32(value);
+ POP_I32(expect);
+ }
+ else {
+ POP_I64(value);
+ POP_I64(expect);
+ }
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+ return false;
+
+ if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+ return false;
+
+ switch (bytes) {
+ case 8:
+ BUILD_PTR_CAST(INT64_PTR_TYPE);
+ break;
+ case 4:
+ BUILD_PTR_CAST(INT32_PTR_TYPE);
+ if (op_type == VALUE_TYPE_I64) {
+ BUILD_TRUNC(value, I32_TYPE);
+ BUILD_TRUNC(expect, I32_TYPE);
+ }
+ break;
+ case 2:
+ BUILD_PTR_CAST(INT16_PTR_TYPE);
+ BUILD_TRUNC(value, INT16_TYPE);
+ BUILD_TRUNC(expect, INT16_TYPE);
+ break;
+ case 1:
+ BUILD_PTR_CAST(INT8_PTR_TYPE);
+ BUILD_TRUNC(value, INT8_TYPE);
+ BUILD_TRUNC(expect, INT8_TYPE);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ if (!(result = LLVMBuildAtomicCmpXchg(
+ comp_ctx->builder, maddr, expect, value,
+ LLVMAtomicOrderingSequentiallyConsistent,
+ LLVMAtomicOrderingSequentiallyConsistent, false))) {
+ goto fail;
+ }
+
+ LLVMSetVolatile(result, true);
+
+ /* CmpXchg return {i32, i1} structure,
+ we need to extrack the previous_value from the structure */
+ if (!(result = LLVMBuildExtractValue(comp_ctx->builder, result, 0,
+ "previous_value"))) {
+ goto fail;
+ }
+
+ if (op_type == VALUE_TYPE_I32) {
+ if (LLVMTypeOf(result) != I32_TYPE) {
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE,
+ "result_i32"))) {
+ goto fail;
+ }
+ }
+ PUSH_I32(result);
+ }
+ else {
+ if (LLVMTypeOf(result) != I64_TYPE) {
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I64_TYPE,
+ "result_i64"))) {
+ goto fail;
+ }
+ }
+ PUSH_I64(result);
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 op_type, uint32 align, uint32 offset,
+ uint32 bytes)
+{
+ LLVMValueRef maddr, value, timeout, expect, cmp;
+ LLVMValueRef param_values[5], ret_value, func, is_wait64;
+ LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+ LLVMBasicBlockRef wait_fail, wait_success;
+ LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+
+ POP_I64(timeout);
+ if (op_type == VALUE_TYPE_I32) {
+ POP_I32(expect);
+ is_wait64 = I8_CONST(false);
+ if (!(expect = LLVMBuildZExt(comp_ctx->builder, expect, I64_TYPE,
+ "expect_i64"))) {
+ goto fail;
+ }
+ }
+ else {
+ POP_I64(expect);
+ is_wait64 = I8_CONST(true);
+ }
+
+ CHECK_LLVM_CONST(is_wait64);
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+ return false;
+
+ if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+ return false;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = INT8_PTR_TYPE;
+ param_types[2] = I64_TYPE;
+ param_types[3] = I64_TYPE;
+ param_types[4] = INT8_TYPE;
+ ret_type = I32_TYPE;
+
+ GET_AOT_FUNCTION(wasm_runtime_atomic_wait, 5);
+
+ /* Call function wasm_runtime_atomic_wait() */
+ param_values[0] = func_ctx->aot_inst;
+ param_values[1] = maddr;
+ param_values[2] = expect;
+ param_values[3] = timeout;
+ param_values[4] = is_wait64;
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 5, "call"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ BUILD_ICMP(LLVMIntNE, ret_value, I32_NEG_ONE, cmp, "atomic_wait_ret");
+
+ ADD_BASIC_BLOCK(wait_fail, "atomic_wait_fail");
+ ADD_BASIC_BLOCK(wait_success, "wait_success");
+
+ LLVMMoveBasicBlockAfter(wait_fail, block_curr);
+ LLVMMoveBasicBlockAfter(wait_success, block_curr);
+
+ if (!LLVMBuildCondBr(comp_ctx->builder, cmp, wait_success, wait_fail)) {
+ aot_set_last_error("llvm build cond br failed.");
+ goto fail;
+ }
+
+ /* If atomic wait failed, return this function
+ so the runtime can catch the exception */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, wait_fail);
+ if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
+ goto fail;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, wait_success);
+
+ PUSH_I32(ret_value);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (comp_ctx->enable_thread_mgr) {
+ if (!check_suspend_flags(comp_ctx, func_ctx))
+ return false;
+ }
+#endif
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint32 align,
+ uint32 offset, uint32 bytes)
+{
+ LLVMValueRef maddr, value, count;
+ LLVMValueRef param_values[3], ret_value, func;
+ LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+
+ POP_I32(count);
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+ return false;
+
+ if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+ return false;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = INT8_PTR_TYPE;
+ param_types[2] = I32_TYPE;
+ ret_type = I32_TYPE;
+
+ GET_AOT_FUNCTION(wasm_runtime_atomic_notify, 3);
+
+ /* Call function wasm_runtime_atomic_notify() */
+ param_values[0] = func_ctx->aot_inst;
+ param_values[1] = maddr;
+ param_values[2] = count;
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 3, "call"))) {
+ aot_set_last_error("llvm build call failed.");
+ return false;
+ }
+
+ PUSH_I32(ret_value);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return LLVMBuildFence(comp_ctx->builder,
+ LLVMAtomicOrderingSequentiallyConsistent, false, "")
+ ? true
+ : false;
+}
+
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.h
new file mode 100644
index 000000000..e49582e3c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_memory.h
@@ -0,0 +1,110 @@
+/*
+ * 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"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#endif
+
+#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 atomic);
+
+bool
+aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset, uint32 bytes, bool sign,
+ bool atomic);
+
+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 atomic);
+
+bool
+aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset, uint32 bytes,
+ bool atomic);
+
+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);
+
+LLVMValueRef
+aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 offset, uint32 bytes);
+
+bool
+aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 seg_index);
+
+bool
+aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 seg_index);
+
+bool
+aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 atomic_op, uint8 op_type, uint32 align,
+ uint32 offset, uint32 bytes);
+
+bool
+aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 op_type,
+ uint32 align, uint32 offset, uint32 bytes);
+
+bool
+aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 op_type, uint32 align, uint32 offset,
+ uint32 bytes);
+
+bool
+aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint32 align,
+ uint32 offset, uint32 bytes);
+
+bool
+aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_EMIT_MEMORY_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.c
new file mode 100644
index 000000000..4c63e8a40
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.c
@@ -0,0 +1,1248 @@
+/*
+ * Copyright (C) 2020 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 "../aot/aot_intrinsic.h"
+
+#include <stdarg.h>
+
+#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 LLVM_BUILD_OP_OR_INTRINSIC(Op, left, right, res, intrinsic, name, \
+ err_ret) \
+ do { \
+ if (comp_ctx->disable_llvm_intrinsics \
+ && aot_intrinsic_check_capability(comp_ctx, intrinsic)) { \
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, \
+ param_types[0], param_types, 2, \
+ left, right); \
+ } \
+ else { \
+ LLVM_BUILD_OP(Op, left, right, res, name, false); \
+ } \
+ } 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)
+
+#if LLVM_VERSION_NUMBER >= 12
+#define IS_CONST_ZERO(val) \
+ (!LLVMIsUndef(val) && !LLVMIsPoison(val) && LLVMIsConstant(val) \
+ && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \
+ || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0)))
+#else
+#define IS_CONST_ZERO(val) \
+ (!LLVMIsUndef(val) && LLVMIsConstant(val) \
+ && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \
+ || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0)))
+#endif
+
+#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)
+
+/* Call llvm constrained floating-point intrinsic */
+static LLVMValueRef
+call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_f32,
+ const char *intrinsic, ...)
+{
+ va_list param_value_list;
+ LLVMValueRef ret;
+ LLVMTypeRef param_types[4], ret_type = is_f32 ? F32_TYPE : F64_TYPE;
+ int param_count = (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, intrinsic))
+ ? 2
+ : 4;
+
+ param_types[0] = param_types[1] = ret_type;
+ param_types[2] = param_types[3] = MD_TYPE;
+
+ va_start(param_value_list, intrinsic);
+
+ ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type,
+ param_types, param_count, param_value_list);
+
+ va_end(param_value_list);
+
+ return ret;
+}
+
+/* Call llvm constrained libm-equivalent intrinsic */
+static LLVMValueRef
+call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_f32,
+ const char *intrinsic, ...)
+{
+ 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, intrinsic);
+
+ ret = aot_call_llvm_intrinsic_v(comp_ctx, func_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, AOTFuncContext *func_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 (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx,
+ is_f32 ? "f32_cmp" : "f64_cmp")) {
+ LLVMTypeRef param_types_intrinsic[3];
+ LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_UNO, true);
+ param_types_intrinsic[0] = I32_TYPE;
+ param_types_intrinsic[1] = is_f32 ? F32_TYPE : F64_TYPE;
+ param_types_intrinsic[2] = param_types_intrinsic[1];
+ is_nan = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, is_f32 ? "f32_cmp" : "f64_cmp", I32_TYPE,
+ param_types_intrinsic, 3, opcond, left, right);
+
+ opcond = LLVMConstInt(I32_TYPE, FLOAT_EQ, true);
+ is_eq = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, is_f32 ? "f32_cmp" : "f64_cmp", I32_TYPE,
+ param_types_intrinsic, 3, opcond, left, right);
+
+ if (!is_nan || !is_eq) {
+ return NULL;
+ }
+
+ if (!(is_nan = LLVMBuildIntCast(comp_ctx->builder, is_nan, INT1_TYPE,
+ "bit_cast_is_nan"))) {
+ aot_set_last_error("llvm build is_nan bit cast fail.");
+ return NULL;
+ }
+
+ if (!(is_eq = LLVMBuildIntCast(comp_ctx->builder, is_eq, INT1_TYPE,
+ "bit_cast_is_eq"))) {
+ aot_set_last_error("llvm build is_eq bit cast fail.");
+ return NULL;
+ }
+ }
+ else 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_INTRINSIC(Or, left_int, right_int, tmp,
+ is_f32 ? "i32.or" : "i64.or", "tmp_int",
+ false);
+ else
+ LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp,
+ is_f32 ? "i32.and" : "i64.and", "tmp_int",
+ false);
+
+ if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) {
+ aot_set_last_error("llvm build bitcast fail.");
+ return NULL;
+ }
+
+ if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type,
+ param_types, 2, left, right)))
+ return NULL;
+
+ /* The result of XIP intrinsic is 0 or 1, should return it directly */
+
+ if (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx,
+ is_f32 ? "f32_cmp" : "f64_cmp")) {
+ return cmp;
+ }
+
+ 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;
+
+/* clang-format off */
+static char *bit_cnt_llvm_intrinsic[] = {
+ "llvm.ctlz.i32",
+ "llvm.ctlz.i64",
+ "llvm.cttz.i32",
+ "llvm.cttz.i64",
+ "llvm.ctpop.i32",
+ "llvm.ctpop.i64",
+};
+/* clang-format on */
+
+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 */
+ if (type < POP_CNT32)
+ DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, bit_cnt_llvm_intrinsic[type],
+ ret_type, param_types, 2, operand, zero_undef),
+ NULL);
+ else
+ DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, bit_cnt_llvm_intrinsic[type],
+ ret_type, param_types, 1, operand),
+ 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;
+ LLVMTypeRef param_types[2];
+
+ param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE;
+
+ 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);
+
+ LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, no_overflow_value,
+ is_i32 ? "i32.rem_s" : "i64.rem_s", "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;
+ LLVMTypeRef param_types[2];
+ const char *intrinsic = NULL;
+
+ param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE;
+
+ 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 (LLVMIsUndef(right) || LLVMIsUndef(left)
+#if LLVM_VERSION_NUMBER >= 12
+ || LLVMIsPoison(right) || LLVMIsPoison(left)
+#endif
+ ) {
+ if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW,
+ false, NULL, NULL))) {
+ goto fail;
+ }
+ return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
+ }
+
+ 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_OR_INTRINSIC(
+ SDiv, left, right, res,
+ is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false);
+ break;
+ case INT_DIV_U:
+ LLVM_BUILD_OP_OR_INTRINSIC(
+ UDiv, left, right, res,
+ is_i32 ? "i32.div_u" : "i64.div_u", "div_u", false);
+ break;
+ case INT_REM_S:
+ LLVM_BUILD_OP_OR_INTRINSIC(
+ SRem, left, right, res,
+ is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", false);
+ break;
+ case INT_REM_U:
+ LLVM_BUILD_OP_OR_INTRINSIC(
+ URem, left, right, res,
+ is_i32 ? "i32.rem_u" : "i64.rem_u", "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_OR_INTRINSIC(SDiv, left, right, res,
+ is_i32 ? "i32.div_s" : "i64.div_s",
+ "div_s", false);
+ PUSH_INT(res);
+ return true;
+ case INT_DIV_U:
+ intrinsic = is_i32 ? "i32.div_u" : "i64.div_u";
+ if (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, intrinsic)) {
+ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+ param_types[0], param_types,
+ 2, left, right);
+ }
+ else {
+ 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_OR_INTRINSIC(URem, left, right, res,
+ is_i32 ? "i32.rem_u" : "i64.rem_u",
+ "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;
+
+ /* rotl/rotr with 0 */
+ if (IS_CONST_ZERO(right))
+ return left;
+
+ /* 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<<count | 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
+is_target_arm(AOTCompContext *comp_ctx)
+{
+ return !strncmp(comp_ctx->target_arch, "arm", 3)
+ || !strncmp(comp_ctx->target_arch, "aarch64", 7)
+ || !strncmp(comp_ctx->target_arch, "thumb", 5);
+}
+
+static bool
+is_target_x86(AOTCompContext *comp_ctx)
+{
+ return !strncmp(comp_ctx->target_arch, "x86_64", 6)
+ || !strncmp(comp_ctx->target_arch, "i386", 4);
+}
+
+static bool
+is_target_xtensa(AOTCompContext *comp_ctx)
+{
+ return !strncmp(comp_ctx->target_arch, "xtensa", 6);
+}
+
+static bool
+is_target_mips(AOTCompContext *comp_ctx)
+{
+ return !strncmp(comp_ctx->target_arch, "mips", 4);
+}
+
+static bool
+is_target_riscv(AOTCompContext *comp_ctx)
+{
+ return !strncmp(comp_ctx->target_arch, "riscv", 5);
+}
+
+static bool
+is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32)
+{
+ bool ret = false;
+ char *feature_string;
+
+ if (!(feature_string =
+ LLVMGetTargetMachineFeatureString(comp_ctx->target_machine))) {
+ aot_set_last_error("llvm get target machine feature string fail.");
+ return false;
+ }
+
+ /* Note:
+ * LLVM CodeGen uses FPU Coprocessor registers by default,
+ * so user must specify '--cpu-features=+soft-float' to wamrc if the target
+ * doesn't have or enable FPU on arm, x86 or mips. */
+ if (is_target_arm(comp_ctx) || is_target_x86(comp_ctx)
+ || is_target_mips(comp_ctx)) {
+ ret = strstr(feature_string, "+soft-float") ? true : false;
+ }
+ else if (is_target_xtensa(comp_ctx)) {
+ /* Note:
+ * 1. The Floating-Point Coprocessor Option of xtensa only support
+ * single-precision floating-point operations, so must use soft-float
+ * for f64(i.e. double).
+ * 2. LLVM CodeGen uses Floating-Point Coprocessor registers by default,
+ * so user must specify '--cpu-features=-fp' to wamrc if the target
+ * doesn't have or enable Floating-Point Coprocessor Option on xtensa.
+ */
+ if (comp_ctx->disable_llvm_intrinsics)
+ ret = false;
+ else
+ ret = (!is_f32 || strstr(feature_string, "-fp")) ? true : false;
+ }
+ else if (is_target_riscv(comp_ctx)) {
+ /*
+ * Note: Use builtin intrinsics since hardware float operation
+ * will cause rodata relocation, this will try to use hardware
+ * float unit (by return false) but handled by software finally
+ */
+ if (comp_ctx->disable_llvm_intrinsics)
+ ret = false;
+ else
+ ret = !strstr(feature_string, "+d") ? true : false;
+ }
+ else {
+ ret = true;
+ }
+
+ LLVMDisposeMessage(feature_string);
+ return ret;
+}
+
+static bool
+compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op, bool is_f32)
+{
+ switch (arith_op) {
+ case FLOAT_ADD:
+ if (is_targeting_soft_float(comp_ctx, is_f32))
+ DEF_FP_BINARY_OP(
+ LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"),
+ "llvm build fadd fail.");
+ else
+ DEF_FP_BINARY_OP(
+ call_llvm_float_experimental_constrained_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ (is_f32 ? "llvm.experimental.constrained.fadd.f32"
+ : "llvm.experimental.constrained.fadd.f64"),
+ left, right, comp_ctx->fp_rounding_mode,
+ comp_ctx->fp_exception_behavior),
+ NULL);
+ return true;
+ case FLOAT_SUB:
+ if (is_targeting_soft_float(comp_ctx, is_f32))
+ DEF_FP_BINARY_OP(
+ LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"),
+ "llvm build fsub fail.");
+ else
+ DEF_FP_BINARY_OP(
+ call_llvm_float_experimental_constrained_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ (is_f32 ? "llvm.experimental.constrained.fsub.f32"
+ : "llvm.experimental.constrained.fsub.f64"),
+ left, right, comp_ctx->fp_rounding_mode,
+ comp_ctx->fp_exception_behavior),
+ NULL);
+ return true;
+ case FLOAT_MUL:
+ if (is_targeting_soft_float(comp_ctx, is_f32))
+ DEF_FP_BINARY_OP(
+ LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"),
+ "llvm build fmul fail.");
+ else
+ DEF_FP_BINARY_OP(
+ call_llvm_float_experimental_constrained_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ (is_f32 ? "llvm.experimental.constrained.fmul.f32"
+ : "llvm.experimental.constrained.fmul.f64"),
+ left, right, comp_ctx->fp_rounding_mode,
+ comp_ctx->fp_exception_behavior),
+ NULL);
+ return true;
+ case FLOAT_DIV:
+ if (is_targeting_soft_float(comp_ctx, is_f32))
+ DEF_FP_BINARY_OP(
+ LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"),
+ "llvm build fdiv fail.");
+ else
+ DEF_FP_BINARY_OP(
+ call_llvm_float_experimental_constrained_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ (is_f32 ? "llvm.experimental.constrained.fdiv.f32"
+ : "llvm.experimental.constrained.fdiv.f64"),
+ 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, func_ctx, is_f32, left, right, true),
+ NULL);
+ return true;
+ case FLOAT_MAX:
+ DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, func_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,
+ AOTFuncContext *func_ctx, bool is_f32,
+ const char *intrinsic, ...)
+{
+ 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, intrinsic);
+
+ ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type,
+ &param_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, func_ctx, is_f32,
+ is_f32 ? "llvm.fabs.f32" : "llvm.fabs.f64",
+ 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, func_ctx, is_f32,
+ is_f32 ? "llvm.ceil.f32" : "llvm.ceil.f64",
+ operand),
+ NULL);
+ return true;
+ case FLOAT_FLOOR:
+ DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ is_f32 ? "llvm.floor.f32" : "llvm.floor.f64",
+ operand),
+ NULL);
+ return true;
+ case FLOAT_TRUNC:
+ DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ is_f32 ? "llvm.trunc.f32" : "llvm.trunc.f64",
+ operand),
+ NULL);
+ return true;
+ case FLOAT_NEAREST:
+ DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ is_f32 ? "llvm.rint.f32" : "llvm.rint.f64",
+ operand),
+ NULL);
+ return true;
+ case FLOAT_SQRT:
+ if (is_targeting_soft_float(comp_ctx, is_f32)
+ || comp_ctx->disable_llvm_intrinsics)
+ DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ is_f32 ? "llvm.sqrt.f32" : "llvm.sqrt.f64",
+ operand),
+ NULL);
+ else
+ DEF_FP_UNARY_OP(
+ call_llvm_libm_experimental_constrained_intrinsic(
+ comp_ctx, func_ctx, is_f32,
+ (is_f32 ? "llvm.experimental.constrained.sqrt.f32"
+ : "llvm.experimental.constrained.sqrt.f64"),
+ 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(aot_call_llvm_intrinsic(
+ comp_ctx, func_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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.h
new file mode 100644
index 000000000..7206315df
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_numberic.h
@@ -0,0 +1,87 @@
+/*
+ * 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.c
new file mode 100644
index 000000000..8b1a9e6da
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.c
@@ -0,0 +1,107 @@
+/*
+ * 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_runtime_free(aot_value);
+
+ /* is_32: i32, f32, ref.func, ref.extern, v128 */
+ if (is_32
+ && !(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+ || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+ || type == VALUE_TYPE_V128)) {
+ aot_set_last_error("invalid WASM stack data type.");
+ return false;
+ }
+
+ /* !is_32: i64, f64 */
+ if (!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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.h
new file mode 100644
index 000000000..68fe8f11d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_parametric.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_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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.c
new file mode 100644
index 000000000..d8a5efd91
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_emit_table.h"
+#include "aot_emit_exception.h"
+#include "../aot/aot_runtime.h"
+
+uint64
+get_tbl_inst_offset(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, uint32 tbl_idx)
+{
+ uint64 offset = 0, i = 0;
+ AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
+ AOTTable *tbls = comp_ctx->comp_data->tables;
+
+ offset =
+ offsetof(AOTModuleInstance, global_table_data.bytes)
+ + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
+ + comp_ctx->comp_data->global_data_size;
+
+ while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
+ offset += offsetof(AOTTableInstance, elems);
+ /* avoid loading from current AOTTableInstance */
+ offset +=
+ sizeof(uint32)
+ * aot_get_imp_tbl_data_slots(imp_tbls + i, comp_ctx->is_jit_mode);
+ ++i;
+ }
+
+ if (i == tbl_idx) {
+ return offset;
+ }
+
+ tbl_idx -= comp_ctx->comp_data->import_table_count;
+ i -= comp_ctx->comp_data->import_table_count;
+ while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
+ offset += offsetof(AOTTableInstance, elems);
+ /* avoid loading from current AOTTableInstance */
+ offset += sizeof(uint32)
+ * aot_get_tbl_data_slots(tbls + i, comp_ctx->is_jit_mode);
+ ++i;
+ }
+
+ return offset;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+
+LLVMValueRef
+aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx)
+{
+ LLVMValueRef offset, tbl_inst;
+
+ if (!(offset =
+ I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(tbl_inst = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "tbl_inst"))) {
+ HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+ goto fail;
+ }
+
+ return tbl_inst;
+fail:
+ return NULL;
+}
+
+bool
+aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_seg_idx)
+{
+ LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+ LLVMValueRef param_values[2], ret_value, func, value;
+
+ /* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ ret_type = VOID_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_drop_table_seg, 2);
+ else
+ GET_AOT_FUNCTION(aot_drop_table_seg, 2);
+
+ param_values[0] = func_ctx->aot_inst;
+ if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ /* "" means return void */
+ if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+ param_values, 2, ""))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+aot_check_table_access(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx, LLVMValueRef elem_idx)
+{
+ LLVMValueRef offset, tbl_sz, cmp_elem_idx;
+ LLVMBasicBlockRef check_elem_idx_succ;
+
+ /* get the cur size of the table instance */
+ if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+ + offsetof(AOTTableInstance, cur_size)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(tbl_sz = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "cur_size_i8p"))) {
+ HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+ goto fail;
+ }
+
+ if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
+ "cur_siuze_i32p"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ if (!(tbl_sz = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, tbl_sz,
+ "cur_size"))) {
+ HANDLE_FAILURE("LLVMBuildLoad");
+ goto fail;
+ }
+
+ /* Check if (uint32)elem index >= table size */
+ if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
+ tbl_sz, "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_OUT_OF_BOUNDS_TABLE_ACCESS, true,
+ cmp_elem_idx, check_elem_idx_succ)))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx)
+{
+ LLVMValueRef elem_idx, offset, table_elem, func_idx;
+
+ POP_I32(elem_idx);
+
+ if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
+ goto fail;
+ }
+
+ /* load data as i32* */
+ if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+ + offsetof(AOTTableInstance, elems)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(table_elem = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "table_elem_i8p"))) {
+ aot_set_last_error("llvm build add failed.");
+ goto fail;
+ }
+
+ if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
+ INT32_PTR_TYPE, "table_elem_i32p"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ /* Load function index */
+ if (!(table_elem =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE, table_elem,
+ &elem_idx, 1, "table_elem"))) {
+ HANDLE_FAILURE("LLVMBuildNUWAdd");
+ goto fail;
+ }
+
+ if (!(func_idx = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, table_elem,
+ "func_idx"))) {
+ HANDLE_FAILURE("LLVMBuildLoad");
+ goto fail;
+ }
+
+ PUSH_I32(func_idx);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx)
+{
+ LLVMValueRef val, elem_idx, offset, table_elem;
+
+ POP_I32(val);
+ POP_I32(elem_idx);
+
+ if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
+ goto fail;
+ }
+
+ /* load data as i32* */
+ if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+ + offsetof(AOTTableInstance, elems)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(table_elem = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "table_elem_i8p"))) {
+ HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+ goto fail;
+ }
+
+ if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
+ INT32_PTR_TYPE, "table_elem_i32p"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ /* Load function index */
+ if (!(table_elem =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, I32_TYPE, table_elem,
+ &elem_idx, 1, "table_elem"))) {
+ HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+ goto fail;
+ }
+
+ if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem))) {
+ HANDLE_FAILURE("LLVMBuildStore");
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx, uint32 tbl_seg_idx)
+
+{
+ LLVMValueRef func, param_values[6], value;
+ LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ param_types[2] = I32_TYPE;
+ param_types[3] = I32_TYPE;
+ param_types[4] = I32_TYPE;
+ param_types[5] = I32_TYPE;
+ ret_type = VOID_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_table_init, 6);
+ else
+ GET_AOT_FUNCTION(aot_table_init, 6);
+
+ param_values[0] = func_ctx->aot_inst;
+
+ if (!(param_values[1] = I32_CONST(tbl_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ /* n */
+ POP_I32(param_values[3]);
+ /* s */
+ POP_I32(param_values[4]);
+ /* d */
+ POP_I32(param_values[5]);
+
+ /* "" means return void */
+ if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
+ ""))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 src_tbl_idx, uint32 dst_tbl_idx)
+{
+ LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+ LLVMValueRef func, param_values[6], value;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ param_types[2] = I32_TYPE;
+ param_types[3] = I32_TYPE;
+ param_types[4] = I32_TYPE;
+ param_types[5] = I32_TYPE;
+ ret_type = VOID_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_table_copy, 6);
+ else
+ GET_AOT_FUNCTION(aot_table_copy, 6);
+
+ param_values[0] = func_ctx->aot_inst;
+
+ if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ /* n */
+ POP_I32(param_values[3]);
+ /* s */
+ POP_I32(param_values[4]);
+ /* d */
+ POP_I32(param_values[5]);
+
+ /* "" means return void */
+ if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
+ ""))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx)
+{
+ LLVMValueRef offset, tbl_sz;
+
+ if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+ + offsetof(AOTTableInstance, cur_size)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(tbl_sz = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "tbl_sz_ptr_i8"))) {
+ HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+ goto fail;
+ }
+
+ if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
+ "tbl_sz_ptr"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ if (!(tbl_sz =
+ LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, tbl_sz, "tbl_sz"))) {
+ HANDLE_FAILURE("LLVMBuildLoad");
+ goto fail;
+ }
+
+ PUSH_I32(tbl_sz);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx)
+{
+ LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
+ LLVMValueRef func, param_values[4], ret, value;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ param_types[2] = I32_TYPE;
+ param_types[3] = I32_TYPE;
+ ret_type = I32_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_table_grow, 4);
+ else
+ GET_AOT_FUNCTION(aot_table_grow, 4);
+
+ param_values[0] = func_ctx->aot_inst;
+
+ if (!(param_values[1] = I32_CONST(tbl_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ /* n */
+ POP_I32(param_values[2]);
+ /* v */
+ POP_I32(param_values[3]);
+
+ if (!(ret = LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
+ 4, "table_grow"))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ goto fail;
+ }
+
+ PUSH_I32(ret);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx)
+{
+ LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+ LLVMValueRef func, param_values[5], value;
+
+ param_types[0] = INT8_PTR_TYPE;
+ param_types[1] = I32_TYPE;
+ param_types[2] = I32_TYPE;
+ param_types[3] = I32_TYPE;
+ param_types[4] = I32_TYPE;
+ ret_type = VOID_TYPE;
+
+ if (comp_ctx->is_jit_mode)
+ GET_AOT_FUNCTION(llvm_jit_table_fill, 5);
+ else
+ GET_AOT_FUNCTION(aot_table_fill, 5);
+
+ param_values[0] = func_ctx->aot_inst;
+
+ if (!(param_values[1] = I32_CONST(tbl_idx))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ /* n */
+ POP_I32(param_values[2]);
+ /* v */
+ POP_I32(param_values[3]);
+ /* i */
+ POP_I32(param_values[4]);
+
+ /* "" means return void */
+ if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 5,
+ ""))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.h
new file mode 100644
index 000000000..e5ab0ed48
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_table.h
@@ -0,0 +1,59 @@
+
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_EMIT_TABLE_H_
+#define _AOT_EMIT_TABLE_H_
+
+#include "aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_seg_idx);
+
+bool
+aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx);
+
+bool
+aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx);
+
+bool
+aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx, uint32 tbl_seg_idx);
+
+bool
+aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 src_tbl_idx, uint32 dst_tbl_idx);
+
+bool
+aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx);
+
+bool
+aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx);
+
+bool
+aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx);
+
+uint64
+get_tbl_inst_offset(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, uint32 tbl_idx);
+
+LLVMValueRef
+aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 tbl_idx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+#endif \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.c
new file mode 100644
index 000000000..70487d4de
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_emit_variable.h"
+#include "aot_emit_exception.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;
+ AOTValue *aot_value_top;
+ uint8 local_type;
+
+ CHECK_LOCAL(local_idx);
+
+ local_type = get_local_type(func_ctx, local_idx);
+
+ snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#");
+ if (!(value = LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(local_type),
+ func_ctx->locals[local_idx], name))) {
+ aot_set_last_error("llvm build load fail");
+ return false;
+ }
+
+ PUSH(value, local_type);
+
+ aot_value_top =
+ func_ctx->block_stack.block_list_end->value_stack.value_list_end;
+ aot_value_top->is_local = true;
+ aot_value_top->local_idx = 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;
+ }
+
+ aot_checked_addr_list_del(func_ctx, local_idx);
+ 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);
+ aot_checked_addr_list_del(func_ctx, local_idx);
+ return true;
+
+fail:
+ return false;
+}
+
+static bool
+compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 global_idx, bool is_set, bool is_aux_stack)
+{
+ AOTCompData *comp_data = comp_ctx->comp_data;
+ uint32 import_global_count = comp_data->import_global_count;
+ uint32 global_base_offset;
+ uint32 global_offset;
+ uint8 global_type;
+ LLVMValueRef offset, global_ptr, global, res;
+ LLVMTypeRef ptr_type = NULL;
+
+ global_base_offset =
+ offsetof(AOTModuleInstance, global_table_data.bytes)
+ + sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
+
+ 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 = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "global_ptr_tmp"))) {
+ aot_set_last_error("llvm build in bounds gep failed.");
+ return false;
+ }
+
+ switch (global_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+ 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;
+ case VALUE_TYPE_V128:
+ ptr_type = comp_ctx->basic_types.v128_ptr_type;
+ break;
+ default:
+ bh_assert("unknown type");
+ 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 =
+ LLVMBuildLoad2(comp_ctx->builder, TO_LLVM_TYPE(global_type),
+ global_ptr, "global"))) {
+ aot_set_last_error("llvm build load failed.");
+ return false;
+ }
+ /* All globals' data is 4-byte aligned */
+ LLVMSetAlignment(global, 4);
+ PUSH(global, global_type);
+ }
+ else {
+ POP(global, global_type);
+
+ if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
+ LLVMBasicBlockRef block_curr =
+ LLVMGetInsertBlock(comp_ctx->builder);
+ LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
+ LLVMValueRef cmp;
+
+ /* Add basic blocks */
+ if (!(check_overflow_succ = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func,
+ "check_overflow_succ"))) {
+ aot_set_last_error("llvm add basic block failed.");
+ return false;
+ }
+ LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
+
+ if (!(check_underflow_succ = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_ctx->func,
+ "check_underflow_succ"))) {
+ aot_set_last_error("llvm add basic block failed.");
+ return false;
+ }
+ LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
+
+ /* Check aux stack overflow */
+ if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global,
+ func_ctx->aux_stack_bound, "cmp"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ return false;
+ }
+ if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_AUX_STACK_OVERFLOW,
+ true, cmp, check_overflow_succ)) {
+ return false;
+ }
+
+ /* Check aux stack underflow */
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
+ if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global,
+ func_ctx->aux_stack_bottom, "cmp"))) {
+ aot_set_last_error("llvm build icmp failed.");
+ return false;
+ }
+ if (!aot_emit_exception(comp_ctx, func_ctx,
+ EXCE_AUX_STACK_UNDERFLOW, true, cmp,
+ check_underflow_succ)) {
+ return false;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
+ }
+
+ if (!(res = LLVMBuildStore(comp_ctx->builder, global, global_ptr))) {
+ aot_set_last_error("llvm build store failed.");
+ return false;
+ }
+ /* All globals' data is 4-byte aligned */
+ LLVMSetAlignment(res, 4);
+ }
+
+ 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, false);
+}
+
+bool
+aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 global_idx, bool is_aux_stack)
+{
+ return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.h
new file mode 100644
index 000000000..28c0bd093
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_variable.h
@@ -0,0 +1,39 @@
+/*
+ * 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, bool is_aux_stack);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_EMIT_VARIABLE_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.c
new file mode 100644
index 000000000..dc3fe7f59
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.c
@@ -0,0 +1,2770 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_llvm.h"
+#include "aot_llvm_extra2.h"
+#include "aot_compiler.h"
+#include "aot_emit_exception.h"
+#include "../aot/aot_runtime.h"
+#include "../aot/aot_intrinsic.h"
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+#include "debug/dwarf_extractor.h"
+#endif
+
+LLVMTypeRef
+wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
+{
+ switch (wasm_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+ 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_V128:
+ return llvm_types->i64x2_vec_type;
+ case VALUE_TYPE_VOID:
+ return llvm_types->void_type;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/**
+ * Add LLVM function
+ */
+static LLVMValueRef
+aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
+ AOTFuncType *aot_func_type, uint32 func_index,
+ LLVMTypeRef *p_func_type)
+{
+ LLVMValueRef func = NULL;
+ LLVMTypeRef *param_types, ret_type, func_type;
+ LLVMValueRef local_value;
+ LLVMTypeRef func_type_wrapper;
+ LLVMValueRef func_wrapper;
+ LLVMBasicBlockRef func_begin;
+ char func_name[48];
+ uint64 size;
+ uint32 i, j = 0, param_count = (uint64)aot_func_type->param_count;
+ uint32 backend_thread_num, compile_thread_num;
+
+ /* exec env as first parameter */
+ param_count++;
+
+ /* Extra wasm function results(except the first one)'s address are
+ * appended to aot function parameters. */
+ if (aot_func_type->result_count > 1)
+ param_count += aot_func_type->result_count - 1;
+
+ /* Initialize parameter types of the LLVM function */
+ size = sizeof(LLVMTypeRef) * ((uint64)param_count);
+ if (size >= UINT32_MAX
+ || !(param_types = wasm_runtime_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]);
+ /* Extra results' address */
+ for (i = 1; i < aot_func_type->result_count; i++, j++) {
+ param_types[j] =
+ TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count + i]);
+ if (!(param_types[j] = LLVMPointerType(param_types[j], 0))) {
+ aot_set_last_error("llvm get pointer type failed.");
+ goto fail;
+ }
+ }
+
+ /* 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(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, "");
+ }
+
+ if (p_func_type)
+ *p_func_type = func_type;
+
+ backend_thread_num = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+ compile_thread_num = WASM_ORC_JIT_COMPILE_THREAD_NUM;
+
+ /* Add the jit wrapper function with simple prototype, so that we
+ can easily call it to trigger its compilation and let LLVM JIT
+ compile the actual jit functions by adding them into the function
+ list in the PartitionFunction callback */
+ if (comp_ctx->is_jit_mode
+ && (func_index % (backend_thread_num * compile_thread_num)
+ < backend_thread_num)) {
+ func_type_wrapper = LLVMFunctionType(VOID_TYPE, NULL, 0, false);
+ if (!func_type_wrapper) {
+ aot_set_last_error("create LLVM function type failed.");
+ goto fail;
+ }
+
+ snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX,
+ func_index, "_wrapper");
+ if (!(func_wrapper =
+ LLVMAddFunction(module, func_name, func_type_wrapper))) {
+ aot_set_last_error("add LLVM function failed.");
+ goto fail;
+ }
+
+ if (!(func_begin = LLVMAppendBasicBlockInContext(
+ comp_ctx->context, func_wrapper, "func_begin"))) {
+ aot_set_last_error("add LLVM basic block failed.");
+ goto fail;
+ }
+
+ LLVMPositionBuilderAtEnd(comp_ctx->builder, func_begin);
+ if (!LLVMBuildRetVoid(comp_ctx->builder)) {
+ aot_set_last_error("llvm build ret failed.");
+ goto fail;
+ }
+ }
+
+fail:
+ wasm_runtime_free(param_types);
+ return func;
+}
+
+static void
+free_block_memory(AOTBlock *block)
+{
+ if (block->param_types)
+ wasm_runtime_free(block->param_types);
+ if (block->result_types)
+ wasm_runtime_free(block->result_types);
+ wasm_runtime_free(block);
+}
+
+/**
+ * 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;
+ uint32 param_count = aot_func_type->param_count,
+ result_count = aot_func_type->result_count;
+
+ /* Allocate memory */
+ if (!(aot_block = wasm_runtime_malloc(sizeof(AOTBlock)))) {
+ aot_set_last_error("allocate memory failed.");
+ return NULL;
+ }
+ memset(aot_block, 0, sizeof(AOTBlock));
+ if (param_count
+ && !(aot_block->param_types = wasm_runtime_malloc(param_count))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ if (result_count) {
+ if (!(aot_block->result_types = wasm_runtime_malloc(result_count))) {
+ aot_set_last_error("allocate memory failed.");
+ goto fail;
+ }
+ }
+
+ /* Set block data */
+ aot_block->label_type = LABEL_TYPE_FUNCTION;
+ aot_block->param_count = param_count;
+ if (param_count) {
+ bh_memcpy_s(aot_block->param_types, param_count, aot_func_type->types,
+ param_count);
+ }
+ aot_block->result_count = result_count;
+ if (result_count) {
+ bh_memcpy_s(aot_block->result_types, result_count,
+ aot_func_type->types + param_count, result_count);
+ }
+ 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:
+ free_block_memory(aot_block);
+ return NULL;
+}
+
+static bool
+create_argv_buf(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr;
+ LLVMTypeRef int32_ptr_type;
+
+ /* Get argv buffer address */
+ if (!(argv_buf_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
+ &argv_buf_offset, 1, "argv_buf_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+
+ if (!(int32_ptr_type = LLVMPointerType(INT32_PTR_TYPE, 0))) {
+ aot_set_last_error("llvm add pointer type failed");
+ return false;
+ }
+
+ /* Convert to int32 pointer type */
+ if (!(argv_buf_addr = LLVMBuildBitCast(comp_ctx->builder, argv_buf_addr,
+ int32_ptr_type, "argv_buf_ptr"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+
+ if (!(func_ctx->argv_buf = LLVMBuildLoad2(comp_ctx->builder, INT32_PTR_TYPE,
+ argv_buf_addr, "argv_buf"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
+
+ if (!(stack_bound_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
+ &stack_bound_offset, 1, "stack_bound_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+
+ if (!(func_ctx->native_stack_bound =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, stack_bound_addr,
+ "native_stack_bound"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+create_native_stack_top_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef offset = I32_NINE;
+
+ if (!(func_ctx->native_stack_top_min_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
+ "native_stack_top_min_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef aux_stack_bound_offset = I32_SIX, aux_stack_bound_addr;
+ LLVMValueRef aux_stack_bottom_offset = I32_SEVEN, aux_stack_bottom_addr;
+
+ /* Get aux stack boundary address */
+ if (!(aux_stack_bound_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
+ &aux_stack_bound_offset, 1, "aux_stack_bound_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+
+ if (!(aux_stack_bound_addr =
+ LLVMBuildBitCast(comp_ctx->builder, aux_stack_bound_addr,
+ INT32_PTR_TYPE, "aux_stack_bound_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+
+ if (!(func_ctx->aux_stack_bound =
+ LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, aux_stack_bound_addr,
+ "aux_stack_bound"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+
+ /* Get aux stack bottom address */
+ if (!(aux_stack_bottom_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
+ &aux_stack_bottom_offset, 1, "aux_stack_bottom_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+
+ if (!(aux_stack_bottom_addr =
+ LLVMBuildBitCast(comp_ctx->builder, aux_stack_bottom_addr,
+ INT32_PTR_TYPE, "aux_stack_bottom_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (!(func_ctx->aux_stack_bottom =
+ LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, aux_stack_bottom_addr,
+ "aux_stack_bottom"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+create_native_symbol(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef native_symbol_offset = I32_EIGHT, native_symbol_addr;
+
+ if (!(native_symbol_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env,
+ &native_symbol_offset, 1, "native_symbol_addr"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+
+ if (!(func_ctx->native_symbol =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ native_symbol_addr, "native_symbol_tmp"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+
+ if (!(func_ctx->native_symbol =
+ LLVMBuildBitCast(comp_ctx->builder, func_ctx->native_symbol,
+ comp_ctx->exec_env_type, "native_symbol"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+create_local_variables(AOTCompData *comp_data, AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, AOTFunc *func)
+{
+ AOTFuncType *aot_func_type = comp_data->func_types[func->func_type_index];
+ char local_name[32];
+ uint32 i, j = 1;
+
+ 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.");
+ return false;
+ }
+ if (!LLVMBuildStore(comp_ctx->builder, LLVMGetParam(func_ctx->func, j),
+ func_ctx->locals[i])) {
+ aot_set_last_error("llvm build store failed.");
+ return false;
+ }
+ }
+
+ 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.");
+ return false;
+ }
+ 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;
+ case VALUE_TYPE_V128:
+ local_value = V128_i64x2_ZERO;
+ break;
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+ local_value = REF_NULL;
+ 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.");
+ return false;
+ }
+ }
+
+ if (comp_ctx->enable_stack_bound_check
+ || comp_ctx->enable_stack_estimation) {
+ if (aot_func_type->param_count + func->local_count > 0) {
+ func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
+ + func->local_count - 1];
+ if (!(func_ctx->last_alloca =
+ LLVMBuildBitCast(comp_ctx->builder, func_ctx->last_alloca,
+ INT8_PTR_TYPE, "stack_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed.");
+ return false;
+ }
+ }
+ else {
+ if (!(func_ctx->last_alloca = LLVMBuildAlloca(
+ comp_ctx->builder, INT8_TYPE, "stack_ptr"))) {
+ aot_set_last_error("llvm build alloca failed.");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool
+create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef int8_ptr_type, uint32 func_index)
+{
+ LLVMValueRef offset, mem_info_base;
+ uint32 memory_count;
+ WASMModule *module = comp_ctx->comp_data->wasm_module;
+ WASMFunction *func = module->functions[func_index];
+ LLVMTypeRef bound_check_type;
+ bool mem_space_unchanged =
+ (!func->has_op_memory_grow && !func->has_op_func_call)
+ || (!module->possible_memory_grow);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ bool is_shared_memory;
+#endif
+
+ func_ctx->mem_space_unchanged = mem_space_unchanged;
+
+ memory_count = module->memory_count + module->import_memory_count;
+ /* If the module dosen't have memory, reserve
+ one mem_info space with empty content */
+ if (memory_count == 0)
+ memory_count = 1;
+
+ if (!(func_ctx->mem_info =
+ wasm_runtime_malloc(sizeof(AOTMemInfo) * memory_count))) {
+ return false;
+ }
+ memset(func_ctx->mem_info, 0, sizeof(AOTMemInfo));
+
+ /* Currently we only create memory info for memory 0 */
+ /* Load memory base address */
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ is_shared_memory =
+ comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false;
+ if (is_shared_memory) {
+ LLVMValueRef shared_mem_addr;
+ offset = I32_CONST(offsetof(AOTModuleInstance, memories));
+ if (!offset) {
+ aot_set_last_error("create llvm const failed.");
+ return false;
+ }
+
+ /* aot_inst->memories */
+ if (!(shared_mem_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
+ "shared_mem_addr_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(shared_mem_addr =
+ LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr,
+ int8_ptr_type, "shared_mem_addr_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ /* aot_inst->memories[0] */
+ if (!(shared_mem_addr =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ shared_mem_addr, "shared_mem_addr"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ if (!(shared_mem_addr =
+ LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr,
+ int8_ptr_type, "shared_mem_addr_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (!(shared_mem_addr =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ shared_mem_addr, "shared_mem_addr"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ /* memories[0]->memory_data */
+ offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1,
+ "mem_base_addr_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ /* memories[0]->cur_page_count */
+ offset = I32_CONST(offsetof(AOTMemoryInstance, cur_page_count));
+ if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ shared_mem_addr, &offset, 1,
+ "mem_cur_page_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ /* memories[0]->memory_data_size */
+ offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data_size));
+ if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1,
+ "mem_data_size_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ }
+ else
+#endif
+ {
+ uint32 offset_of_global_table_data;
+
+ if (comp_ctx->is_jit_mode)
+ offset_of_global_table_data =
+ offsetof(WASMModuleInstance, global_table_data);
+ else
+ offset_of_global_table_data =
+ offsetof(AOTModuleInstance, global_table_data);
+
+ offset = I32_CONST(offset_of_global_table_data
+ + offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
+ "mem_base_addr_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ offset = I32_CONST(offset_of_global_table_data
+ + offsetof(AOTMemoryInstance, cur_page_count));
+ if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+ func_ctx->aot_inst, &offset, 1,
+ "mem_cur_page_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ offset = I32_CONST(offset_of_global_table_data
+ + offsetof(AOTMemoryInstance, memory_data_size));
+ if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
+ "mem_data_size_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ }
+ /* Store mem info base address before cast */
+ mem_info_base = func_ctx->mem_info[0].mem_base_addr;
+
+ if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr,
+ int8_ptr_type, "mem_base_addr_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_cur_page_count_addr,
+ INT32_PTR_TYPE, "mem_cur_page_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr,
+ 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_info[0].mem_base_addr = LLVMBuildLoad2(
+ comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
+ LLVMBuildLoad2(comp_ctx->builder, I32_TYPE,
+ func_ctx->mem_info[0].mem_cur_page_count_addr,
+ "mem_cur_page_count"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildLoad2(
+ comp_ctx->builder, I32_TYPE,
+ func_ctx->mem_info[0].mem_data_size_addr, "mem_data_size"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ else if (is_shared_memory) {
+ /* The base address for shared memory will never changed,
+ we can load the value here */
+ if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildLoad2(
+ comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->mem_info[0].mem_base_addr, "mem_base_addr"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ }
+#endif
+
+ bound_check_type = (comp_ctx->pointer_size == sizeof(uint64))
+ ? INT64_PTR_TYPE
+ : INT32_PTR_TYPE;
+
+ /* Load memory bound check constants */
+ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte)
+ - offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_bound_check_1byte =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
+ &offset, 1, "bound_check_1byte_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_1byte,
+ bound_check_type, "bound_check_1byte_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (mem_space_unchanged) {
+ if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildLoad2(
+ comp_ctx->builder,
+ (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
+ : I32_TYPE,
+ func_ctx->mem_info[0].mem_bound_check_1byte,
+ "bound_check_1byte"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ }
+
+ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes)
+ - offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_bound_check_2bytes =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
+ &offset, 1, "bound_check_2bytes_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_2bytes,
+ bound_check_type, "bound_check_2bytes_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (mem_space_unchanged) {
+ if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildLoad2(
+ comp_ctx->builder,
+ (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
+ : I32_TYPE,
+ func_ctx->mem_info[0].mem_bound_check_2bytes,
+ "bound_check_2bytes"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ }
+
+ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes)
+ - offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_bound_check_4bytes =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
+ &offset, 1, "bound_check_4bytes_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_4bytes,
+ bound_check_type, "bound_check_4bytes_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (mem_space_unchanged) {
+ if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildLoad2(
+ comp_ctx->builder,
+ (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
+ : I32_TYPE,
+ func_ctx->mem_info[0].mem_bound_check_4bytes,
+ "bound_check_4bytes"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ }
+
+ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes)
+ - offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_bound_check_8bytes =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
+ &offset, 1, "bound_check_8bytes_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_8bytes,
+ bound_check_type, "bound_check_8bytes_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (mem_space_unchanged) {
+ if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildLoad2(
+ comp_ctx->builder,
+ (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
+ : I32_TYPE,
+ func_ctx->mem_info[0].mem_bound_check_8bytes,
+ "bound_check_8bytes"))) {
+ aot_set_last_error("llvm build load failed");
+ return false;
+ }
+ }
+
+ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes)
+ - offsetof(AOTMemoryInstance, memory_data));
+ if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1,
+ "bound_check_16bytes_offset"))) {
+ aot_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildBitCast(
+ comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_16bytes,
+ bound_check_type, "bound_check_16bytes_ptr"))) {
+ aot_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ if (mem_space_unchanged) {
+ if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildLoad2(
+ comp_ctx->builder,
+ (comp_ctx->pointer_size == sizeof(uint64)) ? I64_TYPE
+ : I32_TYPE,
+ func_ctx->mem_info[0].mem_bound_check_16bytes,
+ "bound_check_16bytes"))) {
+ aot_set_last_error("llvm build load 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 =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
+ &offset, 1, "cur_exception");
+ if (!func_ctx->cur_exception) {
+ aot_set_last_error("llvm build in bounds gep 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));
+ func_type_indexes_ptr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, 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 =
+ LLVMBuildLoad2(comp_ctx->builder, INT32_PTR_TYPE,
+ 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;
+}
+
+static bool
+create_func_ptrs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef offset;
+
+ offset = I32_CONST(offsetof(AOTModuleInstance, func_ptrs));
+ func_ctx->func_ptrs =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
+ &offset, 1, "func_ptrs_offset");
+ if (!func_ctx->func_ptrs) {
+ aot_set_last_error("llvm build in bounds gep failed.");
+ return false;
+ }
+ func_ctx->func_ptrs =
+ LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs,
+ comp_ctx->exec_env_type, "func_ptrs_tmp");
+ if (!func_ctx->func_ptrs) {
+ aot_set_last_error("llvm build bit cast failed.");
+ return false;
+ }
+
+ func_ctx->func_ptrs = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ func_ctx->func_ptrs, "func_ptrs_ptr");
+ if (!func_ctx->func_ptrs) {
+ aot_set_last_error("llvm build load failed.");
+ return false;
+ }
+
+ func_ctx->func_ptrs =
+ LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs,
+ comp_ctx->exec_env_type, "func_ptrs");
+ if (!func_ctx->func_ptrs) {
+ aot_set_last_error("llvm build bit cast 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];
+ WASMModule *module = comp_ctx->comp_data->wasm_module;
+ WASMFunction *wasm_func = module->functions[func_index];
+ AOTBlock *aot_block;
+ LLVMTypeRef int8_ptr_type;
+ LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr;
+ uint64 size;
+
+ /* 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_runtime_malloc((uint32)size))) {
+ aot_set_last_error("allocate memory failed.");
+ return NULL;
+ }
+
+ memset(func_ctx, 0, (uint32)size);
+ func_ctx->aot_func = func;
+
+ func_ctx->module = comp_ctx->module;
+
+ /* Add LLVM function */
+ if (!(func_ctx->func =
+ aot_add_llvm_func(comp_ctx, func_ctx->module, aot_func_type,
+ func_index, &func_ctx->func_type))) {
+ goto fail;
+ }
+
+ /* Create function's first AOTBlock */
+ if (!(aot_block =
+ aot_create_func_block(comp_ctx, func_ctx, func, aot_func_type))) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ func_ctx->debug_func = dwarf_gen_func_info(comp_ctx, func_ctx);
+#endif
+
+ 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, 0);
+
+ /* Get aot inst address, the layout of exec_env is:
+ exec_env->next, exec_env->prev, exec_env->module_inst, and argv_buf */
+ if (!(aot_inst_addr = LLVMBuildInBoundsGEP2(
+ comp_ctx->builder, OPQ_PTR_TYPE, 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 = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+ aot_inst_addr, "aot_inst"))) {
+ aot_set_last_error("llvm build load failed");
+ goto fail;
+ }
+
+ /* Get argv buffer address */
+ if (wasm_func->has_op_func_call && !create_argv_buf(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ /* Get native stack boundary address */
+ if (comp_ctx->enable_stack_bound_check
+ && !create_native_stack_bound(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+ if (comp_ctx->enable_stack_estimation
+ && !create_native_stack_top_min(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ /* Get auxiliary stack info */
+ if (wasm_func->has_op_set_global_aux_stack
+ && !create_aux_stack_info(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ /* Get native symbol list */
+ if (comp_ctx->is_indirect_mode
+ && !create_native_symbol(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ /* Create local variables */
+ if (!create_local_variables(comp_data, comp_ctx, func_ctx, func)) {
+ goto fail;
+ }
+
+ if (!(int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) {
+ aot_set_last_error("llvm add pointer type failed.");
+ goto fail;
+ }
+
+ /* Create base addr, end addr, data size of mem, heap */
+ if (wasm_func->has_memory_operations
+ && !create_memory_info(comp_ctx, func_ctx, int8_ptr_type, func_index)) {
+ goto fail;
+ }
+
+ /* Load current exception */
+ if (!create_cur_exception(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ /* Load function type indexes */
+ if (wasm_func->has_op_call_indirect
+ && !create_func_type_indexes(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ /* Load function pointers */
+ if (!create_func_ptrs(comp_ctx, func_ctx)) {
+ goto fail;
+ }
+
+ return func_ctx;
+
+fail:
+ if (func_ctx->mem_info)
+ wasm_runtime_free(func_ctx->mem_info);
+ aot_block_stack_destroy(&func_ctx->block_stack);
+ wasm_runtime_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]->mem_info)
+ wasm_runtime_free(func_ctxes[i]->mem_info);
+ aot_block_stack_destroy(&func_ctxes[i]->block_stack);
+ aot_checked_addr_list_destroy(func_ctxes[i]);
+ wasm_runtime_free(func_ctxes[i]);
+ }
+ wasm_runtime_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_runtime_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);
+
+ if (basic_types->int8_ptr_type) {
+ basic_types->int8_pptr_type =
+ LLVMPointerType(basic_types->int8_ptr_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->i8x16_vec_type = LLVMVectorType(basic_types->int8_type, 16);
+ basic_types->i16x8_vec_type = LLVMVectorType(basic_types->int16_type, 8);
+ basic_types->i32x4_vec_type = LLVMVectorType(basic_types->int32_type, 4);
+ basic_types->i64x2_vec_type = LLVMVectorType(basic_types->int64_type, 2);
+ basic_types->f32x4_vec_type = LLVMVectorType(basic_types->float32_type, 4);
+ basic_types->f64x2_vec_type = LLVMVectorType(basic_types->float64_type, 2);
+
+ basic_types->v128_type = basic_types->i64x2_vec_type;
+ basic_types->v128_ptr_type = LLVMPointerType(basic_types->v128_type, 0);
+
+ basic_types->i1x2_vec_type = LLVMVectorType(basic_types->int1_type, 2);
+
+ basic_types->funcref_type = LLVMInt32TypeInContext(context);
+ basic_types->externref_type = LLVMInt32TypeInContext(context);
+
+ return (basic_types->int8_ptr_type && basic_types->int8_pptr_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->i8x16_vec_type
+ && basic_types->i16x8_vec_type && basic_types->i32x4_vec_type
+ && basic_types->i64x2_vec_type && basic_types->f32x4_vec_type
+ && basic_types->f64x2_vec_type && basic_types->i1x2_vec_type
+ && basic_types->meta_data_type && basic_types->funcref_type
+ && basic_types->externref_type)
+ ? true
+ : false;
+}
+
+static bool
+aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
+{
+#define CREATE_I1_CONST(name, value) \
+ if (!(consts->i1_##name = \
+ LLVMConstInt(comp_ctx->basic_types.int1_type, value, true))) \
+ return false;
+
+ CREATE_I1_CONST(zero, 0)
+ CREATE_I1_CONST(one, 1)
+#undef CREATE_I1_CONST
+
+ if (!(consts->i8_zero = I8_CONST(0)))
+ return false;
+
+ if (!(consts->f32_zero = F32_CONST(0)))
+ return false;
+
+ if (!(consts->f64_zero = F64_CONST(0)))
+ return false;
+
+#define CREATE_I32_CONST(name, value) \
+ if (!(consts->i32_##name = LLVMConstInt(I32_TYPE, value, true))) \
+ return false;
+
+ CREATE_I32_CONST(min, (uint32)INT32_MIN)
+ CREATE_I32_CONST(neg_one, (uint32)-1)
+ CREATE_I32_CONST(zero, 0)
+ CREATE_I32_CONST(one, 1)
+ CREATE_I32_CONST(two, 2)
+ CREATE_I32_CONST(three, 3)
+ CREATE_I32_CONST(four, 4)
+ CREATE_I32_CONST(five, 5)
+ CREATE_I32_CONST(six, 6)
+ CREATE_I32_CONST(seven, 7)
+ CREATE_I32_CONST(eight, 8)
+ CREATE_I32_CONST(nine, 9)
+ CREATE_I32_CONST(ten, 10)
+ CREATE_I32_CONST(eleven, 11)
+ CREATE_I32_CONST(twelve, 12)
+ CREATE_I32_CONST(thirteen, 13)
+ CREATE_I32_CONST(fourteen, 14)
+ CREATE_I32_CONST(fifteen, 15)
+ CREATE_I32_CONST(31, 31)
+ CREATE_I32_CONST(32, 32)
+#undef CREATE_I32_CONST
+
+#define CREATE_I64_CONST(name, value) \
+ if (!(consts->i64_##name = LLVMConstInt(I64_TYPE, value, true))) \
+ return false;
+
+ CREATE_I64_CONST(min, (uint64)INT64_MIN)
+ CREATE_I64_CONST(neg_one, (uint64)-1)
+ CREATE_I64_CONST(zero, 0)
+ CREATE_I64_CONST(63, 63)
+ CREATE_I64_CONST(64, 64)
+#undef CREATE_I64_CONST
+
+#define CREATE_V128_CONST(name, type) \
+ if (!(consts->name##_vec_zero = LLVMConstNull(type))) \
+ return false; \
+ if (!(consts->name##_undef = LLVMGetUndef(type))) \
+ return false;
+
+ CREATE_V128_CONST(i8x16, V128_i8x16_TYPE)
+ CREATE_V128_CONST(i16x8, V128_i16x8_TYPE)
+ CREATE_V128_CONST(i32x4, V128_i32x4_TYPE)
+ CREATE_V128_CONST(i64x2, V128_i64x2_TYPE)
+ CREATE_V128_CONST(f32x4, V128_f32x4_TYPE)
+ CREATE_V128_CONST(f64x2, V128_f64x2_TYPE)
+#undef CREATE_V128_CONST
+
+#define CREATE_VEC_ZERO_MASK(slot) \
+ { \
+ LLVMTypeRef type = LLVMVectorType(I32_TYPE, slot); \
+ if (!type || !(consts->i32x##slot##_zero = LLVMConstNull(type))) \
+ return false; \
+ }
+
+ CREATE_VEC_ZERO_MASK(16)
+ CREATE_VEC_ZERO_MASK(8)
+ CREATE_VEC_ZERO_MASK(4)
+ CREATE_VEC_ZERO_MASK(2)
+#undef CREATE_VEC_ZERO_MASK
+
+ return true;
+}
+
+typedef struct ArchItem {
+ char *arch;
+ bool support_eb;
+} ArchItem;
+
+/* clang-format off */
+static ArchItem valid_archs[] = {
+ { "x86_64", false },
+ { "i386", false },
+ { "xtensa", false },
+ { "mips", true },
+ { "mipsel", false },
+ { "aarch64v8", false },
+ { "aarch64v8.1", false },
+ { "aarch64v8.2", false },
+ { "aarch64v8.3", false },
+ { "aarch64v8.4", false },
+ { "aarch64v8.5", false },
+ { "aarch64_bev8", false }, /* big endian */
+ { "aarch64_bev8.1", false },
+ { "aarch64_bev8.2", false },
+ { "aarch64_bev8.3", false },
+ { "aarch64_bev8.4", false },
+ { "aarch64_bev8.5", false },
+ { "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 },
+ { "riscv32", true },
+ { "riscv64", true },
+ { "arc", true }
+};
+
+static const char *valid_abis[] = {
+ "gnu",
+ "eabi",
+ "gnueabihf",
+ "msvc",
+ "ilp32",
+ "ilp32f",
+ "ilp32d",
+ "lp64",
+ "lp64f",
+ "lp64d"
+};
+/* clang-format on */
+
+static void
+print_supported_targets()
+{
+ uint32 i;
+ os_printf("Supported targets:\n");
+ for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) {
+ os_printf("%s ", valid_archs[i].arch);
+ if (valid_archs[i].support_eb)
+ os_printf("%seb ", valid_archs[i].arch);
+ }
+ os_printf("\n");
+}
+
+static void
+print_supported_abis()
+{
+ uint32 i;
+ os_printf("Supported ABI: ");
+ for (i = 0; i < sizeof(valid_abis) / sizeof(const char *); i++)
+ os_printf("%s ", valid_abis[i]);
+ os_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
+aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err)
+{
+ char *err_msg = LLVMGetErrorMessage(err);
+ aot_set_last_error_v("%s: %s", string, err_msg);
+ LLVMDisposeErrorMessage(err_msg);
+}
+
+static bool
+create_target_machine_detect_host(AOTCompContext *comp_ctx)
+{
+ char *triple = NULL;
+ LLVMTargetRef target = NULL;
+ char *err_msg = NULL;
+ char *cpu = NULL;
+ char *features = NULL;
+ LLVMTargetMachineRef target_machine = NULL;
+ bool ret = false;
+
+ triple = LLVMGetDefaultTargetTriple();
+ if (triple == NULL) {
+ aot_set_last_error("failed to get default target triple.");
+ goto fail;
+ }
+
+ if (LLVMGetTargetFromTriple(triple, &target, &err_msg) != 0) {
+ aot_set_last_error_v("failed to get llvm target from triple %s.",
+ err_msg);
+ LLVMDisposeMessage(err_msg);
+ goto fail;
+ }
+
+ if (!LLVMTargetHasJIT(target)) {
+ aot_set_last_error("unspported JIT on this platform.");
+ goto fail;
+ }
+
+ cpu = LLVMGetHostCPUName();
+ if (cpu == NULL) {
+ aot_set_last_error("failed to get host cpu information.");
+ goto fail;
+ }
+
+ features = LLVMGetHostCPUFeatures();
+ if (features == NULL) {
+ aot_set_last_error("failed to get host cpu features.");
+ goto fail;
+ }
+
+ LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n", cpu,
+ features);
+
+ /* create TargetMachine */
+ target_machine = LLVMCreateTargetMachine(
+ target, triple, cpu, features, LLVMCodeGenLevelDefault,
+ LLVMRelocDefault, LLVMCodeModelJITDefault);
+ if (!target_machine) {
+ aot_set_last_error("failed to create target machine.");
+ goto fail;
+ }
+ comp_ctx->target_machine = target_machine;
+
+ /* Save target arch */
+ get_target_arch_from_triple(triple, comp_ctx->target_arch,
+ sizeof(comp_ctx->target_arch));
+ ret = true;
+
+fail:
+ if (triple)
+ LLVMDisposeMessage(triple);
+ if (features)
+ LLVMDisposeMessage(features);
+ if (cpu)
+ LLVMDisposeMessage(cpu);
+
+ return ret;
+}
+
+static bool
+orc_jit_create(AOTCompContext *comp_ctx)
+{
+ LLVMErrorRef err;
+ LLVMOrcLLLazyJITRef orc_jit = NULL;
+ LLVMOrcLLLazyJITBuilderRef builder = NULL;
+ LLVMOrcJITTargetMachineBuilderRef jtmb = NULL;
+ bool ret = false;
+
+ builder = LLVMOrcCreateLLLazyJITBuilder();
+ if (builder == NULL) {
+ aot_set_last_error("failed to create jit builder.");
+ goto fail;
+ }
+
+ err = LLVMOrcJITTargetMachineBuilderDetectHost(&jtmb);
+ if (err != LLVMErrorSuccess) {
+ aot_handle_llvm_errmsg(
+ "quited to create LLVMOrcJITTargetMachineBuilderRef", err);
+ goto fail;
+ }
+
+ LLVMOrcLLLazyJITBuilderSetNumCompileThreads(
+ builder, WASM_ORC_JIT_COMPILE_THREAD_NUM);
+
+ /* Ownership transfer:
+ LLVMOrcJITTargetMachineBuilderRef -> LLVMOrcLLJITBuilderRef */
+ LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(builder, jtmb);
+ err = LLVMOrcCreateLLLazyJIT(&orc_jit, builder);
+ if (err != LLVMErrorSuccess) {
+ aot_handle_llvm_errmsg("quited to create llvm lazy orcjit instance",
+ err);
+ goto fail;
+ }
+ /* Ownership transfer: LLVMOrcLLJITBuilderRef -> LLVMOrcLLJITRef */
+ builder = NULL;
+
+ /* Ownership transfer: local -> AOTCompContext */
+ comp_ctx->orc_jit = orc_jit;
+ orc_jit = NULL;
+ ret = true;
+
+fail:
+ if (builder)
+ LLVMOrcDisposeLLLazyJITBuilder(builder);
+
+ if (orc_jit)
+ LLVMOrcDisposeLLLazyJIT(orc_jit);
+ return ret;
+}
+
+bool
+aot_compiler_init(void)
+{
+ /* Initialize LLVM environment */
+
+ LLVMInitializeCore(LLVMGetGlobalPassRegistry());
+#if WASM_ENABLE_WAMR_COMPILER != 0
+ /* Init environment of all targets for AOT compiler */
+ LLVMInitializeAllTargetInfos();
+ LLVMInitializeAllTargets();
+ LLVMInitializeAllTargetMCs();
+ LLVMInitializeAllAsmPrinters();
+#else
+ /* Init environment of native for JIT compiler */
+ LLVMInitializeNativeTarget();
+ LLVMInitializeNativeTarget();
+ LLVMInitializeNativeAsmPrinter();
+#endif
+
+ return true;
+}
+
+void
+aot_compiler_destroy(void)
+{
+ LLVMShutdown();
+}
+
+AOTCompContext *
+aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
+{
+ AOTCompContext *comp_ctx, *ret = NULL;
+ LLVMTargetRef target;
+ char *triple = NULL, *triple_norm, *arch, *abi;
+ char *cpu = NULL, *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 }, features_buf[128] = { 0 };
+ uint32 opt_level, size_level, i;
+ LLVMCodeModel code_model;
+ LLVMTargetDataRef target_data_ref;
+
+ /* Allocate memory */
+ if (!(comp_ctx = wasm_runtime_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 */
+ comp_ctx->orc_thread_safe_context = LLVMOrcCreateNewThreadSafeContext();
+ if (!comp_ctx->orc_thread_safe_context) {
+ aot_set_last_error("create LLVM ThreadSafeContext failed.");
+ goto fail;
+ }
+
+ /* Get a reference to the underlying LLVMContext, note:
+ different from non LAZY JIT mode, no need to dispose this context,
+ if will be disposed when the thread safe context is disposed */
+ if (!(comp_ctx->context = LLVMOrcThreadSafeContextGetContext(
+ comp_ctx->orc_thread_safe_context))) {
+ aot_set_last_error("get context from LLVM ThreadSafeContext failed.");
+ goto fail;
+ }
+
+ if (!(comp_ctx->builder = LLVMCreateBuilderInContext(comp_ctx->context))) {
+ aot_set_last_error("create LLVM builder failed.");
+ goto fail;
+ }
+
+ /* Create LLVM module for each jit function, note:
+ different from non ORC JIT mode, no need to dispose it,
+ it will be disposed when the thread safe context is disposed */
+ if (!(comp_ctx->module = LLVMModuleCreateWithNameInContext(
+ "WASM Module", comp_ctx->context))) {
+ aot_set_last_error("create LLVM module failed.");
+ goto fail;
+ }
+
+ if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+ if (!(comp_ctx->debug_builder = LLVMCreateDIBuilder(comp_ctx->module))) {
+ aot_set_last_error("create LLVM Debug Infor builder failed.");
+ goto fail;
+ }
+
+ LLVMAddModuleFlag(
+ comp_ctx->module, LLVMModuleFlagBehaviorWarning, "Debug Info Version",
+ strlen("Debug Info Version"),
+ LLVMValueAsMetadata(LLVMConstInt(LLVMInt32Type(), 3, false)));
+
+ comp_ctx->debug_file = dwarf_gen_file_info(comp_ctx);
+ if (!comp_ctx->debug_file) {
+ aot_set_last_error("dwarf generate file info failed");
+ goto fail;
+ }
+ comp_ctx->debug_comp_unit = dwarf_gen_comp_unit_info(comp_ctx);
+ if (!comp_ctx->debug_comp_unit) {
+ aot_set_last_error("dwarf generate compile unit info failed");
+ goto fail;
+ }
+#endif
+
+ if (option->enable_bulk_memory)
+ comp_ctx->enable_bulk_memory = true;
+
+ if (option->enable_thread_mgr)
+ comp_ctx->enable_thread_mgr = true;
+
+ if (option->enable_tail_call)
+ comp_ctx->enable_tail_call = true;
+
+ if (option->enable_ref_types)
+ comp_ctx->enable_ref_types = true;
+
+ if (option->enable_aux_stack_frame)
+ comp_ctx->enable_aux_stack_frame = true;
+
+ if (option->enable_aux_stack_check)
+ comp_ctx->enable_aux_stack_check = true;
+
+ if (option->is_indirect_mode)
+ comp_ctx->is_indirect_mode = true;
+
+ if (option->disable_llvm_intrinsics)
+ comp_ctx->disable_llvm_intrinsics = true;
+
+ if (option->disable_llvm_lto)
+ comp_ctx->disable_llvm_lto = true;
+
+ if (option->enable_stack_estimation)
+ comp_ctx->enable_stack_estimation = true;
+
+ comp_ctx->opt_level = option->opt_level;
+ comp_ctx->size_level = option->size_level;
+
+ comp_ctx->custom_sections_wp = option->custom_sections;
+ comp_ctx->custom_sections_count = option->custom_sections_count;
+
+ if (option->is_jit_mode) {
+ comp_ctx->is_jit_mode = true;
+
+ /* Create TargetMachine */
+ if (!create_target_machine_detect_host(comp_ctx))
+ goto fail;
+
+ /* Create LLJIT Instance */
+ if (!orc_jit_create(comp_ctx))
+ goto fail;
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ comp_ctx->enable_bound_check = true;
+ /* Always enable stack boundary check if `bounds-checks`
+ is enabled */
+ comp_ctx->enable_stack_bound_check = true;
+#else
+ comp_ctx->enable_bound_check = false;
+ /* When `bounds-checks` is disabled, we set stack boundary
+ check status according to the compilation option */
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK != 0
+ /* Native stack overflow check with hardware trap is disabled,
+ we need to enable the check by LLVM JITed/AOTed code */
+ comp_ctx->enable_stack_bound_check = true;
+#else
+ /* Native stack overflow check with hardware trap is enabled,
+ no need to enable the check by LLVM JITed/AOTed code */
+ comp_ctx->enable_stack_bound_check = false;
+#endif
+#endif
+ }
+ 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;
+ size_level = option->size_level;
+
+ /* verify external llc compiler */
+ comp_ctx->external_llc_compiler = getenv("WAMRC_LLC_COMPILER");
+ if (comp_ctx->external_llc_compiler) {
+#if defined(_WIN32) || defined(_WIN32_)
+ comp_ctx->external_llc_compiler = NULL;
+ LOG_WARNING("External LLC compiler not supported on Windows.");
+#else
+ if (access(comp_ctx->external_llc_compiler, X_OK) != 0) {
+ LOG_WARNING("WAMRC_LLC_COMPILER [%s] not found, fallback to "
+ "default pipeline",
+ comp_ctx->external_llc_compiler);
+ comp_ctx->external_llc_compiler = NULL;
+ }
+ else {
+ comp_ctx->llc_compiler_flags = getenv("WAMRC_LLC_FLAGS");
+ LOG_VERBOSE("Using external LLC compiler [%s]",
+ comp_ctx->external_llc_compiler);
+ }
+#endif
+ }
+
+ /* verify external asm compiler */
+ if (!comp_ctx->external_llc_compiler) {
+ comp_ctx->external_asm_compiler = getenv("WAMRC_ASM_COMPILER");
+ if (comp_ctx->external_asm_compiler) {
+#if defined(_WIN32) || defined(_WIN32_)
+ comp_ctx->external_asm_compiler = NULL;
+ LOG_WARNING("External ASM compiler not supported on Windows.");
+#else
+ if (access(comp_ctx->external_asm_compiler, X_OK) != 0) {
+ LOG_WARNING(
+ "WAMRC_ASM_COMPILER [%s] not found, fallback to "
+ "default pipeline",
+ comp_ctx->external_asm_compiler);
+ comp_ctx->external_asm_compiler = NULL;
+ }
+ else {
+ comp_ctx->asm_compiler_flags = getenv("WAMRC_ASM_FLAGS");
+ LOG_VERBOSE("Using external ASM compiler [%s]",
+ comp_ctx->external_asm_compiler);
+ }
+#endif
+ }
+ }
+
+ 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";
+ else if (!strcmp(arch, "aarch64"))
+ arch = "aarch64v8";
+ else if (!strcmp(arch, "aarch64_be"))
+ arch = "aarch64_bev8";
+ }
+
+ /* 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;
+ }
+
+ /* Set default abi for riscv target */
+ if (arch && !strncmp(arch, "riscv", 5) && !abi) {
+ if (!strcmp(arch, "riscv64"))
+ abi = "lp64d";
+ else
+ abi = "ilp32d";
+ }
+
+#if defined(__APPLE__) || defined(__MACH__)
+ if (!abi) {
+ /* On MacOS platform, set abi to "gnu" to avoid generating
+ object file of Mach-O binary format which is unsupported */
+ abi = "gnu";
+ if (!arch && !cpu && !features) {
+ /* Get CPU name of the host machine to avoid checking
+ SIMD capability failed */
+ if (!(cpu = cpu_new = LLVMGetHostCPUName())) {
+ aot_set_last_error("llvm get host cpu name failed.");
+ goto fail;
+ }
+ }
+ }
+#endif
+
+ if (abi) {
+ /* Construct target triple: <arch>-<vendor>-<sys>-<abi> */
+ const char *vendor_sys;
+ char *arch1 = arch, default_arch[32] = { 0 };
+
+ if (!arch1) {
+ char *default_triple = LLVMGetDefaultTargetTriple();
+
+ if (!default_triple) {
+ aot_set_last_error(
+ "llvm get default target triple failed.");
+ goto fail;
+ }
+
+ vendor_sys = strstr(default_triple, "-");
+ bh_assert(vendor_sys);
+ bh_memcpy_s(default_arch, sizeof(default_arch), default_triple,
+ (uint32)(vendor_sys - default_triple));
+ arch1 = default_arch;
+
+ LLVMDisposeMessage(default_triple);
+ }
+
+ /**
+ * Set <vendor>-<sys> according to abi to generate the object file
+ * with the correct file format which might be different from the
+ * default object file format of the host, e.g., generating AOT file
+ * for Windows/MacOS under Linux host, or generating AOT file for
+ * Linux/MacOS under Windows host.
+ */
+ if (!strcmp(abi, "msvc")) {
+ if (!strcmp(arch1, "i386"))
+ vendor_sys = "-pc-win32-";
+ else
+ vendor_sys = "-pc-windows-";
+ }
+ else {
+ vendor_sys = "-pc-linux-";
+ }
+
+ bh_assert(strlen(arch1) + strlen(vendor_sys) + strlen(abi)
+ < sizeof(triple_buf));
+ bh_memcpy_s(triple_buf, (uint32)sizeof(triple_buf), arch1,
+ (uint32)strlen(arch1));
+ bh_memcpy_s(triple_buf + strlen(arch1),
+ (uint32)(sizeof(triple_buf) - strlen(arch1)),
+ vendor_sys, (uint32)strlen(vendor_sys));
+ bh_memcpy_s(triple_buf + strlen(arch1) + strlen(vendor_sys),
+ (uint32)(sizeof(triple_buf) - strlen(arch1)
+ - strlen(vendor_sys)),
+ abi, (uint32)strlen(abi));
+ triple = triple_buf;
+ }
+ else if (arch) {
+ /* Construct target triple: <arch>-<vendor>-<sys>-<abi> */
+ const char *vendor_sys;
+ char *default_triple = LLVMGetDefaultTargetTriple();
+
+ if (!default_triple) {
+ aot_set_last_error("llvm get default target triple failed.");
+ goto fail;
+ }
+
+ if (strstr(default_triple, "windows")) {
+ vendor_sys = "-pc-windows-";
+ if (!abi)
+ abi = "msvc";
+ }
+ else if (strstr(default_triple, "win32")) {
+ vendor_sys = "-pc-win32-";
+ if (!abi)
+ abi = "msvc";
+ }
+ else {
+ vendor_sys = "-pc-linux-";
+ if (!abi)
+ abi = "gnu";
+ }
+
+ LLVMDisposeMessage(default_triple);
+
+ bh_assert(strlen(arch) + strlen(vendor_sys) + strlen(abi)
+ < sizeof(triple_buf));
+ bh_memcpy_s(triple_buf, (uint32)sizeof(triple_buf), arch,
+ (uint32)strlen(arch));
+ bh_memcpy_s(triple_buf + strlen(arch),
+ (uint32)(sizeof(triple_buf) - strlen(arch)), vendor_sys,
+ (uint32)strlen(vendor_sys));
+ bh_memcpy_s(triple_buf + strlen(arch) + strlen(vendor_sys),
+ (uint32)(sizeof(triple_buf) - strlen(arch)
+ - strlen(vendor_sys)),
+ abi, (uint32)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;
+ }
+
+ /* Add module flag and cpu feature for riscv target */
+ if (arch && !strncmp(arch, "riscv", 5)) {
+ LLVMMetadataRef meta_target_abi;
+
+ if (!(meta_target_abi = LLVMMDStringInContext2(comp_ctx->context,
+ abi, strlen(abi)))) {
+ aot_set_last_error("create metadata string failed.");
+ goto fail;
+ }
+ LLVMAddModuleFlag(comp_ctx->module, LLVMModuleFlagBehaviorError,
+ "target-abi", strlen("target-abi"),
+ meta_target_abi);
+
+ if (!strcmp(abi, "lp64d") || !strcmp(abi, "ilp32d")) {
+ if (features) {
+ snprintf(features_buf, sizeof(features_buf), "%s%s",
+ features, ",+d");
+ features = features_buf;
+ }
+ else
+ features = "+d";
+ }
+ }
+
+ 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));
+
+ if (option->bounds_checks == 1 || option->bounds_checks == 0) {
+ /* Set by user */
+ comp_ctx->enable_bound_check =
+ (option->bounds_checks == 1) ? true : false;
+ }
+ else {
+ /* Unset by user, use default value */
+ if (strstr(comp_ctx->target_arch, "64")
+ && !option->is_sgx_platform) {
+ comp_ctx->enable_bound_check = false;
+ }
+ else {
+ comp_ctx->enable_bound_check = true;
+ }
+ }
+
+ if (comp_ctx->enable_bound_check) {
+ /* Always enable stack boundary check if `bounds-checks`
+ is enabled */
+ comp_ctx->enable_stack_bound_check = true;
+ }
+ else {
+ /* When `bounds-checks` is disabled, we set stack boundary
+ check status according to the input option */
+ comp_ctx->enable_stack_bound_check =
+ (option->stack_bounds_checks == 1) ? true : false;
+ }
+
+ os_printf("Create AoT compiler with:\n");
+ os_printf(" target: %s\n", comp_ctx->target_arch);
+ os_printf(" target cpu: %s\n", cpu);
+ os_printf(" cpu features: %s\n", features);
+ os_printf(" opt level: %d\n", opt_level);
+ os_printf(" size level: %d\n", size_level);
+ switch (option->output_format) {
+ case AOT_LLVMIR_UNOPT_FILE:
+ os_printf(" output format: unoptimized LLVM IR\n");
+ break;
+ case AOT_LLVMIR_OPT_FILE:
+ os_printf(" output format: optimized LLVM IR\n");
+ break;
+ case AOT_FORMAT_FILE:
+ os_printf(" output format: AoT file\n");
+ break;
+ case AOT_OBJECT_FILE:
+ os_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;
+ }
+
+ /* Report error if target isn't arc and hasn't asm backend.
+ For arc target, as it cannot emit to memory buffer of elf file
+ currently, we let it emit to assembly file instead, and then call
+ arc-gcc to compile
+ asm file to elf file, and read elf file to memory buffer. */
+ if (strncmp(comp_ctx->target_arch, "arc", 3)
+ && !LLVMTargetHasAsmBackend(target)) {
+ snprintf(buf, sizeof(buf), "no asm backend for this target (%s).",
+ LLVMGetTargetName(target));
+ aot_set_last_error(buf);
+ goto fail;
+ }
+
+ /* Set code model */
+ if (size_level == 0)
+ code_model = LLVMCodeModelLarge;
+ else if (size_level == 1)
+ code_model = LLVMCodeModelMedium;
+ else if (size_level == 2)
+ code_model = LLVMCodeModelKernel;
+ else
+ code_model = LLVMCodeModelSmall;
+
+ /* Create the target machine */
+ if (!(comp_ctx->target_machine = LLVMCreateTargetMachineWithOpts(
+ target, triple_norm, cpu, features, opt_level,
+ LLVMRelocStatic, code_model, false,
+ option->stack_usage_file))) {
+ aot_set_last_error("create LLVM target machine failed.");
+ goto fail;
+ }
+ }
+
+ if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0
+ && strncmp(comp_ctx->target_arch, "aarch64", 7) != 0) {
+ /* Disable simd if it isn't supported by target arch */
+ option->enable_simd = false;
+ }
+
+ if (option->enable_simd) {
+ char *tmp;
+ bool check_simd_ret;
+
+ comp_ctx->enable_simd = true;
+
+ if (!(tmp = LLVMGetTargetMachineCPU(comp_ctx->target_machine))) {
+ aot_set_last_error("get CPU from Target Machine fail");
+ goto fail;
+ }
+
+ check_simd_ret =
+ aot_check_simd_compatibility(comp_ctx->target_arch, tmp);
+ LLVMDisposeMessage(tmp);
+ if (!check_simd_ret) {
+ aot_set_last_error("SIMD compatibility check failed, "
+ "try adding --cpu=<cpu> to specify a cpu "
+ "or adding --disable-simd to disable SIMD");
+ goto fail;
+ }
+ }
+
+ if (!(target_data_ref =
+ LLVMCreateTargetDataLayout(comp_ctx->target_machine))) {
+ aot_set_last_error("create LLVM target data layout failed.");
+ goto fail;
+ }
+ comp_ctx->pointer_size = LLVMPointerSize(target_data_ref);
+ LLVMDisposeTargetData(target_data_ref);
+
+ comp_ctx->optimize = true;
+ if (option->output_format == AOT_LLVMIR_UNOPT_FILE)
+ comp_ctx->optimize = false;
+
+ /* 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** */
+ comp_ctx->exec_env_type = comp_ctx->basic_types.int8_pptr_type;
+
+ /* 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_data->func_count > 0
+ && !(comp_ctx->func_ctxes =
+ aot_create_func_contexts(comp_data, comp_ctx)))
+ goto fail;
+
+ if (cpu) {
+ uint32 len = (uint32)strlen(cpu) + 1;
+ if (!(comp_ctx->target_cpu = wasm_runtime_malloc(len))) {
+ aot_set_last_error("allocate memory failed");
+ goto fail;
+ }
+ bh_memcpy_s(comp_ctx->target_cpu, len, cpu, len);
+ }
+
+ if (comp_ctx->disable_llvm_intrinsics)
+ aot_intrinsic_fill_capability_flags(comp_ctx);
+
+ 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);
+
+ (void)i;
+ return ret;
+}
+
+void
+aot_destroy_comp_context(AOTCompContext *comp_ctx)
+{
+ if (!comp_ctx)
+ return;
+
+ if (comp_ctx->target_machine)
+ LLVMDisposeTargetMachine(comp_ctx->target_machine);
+
+ if (comp_ctx->builder)
+ LLVMDisposeBuilder(comp_ctx->builder);
+
+ if (comp_ctx->orc_thread_safe_context)
+ LLVMOrcDisposeThreadSafeContext(comp_ctx->orc_thread_safe_context);
+
+ /* Note: don't dispose comp_ctx->context and comp_ctx->module as
+ they are disposed when disposing the thread safe context */
+
+ /* Has to be the last one */
+ if (comp_ctx->orc_jit)
+ LLVMOrcDisposeLLLazyJIT(comp_ctx->orc_jit);
+
+ if (comp_ctx->func_ctxes)
+ aot_destroy_func_contexts(comp_ctx->func_ctxes,
+ comp_ctx->func_ctx_count);
+
+ if (bh_list_length(&comp_ctx->native_symbols) > 0) {
+ AOTNativeSymbol *sym = bh_list_first_elem(&comp_ctx->native_symbols);
+ while (sym) {
+ AOTNativeSymbol *t = bh_list_elem_next(sym);
+ bh_list_remove(&comp_ctx->native_symbols, sym);
+ wasm_runtime_free(sym);
+ sym = t;
+ }
+ }
+
+ if (comp_ctx->target_cpu) {
+ wasm_runtime_free(comp_ctx->target_cpu);
+ }
+
+ wasm_runtime_free(comp_ctx);
+}
+
+static bool
+insert_native_symbol(AOTCompContext *comp_ctx, const char *symbol, int32 idx)
+{
+ AOTNativeSymbol *sym = wasm_runtime_malloc(sizeof(AOTNativeSymbol));
+
+ if (!sym) {
+ aot_set_last_error("alloc native symbol failed.");
+ return false;
+ }
+
+ memset(sym, 0, sizeof(AOTNativeSymbol));
+ bh_assert(strlen(symbol) <= sizeof(sym->symbol));
+ snprintf(sym->symbol, sizeof(sym->symbol), "%s", symbol);
+ sym->index = idx;
+
+ if (BH_LIST_ERROR == bh_list_insert(&comp_ctx->native_symbols, sym)) {
+ wasm_runtime_free(sym);
+ aot_set_last_error("insert native symbol to list failed.");
+ return false;
+ }
+
+ return true;
+}
+
+int32
+aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol)
+{
+ int32 idx = -1;
+ AOTNativeSymbol *sym = NULL;
+
+ sym = bh_list_first_elem(&comp_ctx->native_symbols);
+
+ /* Lookup an existing symobl record */
+
+ while (sym) {
+ if (strcmp(sym->symbol, symbol) == 0) {
+ idx = sym->index;
+ break;
+ }
+ sym = bh_list_elem_next(sym);
+ }
+
+ /* Given symbol is not exist in list, then we alloc a new index for it */
+
+ if (idx < 0) {
+ if (comp_ctx->pointer_size == sizeof(uint32)
+ && (!strncmp(symbol, "f64#", 4) || !strncmp(symbol, "i64#", 4))) {
+ idx = bh_list_length(&comp_ctx->native_symbols);
+ /* Add 4 bytes padding on 32-bit target to make sure that
+ the f64 const is stored on 8-byte aligned address */
+ if (idx & 1) {
+ if (!insert_native_symbol(comp_ctx, "__ignore", idx)) {
+ return -1;
+ }
+ }
+ }
+
+ idx = bh_list_length(&comp_ctx->native_symbols);
+ if (!insert_native_symbol(comp_ctx, symbol, idx)) {
+ return -1;
+ }
+
+ if (comp_ctx->pointer_size == sizeof(uint32)
+ && (!strncmp(symbol, "f64#", 4) || !strncmp(symbol, "i64#", 4))) {
+ /* f64 const occupies 2 pointer slots on 32-bit target */
+ if (!insert_native_symbol(comp_ctx, "__ignore", idx + 1)) {
+ return -1;
+ }
+ }
+ }
+
+ return idx;
+}
+
+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_runtime_free(value);
+ value = p;
+ }
+
+ stack->value_list_head = NULL;
+ stack->value_list_end = NULL;
+}
+
+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);
+ aot_block_destroy(block);
+ block = p;
+ }
+
+ stack->block_list_head = NULL;
+ stack->block_list_end = NULL;
+}
+
+void
+aot_block_destroy(AOTBlock *block)
+{
+ aot_value_stack_destroy(&block->value_stack);
+ if (block->param_types)
+ wasm_runtime_free(block->param_types);
+ if (block->param_phis)
+ wasm_runtime_free(block->param_phis);
+ if (block->else_param_phis)
+ wasm_runtime_free(block->else_param_phis);
+ if (block->result_types)
+ wasm_runtime_free(block->result_types);
+ if (block->result_phis)
+ wasm_runtime_free(block->result_phis);
+ wasm_runtime_free(block);
+}
+
+bool
+aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx,
+ uint32 offset, uint32 bytes)
+{
+ AOTCheckedAddr *node = func_ctx->checked_addr_list;
+
+ if (!(node = wasm_runtime_malloc(sizeof(AOTCheckedAddr)))) {
+ aot_set_last_error("allocate memory failed.");
+ return false;
+ }
+
+ node->local_idx = local_idx;
+ node->offset = offset;
+ node->bytes = bytes;
+
+ node->next = func_ctx->checked_addr_list;
+ func_ctx->checked_addr_list = node;
+ return true;
+}
+
+void
+aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx)
+{
+ AOTCheckedAddr *node = func_ctx->checked_addr_list;
+ AOTCheckedAddr *node_prev = NULL, *node_next;
+
+ while (node) {
+ node_next = node->next;
+
+ if (node->local_idx == local_idx) {
+ if (!node_prev)
+ func_ctx->checked_addr_list = node_next;
+ else
+ node_prev->next = node_next;
+ wasm_runtime_free(node);
+ }
+ else {
+ node_prev = node;
+ }
+
+ node = node_next;
+ }
+}
+
+bool
+aot_checked_addr_list_find(AOTFuncContext *func_ctx, uint32 local_idx,
+ uint32 offset, uint32 bytes)
+{
+ AOTCheckedAddr *node = func_ctx->checked_addr_list;
+
+ while (node) {
+ if (node->local_idx == local_idx && node->offset == offset
+ && node->bytes >= bytes) {
+ return true;
+ }
+ node = node->next;
+ }
+
+ return false;
+}
+
+void
+aot_checked_addr_list_destroy(AOTFuncContext *func_ctx)
+{
+ AOTCheckedAddr *node = func_ctx->checked_addr_list, *node_next;
+
+ while (node) {
+ node_next = node->next;
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+
+ func_ctx->checked_addr_list = NULL;
+}
+
+bool
+aot_build_zero_function_ret(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ AOTFuncType *func_type)
+{
+ LLVMValueRef ret = NULL;
+
+ if (func_type->result_count) {
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+ ret = LLVMBuildRet(comp_ctx->builder, I32_ZERO);
+ break;
+ case VALUE_TYPE_I64:
+ ret = LLVMBuildRet(comp_ctx->builder, I64_ZERO);
+ break;
+ case VALUE_TYPE_F32:
+ ret = LLVMBuildRet(comp_ctx->builder, F32_ZERO);
+ break;
+ case VALUE_TYPE_F64:
+ ret = LLVMBuildRet(comp_ctx->builder, F64_ZERO);
+ break;
+ case VALUE_TYPE_V128:
+ ret =
+ LLVMBuildRet(comp_ctx->builder, LLVM_CONST(i64x2_vec_zero));
+ break;
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+ ret = LLVMBuildRet(comp_ctx->builder, REF_NULL);
+ break;
+ default:
+ bh_assert(0);
+ }
+ }
+ else {
+ ret = LLVMBuildRetVoid(comp_ctx->builder);
+ }
+
+ if (!ret) {
+ aot_set_last_error("llvm build ret failed.");
+ return false;
+ }
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMMetadataRef return_location =
+ dwarf_gen_func_ret_location(comp_ctx, func_ctx);
+ LLVMInstructionSetDebugLoc(ret, return_location);
+#endif
+ return true;
+}
+
+static LLVMValueRef
+__call_llvm_intrinsic(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, const char *name,
+ LLVMTypeRef ret_type, LLVMTypeRef *param_types,
+ int param_count, LLVMValueRef *param_values)
+{
+ LLVMValueRef func, ret;
+ LLVMTypeRef func_type;
+ const char *symname;
+ int32 func_idx;
+
+ if (comp_ctx->disable_llvm_intrinsics
+ && aot_intrinsic_check_capability(comp_ctx, name)) {
+ if (func_ctx == NULL) {
+ aot_set_last_error_v("invalid func_ctx for intrinsic: %s", name);
+ return NULL;
+ }
+
+ if (!(func_type = LLVMFunctionType(ret_type, param_types,
+ (uint32)param_count, false))) {
+ aot_set_last_error("create LLVM intrinsic function type failed.");
+ return NULL;
+ }
+ if (!(func_type = LLVMPointerType(func_type, 0))) {
+ aot_set_last_error(
+ "create LLVM intrinsic function pointer type failed.");
+ return NULL;
+ }
+
+ if (!(symname = aot_intrinsic_get_symbol(name))) {
+ aot_set_last_error_v("runtime intrinsic not implemented: %s\n",
+ name);
+ return NULL;
+ }
+
+ func_idx =
+ aot_get_native_symbol_index((AOTCompContext *)comp_ctx, symname);
+ if (func_idx < 0) {
+ aot_set_last_error_v("get runtime intrinsc index failed: %s\n",
+ name);
+ return NULL;
+ }
+
+ if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+ func_type, func_idx))) {
+ aot_set_last_error_v("get runtime intrinsc failed: %s\n", name);
+ return NULL;
+ }
+ }
+ else {
+ /* Declare llvm intrinsic function if necessary */
+ if (!(func = LLVMGetNamedFunction(func_ctx->module, name))) {
+ if (!(func_type = LLVMFunctionType(ret_type, param_types,
+ (uint32)param_count, false))) {
+ aot_set_last_error(
+ "create LLVM intrinsic function type failed.");
+ return NULL;
+ }
+
+ if (!(func = LLVMAddFunction(func_ctx->module, name, func_type))) {
+ aot_set_last_error("add LLVM intrinsic function failed.");
+ return NULL;
+ }
+ }
+ }
+
+#if LLVM_VERSION_MAJOR >= 14
+ func_type =
+ LLVMFunctionType(ret_type, param_types, (uint32)param_count, false);
+#endif
+
+ /* Call the LLVM intrinsic function */
+ if (!(ret = LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
+ (uint32)param_count, "call"))) {
+ aot_set_last_error("llvm build intrinsic call failed.");
+ return NULL;
+ }
+
+ return ret;
+}
+
+LLVMValueRef
+aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, const char *intrinsic,
+ 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_runtime_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, func_ctx, intrinsic, ret_type,
+ param_types, param_count, param_values);
+
+ wasm_runtime_free(param_values);
+
+ return ret;
+}
+
+LLVMValueRef
+aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, const char *intrinsic,
+ 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_runtime_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, func_ctx, intrinsic, ret_type,
+ param_types, param_count, param_values);
+
+ wasm_runtime_free(param_values);
+
+ return ret;
+}
+
+LLVMValueRef
+aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
+ LLVMTypeRef func_type, int32 index)
+{
+ LLVMValueRef func;
+ LLVMValueRef func_addr;
+
+ if (!(func_addr = I32_CONST(index))) {
+ aot_set_last_error("construct function index failed.");
+ goto fail;
+ }
+
+ if (!(func_addr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE, base,
+ &func_addr, 1, "func_addr"))) {
+ aot_set_last_error("get function addr by index failed.");
+ goto fail;
+ }
+
+ func =
+ LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, func_addr, "func_tmp");
+
+ if (func == NULL) {
+ aot_set_last_error("get function pointer failed.");
+ goto fail;
+ }
+
+ if (!(func =
+ LLVMBuildBitCast(comp_ctx->builder, func, func_type, "func"))) {
+ aot_set_last_error("cast function fialed.");
+ goto fail;
+ }
+
+ return func;
+fail:
+ return NULL;
+}
+
+LLVMValueRef
+aot_load_const_from_table(AOTCompContext *comp_ctx, LLVMValueRef base,
+ const WASMValue *value, uint8 value_type)
+{
+ LLVMValueRef const_index, const_addr, const_value;
+ LLVMTypeRef const_ptr_type, const_type;
+ char buf[128] = { 0 };
+ int32 index;
+
+ switch (value_type) {
+ case VALUE_TYPE_I32:
+ /* Store the raw int bits of i32 const as a hex string */
+ snprintf(buf, sizeof(buf), "i32#%08" PRIX32, value->i32);
+ const_ptr_type = INT32_PTR_TYPE;
+ const_type = I32_TYPE;
+ break;
+ case VALUE_TYPE_I64:
+ /* Store the raw int bits of i64 const as a hex string */
+ snprintf(buf, sizeof(buf), "i64#%016" PRIX64, value->i64);
+ const_ptr_type = INT64_PTR_TYPE;
+ const_type = I64_TYPE;
+ break;
+ case VALUE_TYPE_F32:
+ /* Store the raw int bits of f32 const as a hex string */
+ snprintf(buf, sizeof(buf), "f32#%08" PRIX32, value->i32);
+ const_ptr_type = F32_PTR_TYPE;
+ const_type = F32_TYPE;
+ break;
+ case VALUE_TYPE_F64:
+ /* Store the raw int bits of f64 const as a hex string */
+ snprintf(buf, sizeof(buf), "f64#%016" PRIX64, value->i64);
+ const_ptr_type = F64_PTR_TYPE;
+ const_type = F64_TYPE;
+ break;
+ default:
+ bh_assert(0);
+ return NULL;
+ }
+
+ /* Load f32/f64 const from exec_env->native_symbol[index] */
+
+ index = aot_get_native_symbol_index(comp_ctx, buf);
+ if (index < 0) {
+ return NULL;
+ }
+
+ if (!(const_index = I32_CONST(index))) {
+ aot_set_last_error("construct const index failed.");
+ return NULL;
+ }
+
+ if (!(const_addr =
+ LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE, base,
+ &const_index, 1, "const_addr_tmp"))) {
+ aot_set_last_error("get const addr by index failed.");
+ return NULL;
+ }
+
+ if (!(const_addr = LLVMBuildBitCast(comp_ctx->builder, const_addr,
+ const_ptr_type, "const_addr"))) {
+ aot_set_last_error("cast const fialed.");
+ return NULL;
+ }
+
+ if (!(const_value = LLVMBuildLoad2(comp_ctx->builder, const_type,
+ const_addr, "const_value"))) {
+ aot_set_last_error("load const failed.");
+ return NULL;
+ }
+
+ (void)const_type;
+ return const_value;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.h
new file mode 100644
index 000000000..2a1564019
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm.h
@@ -0,0 +1,526 @@
+/*
+ * 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/Config/llvm-config.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/BitWriter.h"
+#include "llvm-c/Transforms/Utils.h"
+#include "llvm-c/Transforms/Scalar.h"
+#include "llvm-c/Transforms/Vectorize.h"
+#include "llvm-c/Transforms/PassManagerBuilder.h"
+
+#include "llvm-c/Orc.h"
+#include "llvm-c/Error.h"
+#include "llvm-c/Support.h"
+#include "llvm-c/Initialization.h"
+#include "llvm-c/TargetMachine.h"
+#include "llvm-c/LLJIT.h"
+#if WASM_ENABLE_DEBUG_AOT != 0
+#include "llvm-c/DebugInfo.h"
+#endif
+
+#include "aot_orc_extra.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if LLVM_VERSION_MAJOR < 14
+#define LLVMBuildLoad2(builder, type, value, name) \
+ LLVMBuildLoad(builder, value, name)
+
+#define LLVMBuildCall2(builder, type, func, args, num_args, name) \
+ LLVMBuildCall(builder, func, args, num_args, name)
+
+#define LLVMBuildInBoundsGEP2(builder, type, ptr, indices, num_indices, name) \
+ LLVMBuildInBoundsGEP(builder, ptr, indices, num_indices, name)
+#else
+/* Opaque pointer type */
+#define OPQ_PTR_TYPE INT8_PTR_TYPE
+#endif
+
+#ifndef NDEBUG
+#undef DEBUG_PASS
+#undef DUMP_MODULE
+// #define DEBUG_PASS
+// #define DUMP_MODULE
+#else
+#undef DEBUG_PASS
+#undef DUMP_MODULE
+#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;
+ bool is_local;
+ uint32 local_idx;
+} 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;
+ /* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */
+ uint32 label_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;
+
+ /* Param count/types/PHIs of this block */
+ uint32 param_count;
+ uint8 *param_types;
+ LLVMValueRef *param_phis;
+ LLVMValueRef *else_param_phis;
+
+ /* Result count/types/PHIs of this block */
+ uint32 result_count;
+ uint8 *result_types;
+ LLVMValueRef *result_phis;
+} 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 AOTCheckedAddr {
+ struct AOTCheckedAddr *next;
+ uint32 local_idx;
+ uint32 offset;
+ uint32 bytes;
+} AOTCheckedAddr, *AOTCheckedAddrList;
+
+typedef struct AOTMemInfo {
+ LLVMValueRef mem_base_addr;
+ LLVMValueRef mem_data_size_addr;
+ LLVMValueRef mem_cur_page_count_addr;
+ LLVMValueRef mem_bound_check_1byte;
+ LLVMValueRef mem_bound_check_2bytes;
+ LLVMValueRef mem_bound_check_4bytes;
+ LLVMValueRef mem_bound_check_8bytes;
+ LLVMValueRef mem_bound_check_16bytes;
+} AOTMemInfo;
+
+typedef struct AOTFuncContext {
+ AOTFunc *aot_func;
+ LLVMValueRef func;
+ LLVMTypeRef func_type;
+ /* LLVM module for this function, note that in LAZY JIT mode,
+ each aot function belongs to an individual module */
+ LLVMModuleRef module;
+ AOTBlockStack block_stack;
+
+ LLVMValueRef exec_env;
+ LLVMValueRef aot_inst;
+ LLVMValueRef argv_buf;
+ LLVMValueRef native_stack_bound;
+ LLVMValueRef native_stack_top_min_addr;
+ LLVMValueRef aux_stack_bound;
+ LLVMValueRef aux_stack_bottom;
+ LLVMValueRef native_symbol;
+ LLVMValueRef last_alloca;
+ LLVMValueRef func_ptrs;
+
+ AOTMemInfo *mem_info;
+
+ LLVMValueRef cur_exception;
+
+ bool mem_space_unchanged;
+ AOTCheckedAddrList checked_addr_list;
+
+ LLVMBasicBlockRef got_exception_block;
+ LLVMBasicBlockRef func_return_block;
+ LLVMValueRef exception_id_phi;
+ LLVMValueRef func_type_indexes;
+#if WASM_ENABLE_DEBUG_AOT != 0
+ LLVMMetadataRef debug_func;
+#endif
+ 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 int8_pptr_type;
+ LLVMTypeRef int16_ptr_type;
+ LLVMTypeRef int32_ptr_type;
+ LLVMTypeRef int64_ptr_type;
+ LLVMTypeRef float32_ptr_type;
+ LLVMTypeRef float64_ptr_type;
+
+ LLVMTypeRef v128_type;
+ LLVMTypeRef v128_ptr_type;
+ LLVMTypeRef i8x16_vec_type;
+ LLVMTypeRef i16x8_vec_type;
+ LLVMTypeRef i32x4_vec_type;
+ LLVMTypeRef i64x2_vec_type;
+ LLVMTypeRef f32x4_vec_type;
+ LLVMTypeRef f64x2_vec_type;
+
+ LLVMTypeRef i1x2_vec_type;
+
+ LLVMTypeRef meta_data_type;
+
+ LLVMTypeRef funcref_type;
+ LLVMTypeRef externref_type;
+} AOTLLVMTypes;
+
+typedef struct AOTLLVMConsts {
+ LLVMValueRef i1_zero;
+ LLVMValueRef i1_one;
+ LLVMValueRef i8_zero;
+ LLVMValueRef i32_zero;
+ LLVMValueRef i64_zero;
+ LLVMValueRef f32_zero;
+ LLVMValueRef f64_zero;
+ LLVMValueRef i32_one;
+ LLVMValueRef i32_two;
+ LLVMValueRef i32_three;
+ LLVMValueRef i32_four;
+ LLVMValueRef i32_five;
+ LLVMValueRef i32_six;
+ LLVMValueRef i32_seven;
+ LLVMValueRef i32_eight;
+ LLVMValueRef i32_nine;
+ LLVMValueRef i32_ten;
+ LLVMValueRef i32_eleven;
+ LLVMValueRef i32_twelve;
+ LLVMValueRef i32_thirteen;
+ LLVMValueRef i32_fourteen;
+ LLVMValueRef i32_fifteen;
+ 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;
+ LLVMValueRef i8x16_vec_zero;
+ LLVMValueRef i16x8_vec_zero;
+ LLVMValueRef i32x4_vec_zero;
+ LLVMValueRef i64x2_vec_zero;
+ LLVMValueRef f32x4_vec_zero;
+ LLVMValueRef f64x2_vec_zero;
+ LLVMValueRef i8x16_undef;
+ LLVMValueRef i16x8_undef;
+ LLVMValueRef i32x4_undef;
+ LLVMValueRef i64x2_undef;
+ LLVMValueRef f32x4_undef;
+ LLVMValueRef f64x2_undef;
+ LLVMValueRef i32x16_zero;
+ LLVMValueRef i32x8_zero;
+ LLVMValueRef i32x4_zero;
+ LLVMValueRef i32x2_zero;
+} AOTLLVMConsts;
+
+/**
+ * Compiler context
+ */
+typedef struct AOTCompContext {
+ AOTCompData *comp_data;
+
+ /* LLVM variables required to emit LLVM IR */
+ LLVMContextRef context;
+ LLVMBuilderRef builder;
+#if WASM_ENABLE_DEBUG_AOT
+ LLVMDIBuilderRef debug_builder;
+ LLVMMetadataRef debug_file;
+ LLVMMetadataRef debug_comp_unit;
+#endif
+ LLVMTargetMachineRef target_machine;
+ char *target_cpu;
+ char target_arch[16];
+ unsigned pointer_size;
+
+ /* Hardware intrinsic compability flags */
+ uint64 flags[8];
+
+ /* required by JIT */
+ LLVMOrcLLLazyJITRef orc_jit;
+ LLVMOrcThreadSafeContextRef orc_thread_safe_context;
+
+ LLVMModuleRef module;
+
+ bool is_jit_mode;
+
+ /* AOT indirect mode flag & symbol list */
+ bool is_indirect_mode;
+ bh_list native_symbols;
+
+ /* Bulk memory feature */
+ bool enable_bulk_memory;
+
+ /* Bounday Check */
+ bool enable_bound_check;
+
+ /* Native stack bounday Check */
+ bool enable_stack_bound_check;
+
+ /* Native stack usage estimation */
+ bool enable_stack_estimation;
+
+ /* 128-bit SIMD */
+ bool enable_simd;
+
+ /* Auxiliary stack overflow/underflow check */
+ bool enable_aux_stack_check;
+
+ /* Generate auxiliary stack frame */
+ bool enable_aux_stack_frame;
+
+ /* Thread Manager */
+ bool enable_thread_mgr;
+
+ /* Tail Call */
+ bool enable_tail_call;
+
+ /* Reference Types */
+ bool enable_ref_types;
+
+ /* Disable LLVM built-in intrinsics */
+ bool disable_llvm_intrinsics;
+
+ /* Disable LLVM link time optimization */
+ bool disable_llvm_lto;
+
+ /* Whether optimize the JITed code */
+ bool optimize;
+
+ uint32 opt_level;
+ uint32 size_level;
+
+ /* 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 */
+ /* TODO: */
+ AOTFuncContext **func_ctxes;
+ uint32 func_ctx_count;
+ char **custom_sections_wp;
+ uint32 custom_sections_count;
+
+ /* 3rd-party toolchains */
+ /* External llc compiler, if specified, wamrc will emit the llvm-ir file and
+ * invoke the llc compiler to generate object file.
+ * This can be used when we want to benefit from the optimization of other
+ * LLVM based toolchains */
+ const char *external_llc_compiler;
+ const char *llc_compiler_flags;
+ /* External asm compiler, if specified, wamrc will emit the text-based
+ * assembly file (.s) and invoke the llc compiler to generate object file.
+ * This will be useful when the upstream LLVM doesn't support to emit object
+ * file for some architecture (such as arc) */
+ const char *external_asm_compiler;
+ const char *asm_compiler_flags;
+} AOTCompContext;
+
+enum {
+ AOT_FORMAT_FILE,
+ AOT_OBJECT_FILE,
+ AOT_LLVMIR_UNOPT_FILE,
+ AOT_LLVMIR_OPT_FILE,
+};
+
+typedef struct AOTCompOption {
+ bool is_jit_mode;
+ bool is_indirect_mode;
+ char *target_arch;
+ char *target_abi;
+ char *target_cpu;
+ char *cpu_features;
+ bool is_sgx_platform;
+ bool enable_bulk_memory;
+ bool enable_thread_mgr;
+ bool enable_tail_call;
+ bool enable_simd;
+ bool enable_ref_types;
+ bool enable_aux_stack_check;
+ bool enable_aux_stack_frame;
+ bool disable_llvm_intrinsics;
+ bool disable_llvm_lto;
+ bool enable_stack_estimation;
+ uint32 opt_level;
+ uint32 size_level;
+ uint32 output_format;
+ uint32 bounds_checks;
+ uint32 stack_bounds_checks;
+ char **custom_sections;
+ uint32 custom_sections_count;
+ const char *stack_usage_file;
+} AOTCompOption, *aot_comp_option_t;
+
+bool
+aot_compiler_init(void);
+
+void
+aot_compiler_destroy(void);
+
+AOTCompContext *
+aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option);
+
+void
+aot_destroy_comp_context(AOTCompContext *comp_ctx);
+
+int32
+aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol);
+
+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);
+
+bool
+aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx,
+ uint32 offset, uint32 bytes);
+
+void
+aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx);
+
+bool
+aot_checked_addr_list_find(AOTFuncContext *func_ctx, uint32 local_idx,
+ uint32 offset, uint32 bytes);
+
+void
+aot_checked_addr_list_destroy(AOTFuncContext *func_ctx);
+
+bool
+aot_build_zero_function_ret(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ AOTFuncType *func_type);
+
+LLVMValueRef
+aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, const char *intrinsic,
+ LLVMTypeRef ret_type, LLVMTypeRef *param_types,
+ int param_count, ...);
+
+LLVMValueRef
+aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, const char *intrinsic,
+ LLVMTypeRef ret_type, LLVMTypeRef *param_types,
+ int param_count, va_list param_value_list);
+
+LLVMValueRef
+aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
+ LLVMTypeRef func_type, int32 index);
+
+LLVMValueRef
+aot_load_const_from_table(AOTCompContext *comp_ctx, LLVMValueRef base,
+ const WASMValue *value, uint8 value_type);
+
+bool
+aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
+
+void
+aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
+
+void
+aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass);
+
+void
+aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module);
+
+void
+aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _AOT_LLVM_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra.cpp
new file mode 100644
index 000000000..9b77f5e6a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <llvm/Passes/StandardInstrumentations.h>
+#include <llvm/Support/Error.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/Analysis/TargetTransformInfo.h>
+#include <llvm/CodeGen/TargetPassConfig.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/MC/MCSubtargetInfo.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm-c/Core.h>
+#include <llvm-c/ExecutionEngine.h>
+#include <llvm-c/Initialization.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/ExecutionEngine/JITEventListener.h>
+#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
+#include <llvm/ExecutionEngine/Orc/LLJIT.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/IntrinsicInst.h>
+#include <llvm/IR/LegacyPassManager.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Target/CodeGenCWrappers.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm/Target/TargetOptions.h>
+#include <llvm/Transforms/Utils/LowerMemIntrinsics.h>
+#include <llvm/Transforms/Vectorize/LoopVectorize.h>
+#include <llvm/Transforms/Vectorize/LoadStoreVectorizer.h>
+#include <llvm/Transforms/Vectorize/SLPVectorizer.h>
+#include <llvm/Transforms/Scalar/LoopRotation.h>
+#include <llvm/Transforms/Scalar/SimpleLoopUnswitch.h>
+#include <llvm/Transforms/Scalar/LICM.h>
+#include <llvm/Transforms/Scalar/GVN.h>
+#include <llvm/Passes/PassBuilder.h>
+#include <llvm/Analysis/TargetLibraryInfo.h>
+#if LLVM_VERSION_MAJOR >= 12
+#include <llvm/Analysis/AliasAnalysis.h>
+#endif
+
+#include <cstring>
+#include "../aot/aot_runtime.h"
+#include "aot_llvm.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+LLVM_C_EXTERN_C_BEGIN
+
+bool
+aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
+
+void
+aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
+
+void
+aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass);
+
+void
+aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module);
+
+LLVM_C_EXTERN_C_END
+
+ExitOnError ExitOnErr;
+
+class ExpandMemoryOpPass : public llvm::ModulePass
+{
+ public:
+ static char ID;
+
+ ExpandMemoryOpPass()
+ : ModulePass(ID)
+ {}
+
+ bool runOnModule(Module &M) override;
+
+ bool expandMemIntrinsicUses(Function &F);
+ StringRef getPassName() const override
+ {
+ return "Expand memory operation intrinsics";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override
+ {
+ AU.addRequired<TargetTransformInfoWrapperPass>();
+ }
+};
+
+char ExpandMemoryOpPass::ID = 0;
+
+bool
+ExpandMemoryOpPass::expandMemIntrinsicUses(Function &F)
+{
+ Intrinsic::ID ID = F.getIntrinsicID();
+ bool Changed = false;
+
+ for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
+ Instruction *Inst = cast<Instruction>(*I);
+ ++I;
+
+ switch (ID) {
+ case Intrinsic::memcpy:
+ {
+ auto *Memcpy = cast<MemCpyInst>(Inst);
+ Function *ParentFunc = Memcpy->getParent()->getParent();
+ const TargetTransformInfo &TTI =
+ getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
+ *ParentFunc);
+ expandMemCpyAsLoop(Memcpy, TTI);
+ Changed = true;
+ Memcpy->eraseFromParent();
+ break;
+ }
+ case Intrinsic::memmove:
+ {
+ auto *Memmove = cast<MemMoveInst>(Inst);
+ expandMemMoveAsLoop(Memmove);
+ Changed = true;
+ Memmove->eraseFromParent();
+ break;
+ }
+ case Intrinsic::memset:
+ {
+ auto *Memset = cast<MemSetInst>(Inst);
+ expandMemSetAsLoop(Memset);
+ Changed = true;
+ Memset->eraseFromParent();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return Changed;
+}
+
+bool
+ExpandMemoryOpPass::runOnModule(Module &M)
+{
+ bool Changed = false;
+
+ for (Function &F : M) {
+ if (!F.isDeclaration())
+ continue;
+
+ switch (F.getIntrinsicID()) {
+ case Intrinsic::memcpy:
+ case Intrinsic::memmove:
+ case Intrinsic::memset:
+ if (expandMemIntrinsicUses(F))
+ Changed = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return Changed;
+}
+
+void
+aot_add_expand_memory_op_pass(LLVMPassManagerRef pass)
+{
+ reinterpret_cast<legacy::PassManager *>(pass)->add(
+ new ExpandMemoryOpPass());
+}
+
+void
+aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass)
+{
+ reinterpret_cast<legacy::PassManager *>(pass)->add(
+ createSimpleLoopUnswitchLegacyPass());
+}
+
+bool
+aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str)
+{
+#if WASM_ENABLE_SIMD != 0
+ if (!arch_c_str || !cpu_c_str) {
+ return false;
+ }
+
+ llvm::SmallVector<std::string, 1> targetAttributes;
+ llvm::Triple targetTriple(arch_c_str, "", "");
+ auto targetMachine =
+ std::unique_ptr<llvm::TargetMachine>(llvm::EngineBuilder().selectTarget(
+ targetTriple, "", std::string(cpu_c_str), targetAttributes));
+ if (!targetMachine) {
+ return false;
+ }
+
+ const llvm::Triple::ArchType targetArch =
+ targetMachine->getTargetTriple().getArch();
+ const llvm::MCSubtargetInfo *subTargetInfo =
+ targetMachine->getMCSubtargetInfo();
+ if (subTargetInfo == nullptr) {
+ return false;
+ }
+
+ if (targetArch == llvm::Triple::x86_64) {
+ return subTargetInfo->checkFeatures("+sse4.1");
+ }
+ else if (targetArch == llvm::Triple::aarch64) {
+ return subTargetInfo->checkFeatures("+neon");
+ }
+ else {
+ return false;
+ }
+#else
+ (void)arch_c_str;
+ (void)cpu_c_str;
+ return true;
+#endif /* WASM_ENABLE_SIMD */
+}
+
+void
+aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
+{
+ TargetMachine *TM =
+ reinterpret_cast<TargetMachine *>(comp_ctx->target_machine);
+ PipelineTuningOptions PTO;
+ PTO.LoopVectorization = true;
+ PTO.SLPVectorization = true;
+ PTO.LoopUnrolling = true;
+
+#ifdef DEBUG_PASS
+ PassInstrumentationCallbacks PIC;
+ PassBuilder PB(TM, PTO, None, &PIC);
+#else
+#if LLVM_VERSION_MAJOR == 12
+ PassBuilder PB(false, TM, PTO);
+#else
+ PassBuilder PB(TM, PTO);
+#endif
+#endif
+
+ /* Register all the basic analyses with the managers */
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager MAM;
+
+ /* Register the target library analysis directly and give it a
+ customized preset TLI */
+ std::unique_ptr<TargetLibraryInfoImpl> TLII(
+ new TargetLibraryInfoImpl(Triple(TM->getTargetTriple())));
+ FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
+
+ /* Register the AA manager first so that our version is the one used */
+ AAManager AA = PB.buildDefaultAAPipeline();
+ FAM.registerPass([&] { return std::move(AA); });
+
+#ifdef DEBUG_PASS
+ StandardInstrumentations SI(true, false);
+ SI.registerCallbacks(PIC, &FAM);
+#endif
+
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.registerModuleAnalyses(MAM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+#if LLVM_VERSION_MAJOR <= 13
+ PassBuilder::OptimizationLevel OL;
+
+ switch (comp_ctx->opt_level) {
+ case 0:
+ OL = PassBuilder::OptimizationLevel::O0;
+ break;
+ case 1:
+ OL = PassBuilder::OptimizationLevel::O1;
+ break;
+ case 2:
+ OL = PassBuilder::OptimizationLevel::O2;
+ break;
+ case 3:
+ default:
+ OL = PassBuilder::OptimizationLevel::O3;
+ break;
+ }
+#else
+ OptimizationLevel OL;
+
+ switch (comp_ctx->opt_level) {
+ case 0:
+ OL = OptimizationLevel::O0;
+ break;
+ case 1:
+ OL = OptimizationLevel::O1;
+ break;
+ case 2:
+ OL = OptimizationLevel::O2;
+ break;
+ case 3:
+ default:
+ OL = OptimizationLevel::O3;
+ break;
+ }
+#endif /* end of LLVM_VERSION_MAJOR */
+
+ bool disable_llvm_lto = comp_ctx->disable_llvm_lto;
+#if WASM_ENABLE_SPEC_TEST != 0
+ disable_llvm_lto = true;
+#endif
+
+ Module *M = reinterpret_cast<Module *>(module);
+ if (disable_llvm_lto) {
+ for (Function &F : *M) {
+ F.addFnAttr("disable-tail-calls", "true");
+ }
+ }
+
+ ModulePassManager MPM;
+ if (comp_ctx->is_jit_mode) {
+ const char *Passes =
+ "mem2reg,instcombine,simplifycfg,jump-threading,indvars";
+ ExitOnErr(PB.parsePassPipeline(MPM, Passes));
+ }
+ else {
+ FunctionPassManager FPM;
+
+ /* Apply Vectorize related passes for AOT mode */
+ FPM.addPass(LoopVectorizePass());
+ FPM.addPass(SLPVectorizerPass());
+ FPM.addPass(LoadStoreVectorizerPass());
+
+ /*
+ FPM.addPass(createFunctionToLoopPassAdaptor(LICMPass()));
+ FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass()));
+ FPM.addPass(createFunctionToLoopPassAdaptor(SimpleLoopUnswitchPass()));
+ */
+
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+
+ if (!disable_llvm_lto) {
+ /* Apply LTO for AOT mode */
+ if (comp_ctx->comp_data->func_count >= 10)
+ /* Adds the pre-link optimizations if the func count
+ is large enough */
+ MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(OL));
+ else
+ MPM.addPass(PB.buildLTODefaultPipeline(OL, NULL));
+ }
+ else {
+ MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
+ }
+ }
+
+ MPM.run(*M, MAM);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.cpp
new file mode 100644
index 000000000..9bd44bbff
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c)2023 YAMAMOTO Takashi. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <llvm-c/TargetMachine.h>
+#include <llvm/MC/TargetRegistry.h>
+#include <llvm/Target/TargetMachine.h>
+
+#include "bh_assert.h"
+
+#include "aot_llvm_extra2.h"
+
+static llvm::Optional<llvm::Reloc::Model>
+convert(LLVMRelocMode reloc_mode)
+{
+ switch (reloc_mode) {
+ case LLVMRelocDefault:
+ return llvm::None;
+ case LLVMRelocStatic:
+ return llvm::Reloc::Static;
+ case LLVMRelocPIC:
+ return llvm::Reloc::PIC_;
+ case LLVMRelocDynamicNoPic:
+ return llvm::Reloc::DynamicNoPIC;
+ case LLVMRelocROPI:
+ return llvm::Reloc::ROPI;
+ case LLVMRelocRWPI:
+ return llvm::Reloc::RWPI;
+ case LLVMRelocROPI_RWPI:
+ return llvm::Reloc::ROPI_RWPI;
+ }
+ bh_assert(0);
+ return llvm::None;
+}
+
+static llvm::CodeGenOpt::Level
+convert(LLVMCodeGenOptLevel opt_level)
+{
+ switch (opt_level) {
+ case LLVMCodeGenLevelNone:
+ return llvm::CodeGenOpt::None;
+ case LLVMCodeGenLevelLess:
+ return llvm::CodeGenOpt::Less;
+ case LLVMCodeGenLevelDefault:
+ return llvm::CodeGenOpt::Default;
+ case LLVMCodeGenLevelAggressive:
+ return llvm::CodeGenOpt::Aggressive;
+ }
+ bh_assert(0);
+ return llvm::CodeGenOpt::None;
+}
+
+static llvm::Optional<llvm::CodeModel::Model>
+convert(LLVMCodeModel code_model, bool *jit)
+{
+ *jit = false;
+ switch (code_model) {
+ case LLVMCodeModelDefault:
+ return llvm::None;
+ case LLVMCodeModelJITDefault:
+ *jit = true;
+ return llvm::None;
+ case LLVMCodeModelTiny:
+ return llvm::CodeModel::Tiny;
+ case LLVMCodeModelSmall:
+ return llvm::CodeModel::Small;
+ case LLVMCodeModelKernel:
+ return llvm::CodeModel::Kernel;
+ case LLVMCodeModelMedium:
+ return llvm::CodeModel::Medium;
+ case LLVMCodeModelLarge:
+ return llvm::CodeModel::Large;
+ }
+ bh_assert(0);
+ return llvm::None;
+}
+
+LLVMTargetMachineRef
+LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple,
+ const char *cpu, const char *features,
+ LLVMCodeGenOptLevel opt_level,
+ LLVMRelocMode reloc_mode,
+ LLVMCodeModel code_model,
+ bool EmitStackSizeSection,
+ const char *StackUsageOutput)
+{
+ llvm::TargetOptions opts;
+
+ // -fstack-size-section equiv
+ // emit it to ".stack_sizes" section in case of ELF
+ // you can read it with "llvm-readobj --stack-sizes"
+ opts.EmitStackSizeSection = EmitStackSizeSection;
+
+ // -fstack-usage equiv
+ if (StackUsageOutput != NULL) {
+ opts.StackUsageOutput = StackUsageOutput;
+ }
+
+ auto target = reinterpret_cast<llvm::Target *>(ctarget);
+ auto rm = convert(reloc_mode);
+ auto ol = convert(opt_level);
+ bool jit;
+ auto cm = convert(code_model, &jit);
+ auto targetmachine = target->createTargetMachine(triple, cpu, features,
+ opts, rm, cm, ol, jit);
+ return reinterpret_cast<LLVMTargetMachineRef>(targetmachine);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.h
new file mode 100644
index 000000000..ef99622a4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_llvm_extra2.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c)2023 YAMAMOTO Takashi. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <llvm-c/TargetMachine.h>
+
+LLVM_C_EXTERN_C_BEGIN
+LLVMTargetMachineRef
+LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple,
+ const char *cpu, const char *features,
+ LLVMCodeGenOptLevel opt_level,
+ LLVMRelocMode reloc_mode,
+ LLVMCodeModel code_model,
+ bool EmitStackSizeSection,
+ const char *StackUsageOutput);
+LLVM_C_EXTERN_C_END
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.cpp
new file mode 100644
index 000000000..8cf253e94
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "llvm-c/LLJIT.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/OrcEE.h"
+#include "llvm-c/TargetMachine.h"
+
+#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/Support/CBindingWrapping.h"
+
+#include "aot_orc_extra.h"
+#include "aot.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+using GlobalValueSet = std::set<const GlobalValue *>;
+
+namespace llvm {
+namespace orc {
+
+class InProgressLookupState;
+
+class OrcV2CAPIHelper
+{
+ public:
+ using PoolEntry = SymbolStringPtr::PoolEntry;
+ using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr;
+
+ // Move from SymbolStringPtr to PoolEntryPtr (no change in ref count).
+ static PoolEntryPtr moveFromSymbolStringPtr(SymbolStringPtr S)
+ {
+ PoolEntryPtr Result = nullptr;
+ std::swap(Result, S.S);
+ return Result;
+ }
+
+ // Move from a PoolEntryPtr to a SymbolStringPtr (no change in ref count).
+ static SymbolStringPtr moveToSymbolStringPtr(PoolEntryPtr P)
+ {
+ SymbolStringPtr S;
+ S.S = P;
+ return S;
+ }
+
+ // Copy a pool entry to a SymbolStringPtr (increments ref count).
+ static SymbolStringPtr copyToSymbolStringPtr(PoolEntryPtr P)
+ {
+ return SymbolStringPtr(P);
+ }
+
+ static PoolEntryPtr getRawPoolEntryPtr(const SymbolStringPtr &S)
+ {
+ return S.S;
+ }
+
+ static void retainPoolEntry(PoolEntryPtr P)
+ {
+ SymbolStringPtr S(P);
+ S.S = nullptr;
+ }
+
+ static void releasePoolEntry(PoolEntryPtr P)
+ {
+ SymbolStringPtr S;
+ S.S = P;
+ }
+
+ static InProgressLookupState *extractLookupState(LookupState &LS)
+ {
+ return LS.IPLS.release();
+ }
+
+ static void resetLookupState(LookupState &LS, InProgressLookupState *IPLS)
+ {
+ return LS.reset(IPLS);
+ }
+};
+
+} // namespace orc
+} // namespace llvm
+
+// ORC.h
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionSession, LLVMOrcExecutionSessionRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRTransformLayer, LLVMOrcIRTransformLayerRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder,
+ LLVMOrcJITTargetMachineBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectTransformLayer,
+ LLVMOrcObjectTransformLayerRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry,
+ LLVMOrcSymbolStringPoolEntryRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SymbolStringPool, LLVMOrcSymbolStringPoolRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
+
+// LLJIT.h
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLLazyJITBuilder, LLVMOrcLLLazyJITBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLLazyJIT, LLVMOrcLLLazyJITRef)
+
+void
+LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef Builder,
+ unsigned NumCompileThreads)
+{
+ unwrap(Builder)->setNumCompileThreads(NumCompileThreads);
+}
+
+LLVMOrcLLLazyJITBuilderRef
+LLVMOrcCreateLLLazyJITBuilder(void)
+{
+ return wrap(new LLLazyJITBuilder());
+}
+
+void
+LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder)
+{
+ delete unwrap(Builder);
+}
+
+void
+LLVMOrcLLLazyJITBuilderSetNumCompileThreads(LLVMOrcLLLazyJITBuilderRef Builder,
+ unsigned NumCompileThreads)
+{
+ unwrap(Builder)->setNumCompileThreads(NumCompileThreads);
+}
+
+void
+LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
+ LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMP)
+{
+ unwrap(Builder)->setJITTargetMachineBuilder(*unwrap(JTMP));
+ /* Destroy the JTMP, similar to
+ LLVMOrcLLJITBuilderSetJITTargetMachineBuilder */
+ LLVMOrcDisposeJITTargetMachineBuilder(JTMP);
+}
+
+static Optional<CompileOnDemandLayer::GlobalValueSet>
+PartitionFunction(GlobalValueSet Requested)
+{
+ std::vector<const GlobalValue *> GVsToAdd;
+
+ for (auto *GV : Requested) {
+ if (isa<Function>(GV) && GV->hasName()) {
+ auto &F = cast<Function>(*GV); /* get LLVM function */
+ const Module *M = F.getParent(); /* get LLVM module */
+ auto GVName = GV->getName(); /* get the function name */
+ const char *gvname = GVName.begin(); /* C function name */
+ const char *wrapper;
+ uint32 prefix_len = strlen(AOT_FUNC_PREFIX);
+
+ /* Convert "aot_func#n_wrapper" to "aot_func#n" */
+ if (strstr(gvname, AOT_FUNC_PREFIX)
+ && (wrapper = strstr(gvname + prefix_len, "_wrapper"))) {
+ char buf[16] = { 0 };
+ char func_name[64];
+ int group_stride, i, j;
+
+ bh_assert(wrapper - (gvname + prefix_len) > 0);
+ /* Get AOT function index */
+ bh_memcpy_s(buf, (uint32)sizeof(buf), gvname + prefix_len,
+ (uint32)(wrapper - (gvname + prefix_len)));
+ i = atoi(buf);
+
+ group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+
+ /* Compile some functions each time */
+ for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+ snprintf(func_name, sizeof(func_name), "%s%d",
+ AOT_FUNC_PREFIX, i + j * group_stride);
+ Function *F1 = M->getFunction(func_name);
+ if (F1) {
+ LOG_DEBUG("compile func %s", func_name);
+ GVsToAdd.push_back(cast<GlobalValue>(F1));
+ }
+ }
+ }
+ }
+ }
+
+ for (auto *GV : GVsToAdd) {
+ Requested.insert(GV);
+ }
+
+ return Requested;
+}
+
+LLVMErrorRef
+LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
+ LLVMOrcLLLazyJITBuilderRef Builder)
+{
+ assert(Result && "Result can not be null");
+
+ if (!Builder)
+ Builder = LLVMOrcCreateLLLazyJITBuilder();
+
+ auto J = unwrap(Builder)->create();
+ LLVMOrcDisposeLLLazyJITBuilder(Builder);
+
+ if (!J) {
+ Result = nullptr;
+ return 0;
+ }
+
+ LLLazyJIT *lazy_jit = J->release();
+ lazy_jit->setPartitionFunction(PartitionFunction);
+
+ *Result = wrap(lazy_jit);
+ return LLVMErrorSuccess;
+}
+
+LLVMErrorRef
+LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J)
+{
+ delete unwrap(J);
+ return LLVMErrorSuccess;
+}
+
+LLVMErrorRef
+LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD,
+ LLVMOrcThreadSafeModuleRef TSM)
+{
+ std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM));
+ return wrap(unwrap(J)->addLazyIRModule(*unwrap(JD), std::move(*TmpTSM)));
+}
+
+LLVMErrorRef
+LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcExecutorAddress *Result,
+ const char *Name)
+{
+ assert(Result && "Result can not be null");
+
+ auto Sym = unwrap(J)->lookup(Name);
+ if (!Sym) {
+ *Result = 0;
+ return wrap(Sym.takeError());
+ }
+
+#if LLVM_VERSION_MAJOR < 15
+ *Result = Sym->getAddress();
+#else
+ *Result = Sym->getValue();
+#endif
+ return LLVMErrorSuccess;
+}
+
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcLLLazyJITMangleAndIntern(LLVMOrcLLLazyJITRef J,
+ const char *UnmangledName)
+{
+ return wrap(OrcV2CAPIHelper::moveFromSymbolStringPtr(
+ unwrap(J)->mangleAndIntern(UnmangledName)));
+}
+
+LLVMOrcJITDylibRef
+LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J)
+{
+ return wrap(&unwrap(J)->getMainJITDylib());
+}
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J)
+{
+ return unwrap(J)->getTargetTriple().str().c_str();
+}
+
+LLVMOrcExecutionSessionRef
+LLVMOrcLLLazyJITGetExecutionSession(LLVMOrcLLLazyJITRef J)
+{
+ return wrap(&unwrap(J)->getExecutionSession());
+}
+
+LLVMOrcIRTransformLayerRef
+LLVMOrcLLLazyJITGetIRTransformLayer(LLVMOrcLLLazyJITRef J)
+{
+ return wrap(&unwrap(J)->getIRTransformLayer());
+}
+
+LLVMOrcObjectTransformLayerRef
+LLVMOrcLLLazyJITGetObjTransformLayer(LLVMOrcLLLazyJITRef J)
+{
+ return wrap(&unwrap(J)->getObjTransformLayer());
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.h
new file mode 100644
index 000000000..e152b8778
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_orc_extra.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_ORC_LAZINESS_H_
+#define _AOT_ORC_LAZINESS_H_
+
+#include "llvm-c/Error.h"
+#include "llvm-c/ExternC.h"
+#include "llvm-c/LLJIT.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/Types.h"
+
+LLVM_C_EXTERN_C_BEGIN
+
+typedef struct LLVMOrcOpaqueLLLazyJITBuilder *LLVMOrcLLLazyJITBuilderRef;
+typedef struct LLVMOrcOpaqueLLLazyJIT *LLVMOrcLLLazyJITRef;
+
+// Extra bindings for LLJIT
+void
+LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef Builder,
+ unsigned NumCompileThreads);
+
+// Extra bindings for LLLazyJIT
+LLVMOrcLLLazyJITBuilderRef
+LLVMOrcCreateLLLazyJITBuilder(void);
+
+void
+LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder);
+
+void
+LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
+ LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMP);
+
+void
+LLVMOrcLLLazyJITBuilderSetNumCompileThreads(LLVMOrcLLLazyJITBuilderRef Builder,
+ unsigned NumCompileThreads);
+
+LLVMErrorRef
+LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
+ LLVMOrcLLLazyJITBuilderRef Builder);
+
+LLVMErrorRef
+LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J);
+
+LLVMErrorRef
+LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD,
+ LLVMOrcThreadSafeModuleRef TSM);
+
+LLVMErrorRef
+LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcExecutorAddress *Result,
+ const char *Name);
+
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcLLLazyJITMangleAndIntern(LLVMOrcLLLazyJITRef J,
+ const char *UnmangledName);
+
+LLVMOrcJITDylibRef
+LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J);
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcExecutionSessionRef
+LLVMOrcLLLazyJITGetExecutionSession(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcIRTransformLayerRef
+LLVMOrcLLLazyJITGetIRTransformLayer(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcObjectTransformLayerRef
+LLVMOrcLLLazyJITGetObjTransformLayer(LLVMOrcLLLazyJITRef J);
+
+LLVM_C_EXTERN_C_END
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.cpp
new file mode 100644
index 000000000..d5a1be85e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.cpp
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "lldb/API/SBBlock.h"
+#include "lldb/API/SBCompileUnit.h"
+#include "lldb/API/SBCommandReturnObject.h"
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API//SBFunction.h"
+#include "lldb/API//SBModule.h"
+#include "lldb/API//SBProcess.h"
+#include "lldb/API//SBStream.h"
+#include "lldb/API//SBSymbol.h"
+#include "lldb/API//SBTarget.h"
+#include "lldb/API//SBThread.h"
+#include "lldb/API/SBDeclaration.h"
+
+#include "dwarf_extractor.h"
+#include "../aot_llvm.h"
+
+#include "bh_log.h"
+#include "../../aot/aot_runtime.h"
+
+#include "llvm/BinaryFormat/Dwarf.h"
+
+using namespace lldb;
+
+typedef struct dwar_extractor {
+ SBDebugger debugger;
+ SBTarget target;
+ SBModule module;
+
+} dwar_extractor;
+
+#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor)
+
+#define TO_EXTACTOR(handle) (dwar_extractor *)(handle)
+
+static bool is_debugger_initialized;
+
+dwar_extractor_handle_t
+create_dwarf_extractor(AOTCompData *comp_data, char *file_name)
+{
+ char *arch = NULL;
+ char *platform = NULL;
+ dwar_extractor *extractor = NULL;
+
+ //__attribute__((constructor)) may be better?
+ if (!is_debugger_initialized) {
+ SBError error = SBDebugger::InitializeWithErrorHandling();
+ if (error.Fail()) {
+ LOG_ERROR("Init Dwarf Debugger failed");
+ return TO_HANDLE(NULL);
+ }
+ is_debugger_initialized = true;
+ }
+
+ SBError error;
+ SBFileSpec exe_file_spec(file_name, true);
+
+ if (!(extractor = new dwar_extractor())) {
+ LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory");
+ goto fail3;
+ }
+
+ extractor->debugger = SBDebugger::Create();
+ if (!extractor->debugger.IsValid()) {
+ LOG_ERROR("Create Dwarf Debugger failed");
+ goto fail2;
+ }
+
+ extractor->target = extractor->debugger.CreateTarget(
+ file_name, arch, platform, false, error);
+
+ if (!error.Success()) {
+ LOG_ERROR("Create Dwarf target failed:%s", error.GetCString());
+ goto fail1;
+ }
+
+ if (!extractor->target.IsValid()) {
+ LOG_ERROR("Create Dwarf target not valid");
+ goto fail1;
+ }
+
+ extractor->module = extractor->target.FindModule(exe_file_spec);
+ comp_data->extractor = TO_HANDLE(extractor);
+
+ return TO_HANDLE(extractor);
+
+fail1:
+ SBDebugger::Destroy(extractor->debugger);
+
+fail2:
+ wasm_runtime_free(extractor);
+
+fail3:
+ return TO_HANDLE(NULL);
+}
+
+void
+destroy_dwarf_extractor(dwar_extractor_handle_t handle)
+{
+ dwar_extractor *extractor = TO_EXTACTOR(handle);
+ if (!extractor)
+ return;
+ extractor->debugger.DeleteTarget(extractor->target);
+ SBDebugger::Destroy(extractor->debugger);
+ delete extractor;
+ SBDebugger::Terminate();
+ is_debugger_initialized = false;
+}
+
+LLVMMetadataRef
+dwarf_gen_file_info(AOTCompContext *comp_ctx)
+{
+ dwar_extractor *extractor;
+ int units_number;
+ LLVMMetadataRef file_info = NULL;
+ const char *file_name;
+ const char *dir_name;
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return NULL;
+
+ units_number = extractor->module.GetNumCompileUnits();
+
+ if (units_number > 0) {
+ SBCompileUnit compile_unit = extractor->module.GetCompileUnitAtIndex(0);
+ auto filespec = compile_unit.GetFileSpec();
+ file_name = filespec.GetFilename();
+ dir_name = filespec.GetDirectory();
+ if (file_name || dir_name) {
+ file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder,
+ file_name, strlen(file_name),
+ dir_name, strlen(dir_name));
+ }
+ }
+ return file_info;
+}
+
+#if 0
+void
+dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx)
+{
+ LLVMMetadataRef file_info = NULL;
+ LLVMMetadataRef comp_unit = NULL;
+ file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder,
+ "ant_runtime_mock.c", 18, ".", 1);
+
+ comp_unit = LLVMDIBuilderCreateCompileUnit(
+ comp_ctx->debug_builder, LLVMDWARFSourceLanguageC, file_info,
+ "ant compiler", 12, 0, NULL, 0, 1, NULL, 0, LLVMDWARFEmissionFull, 0, 0,
+ 0, "/", 1, "", 0);
+
+ LLVMTypeRef ParamTys[] = {
+ LLVMVoidType(),
+ };
+
+ LLVMTypeRef FuncTy = LLVMFunctionType(LLVMVoidType(), ParamTys, 0, 0);
+
+ LLVMValueRef Function =
+ LLVMAddFunction(comp_ctx->module, "ant_runtime_mock", FuncTy);
+
+ LLVMMetadataRef ParamTypes[0];
+ LLVMMetadataRef FunctionTy = LLVMDIBuilderCreateSubroutineType(
+ comp_ctx->debug_builder, file_info, ParamTypes, 0, LLVMDIFlagZero);
+
+ /* 0x0015 is subroutine_type */
+ LLVMMetadataRef ReplaceableFunctionMetadata =
+ LLVMDIBuilderCreateReplaceableCompositeType(
+ comp_ctx->debug_builder, 0x15, "ant_runtime_mock", 16, file_info,
+ file_info, 2, 0, 0, 0, LLVMDIFlagFwdDecl, "", 0);
+
+ LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction(
+ comp_ctx->debug_builder, file_info, "ant_runtime_mock", 16,
+ "ant_runtime_mock", 16, file_info, 2, FunctionTy, true, true, 2, LLVMDIFlagZero,
+ false);
+
+ LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata,
+ FunctionMetadata);
+
+ LLVMSetSubprogram(Function, FunctionMetadata);
+
+ comp_ctx->vm_debug_comp_unit = comp_unit;
+ comp_ctx->vm_debug_file = file_info;
+ comp_ctx->vm_debug_func = FunctionMetadata;
+}
+#endif
+
+LLVMMetadataRef
+dwarf_gen_comp_unit_info(AOTCompContext *comp_ctx)
+{
+ dwar_extractor *extractor;
+ int units_number;
+ LLVMMetadataRef comp_unit = NULL;
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return NULL;
+
+ units_number = extractor->module.GetNumCompileUnits();
+
+ if (units_number > 0) {
+ SBCompileUnit compile_unit = extractor->module.GetCompileUnitAtIndex(0);
+ auto lang_type = compile_unit.GetLanguage();
+
+ comp_unit = LLVMDIBuilderCreateCompileUnit(
+ comp_ctx->debug_builder, LLDB_TO_LLVM_LANG_TYPE(lang_type),
+ comp_ctx->debug_file, "ant compiler", 12, 0, NULL, 0, 1, NULL, 0,
+ LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0);
+ }
+ return comp_unit;
+}
+
+static LLVMDWARFTypeEncoding
+lldb_get_basic_type_encoding(BasicType basic_type)
+{
+ LLVMDWARFTypeEncoding encoding = 0;
+ switch (basic_type) {
+ case eBasicTypeUnsignedChar:
+ encoding = llvm::dwarf::DW_ATE_unsigned_char;
+ break;
+ case eBasicTypeSignedChar:
+ encoding = llvm::dwarf::DW_ATE_signed_char;
+ break;
+ case eBasicTypeUnsignedInt:
+ case eBasicTypeUnsignedLong:
+ case eBasicTypeUnsignedLongLong:
+ case eBasicTypeUnsignedWChar:
+ case eBasicTypeUnsignedInt128:
+ case eBasicTypeUnsignedShort:
+ encoding = llvm::dwarf::DW_ATE_unsigned;
+ break;
+ case eBasicTypeInt:
+ case eBasicTypeLong:
+ case eBasicTypeLongLong:
+ case eBasicTypeWChar:
+ case eBasicTypeInt128:
+ case eBasicTypeShort:
+ encoding = llvm::dwarf::DW_ATE_signed;
+ break;
+ case eBasicTypeBool:
+ encoding = llvm::dwarf::DW_ATE_boolean;
+ break;
+ case eBasicTypeHalf:
+ case eBasicTypeFloat:
+ case eBasicTypeDouble:
+ case eBasicTypeLongDouble:
+ encoding = llvm::dwarf::DW_ATE_float;
+ break;
+ default:
+ break;
+ }
+ return encoding;
+}
+
+static LLVMMetadataRef
+lldb_type_to_type_dbi(AOTCompContext *comp_ctx, SBType &type)
+{
+ LLVMMetadataRef type_info = NULL;
+ BasicType basic_type = type.GetBasicType();
+ uint64_t bit_size = type.GetByteSize() * 8;
+ LLVMDIBuilderRef DIB = comp_ctx->debug_builder;
+ LLVMDWARFTypeEncoding encoding;
+
+ if (basic_type != eBasicTypeInvalid) {
+ encoding = lldb_get_basic_type_encoding(basic_type);
+ type_info = LLVMDIBuilderCreateBasicType(
+ DIB, type.GetName(), strlen(type.GetName()), bit_size, encoding,
+ LLVMDIFlagZero);
+ }
+ else if (type.IsPointerType()) {
+ SBType pointee_type = type.GetPointeeType();
+ type_info = LLVMDIBuilderCreatePointerType(
+ DIB, lldb_type_to_type_dbi(comp_ctx, pointee_type), bit_size, 0, 0,
+ "", 0);
+ }
+
+ return type_info;
+}
+
+static LLVMMetadataRef
+lldb_function_to_function_dbi(AOTCompContext *comp_ctx, SBSymbolContext &sc,
+ AOTFuncContext *func_ctx)
+{
+ SBFunction function(sc.GetFunction());
+ const char *function_name = function.GetName();
+ const char *link_name = function.GetName();
+ SBTypeList function_args = function.GetType().GetFunctionArgumentTypes();
+ SBType return_type = function.GetType().GetFunctionReturnType();
+ const size_t num_function_args = function_args.GetSize();
+ dwar_extractor *extractor;
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return NULL;
+
+ LLVMDIBuilderRef DIB = comp_ctx->debug_builder;
+ LLVMMetadataRef File = comp_ctx->debug_file;
+
+ LLVMMetadataRef ParamTypes[num_function_args + 1];
+
+ ParamTypes[0] = lldb_type_to_type_dbi(comp_ctx, return_type);
+
+ for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args;
+ ++function_arg_idx) {
+ SBType function_arg_type =
+ function_args.GetTypeAtIndex(function_arg_idx);
+
+ if (function_arg_type.IsValid()) {
+ ParamTypes[function_arg_idx + 1] =
+ lldb_type_to_type_dbi(comp_ctx, function_arg_type);
+ }
+ }
+
+ LLVMMetadataRef FunctionTy = LLVMDIBuilderCreateSubroutineType(
+ DIB, File, ParamTypes, num_function_args + 1, LLVMDIFlagZero);
+
+ auto line_entry = sc.GetLineEntry();
+ LLVMMetadataRef ReplaceableFunctionMetadata =
+ LLVMDIBuilderCreateReplaceableCompositeType(
+ DIB, 0x15, function_name, strlen(function_name), File, File,
+ line_entry.GetLine(), 0, 0, 0, LLVMDIFlagFwdDecl, "", 0);
+
+ LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction(
+ DIB, File, function_name, strlen(function_name), link_name,
+ strlen(link_name), File, line_entry.GetLine(), FunctionTy, true, true,
+ line_entry.GetLine(), LLVMDIFlagZero, false);
+
+ LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata,
+ FunctionMetadata);
+
+ LLVMSetSubprogram(func_ctx->func, FunctionMetadata);
+
+ LLVMMetadataRef ParamExpression =
+ LLVMDIBuilderCreateExpression(DIB, NULL, 0);
+ auto variable_list =
+ function.GetBlock().GetVariables(extractor->target, true, false, false);
+ if (num_function_args != variable_list.GetSize()) {
+ LOG_ERROR(
+ "function args number dismatch!:value number=%d, function args=%d",
+ variable_list.GetSize(), num_function_args);
+ }
+
+ LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation(
+ comp_ctx->context, line_entry.GetLine(), 0, FunctionMetadata, NULL);
+
+ // TODO:change to void * or WasmExenv * ?
+ LLVMMetadataRef voidtype =
+ LLVMDIBuilderCreateBasicType(DIB, "void", 4, 0, 0, LLVMDIFlagZero);
+ LLVMMetadataRef voidpionter =
+ LLVMDIBuilderCreatePointerType(DIB, voidtype, 64, 0, 0, "void *", 6);
+
+ LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable(
+ DIB, FunctionMetadata, "exenv", 5, 1,
+ File, // starts form 1, and 1 is exenv,
+ line_entry.GetLine(), voidpionter, true, LLVMDIFlagZero);
+ LLVMValueRef Param = LLVMGetParam(func_ctx->func, 0);
+ LLVMBasicBlockRef block_curr = LLVMGetEntryBasicBlock(func_ctx->func);
+ LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar, ParamExpression,
+ ParamLocation, block_curr);
+
+ for (uint32_t function_arg_idx = 0;
+ function_arg_idx < variable_list.GetSize(); ++function_arg_idx) {
+ SBValue variable(variable_list.GetValueAtIndex(function_arg_idx));
+ if (variable.IsValid()) {
+ SBDeclaration dec(variable.GetDeclaration());
+ auto valtype = variable.GetType();
+ LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation(
+ comp_ctx->context, dec.GetLine(), dec.GetColumn(),
+ FunctionMetadata, NULL);
+ LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable(
+ DIB, FunctionMetadata, variable.GetName(),
+ strlen(variable.GetName()), function_arg_idx + 1 + 1,
+ File, // starts form 1, and 1 is exenv,
+ dec.GetLine(), ParamTypes[function_arg_idx + 1], true,
+ LLVMDIFlagZero);
+ LLVMValueRef Param =
+ LLVMGetParam(func_ctx->func, function_arg_idx + 1);
+ LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar,
+ ParamExpression, ParamLocation,
+ block_curr);
+ }
+ }
+
+ return FunctionMetadata;
+}
+
+LLVMMetadataRef
+dwarf_gen_func_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMMetadataRef func_info = NULL;
+ dwar_extractor *extractor;
+ uint64_t vm_offset;
+ AOTFunc *func = func_ctx->aot_func;
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return NULL;
+
+ // A code address in DWARF for WebAssembly is the offset of an
+ // instruction relative within the Code section of the WebAssembly file.
+ // For this reason Section::GetFileAddress() must return zero for the
+ // Code section. (refert to ObjectFileWasm.cpp)
+ vm_offset = func->code - comp_ctx->comp_data->wasm_module->buf_code;
+
+ auto sbaddr = extractor->target.ResolveFileAddress(vm_offset);
+ SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction
+ | eSymbolContextLineEntry));
+ if (sc.IsValid()) {
+ SBFunction function(sc.GetFunction());
+ if (function.IsValid()) {
+ func_info = lldb_function_to_function_dbi(comp_ctx, sc, func_ctx);
+ }
+ }
+ return func_info;
+}
+
+void
+dwarf_get_func_name(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ char *name, int len)
+{
+ LLVMMetadataRef func_info = NULL;
+ dwar_extractor *extractor;
+ uint64_t vm_offset;
+ AOTFunc *func = func_ctx->aot_func;
+
+ name[0] = '\0';
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return;
+
+ // A code address in DWARF for WebAssembly is the offset of an
+ // instruction relative within the Code section of the WebAssembly file.
+ // For this reason Section::GetFileAddress() must return zero for the
+ // Code section. (refert to ObjectFileWasm.cpp)
+ vm_offset = func->code - comp_ctx->comp_data->wasm_module->buf_code;
+
+ auto sbaddr = extractor->target.ResolveFileAddress(vm_offset);
+ SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction
+ | eSymbolContextLineEntry));
+ if (sc.IsValid()) {
+ SBFunction function(sc.GetFunction());
+ if (function.IsValid()) {
+ bh_strcpy_s(name, len, function.GetName());
+ }
+ }
+}
+
+LLVMMetadataRef
+dwarf_gen_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint64_t vm_offset)
+{
+ LLVMMetadataRef location_info = NULL;
+ dwar_extractor *extractor;
+ AOTFunc *func = func_ctx->aot_func;
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return NULL;
+
+ auto sbaddr = extractor->target.ResolveFileAddress(vm_offset);
+ SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction
+ | eSymbolContextLineEntry));
+ if (sc.IsValid()) {
+ // TODO:need to check if the vm_offset is belong to
+ SBFunction function(sc.GetFunction());
+ if (function.IsValid()) {
+ uint64_t start = func_ctx->aot_func->code
+ - comp_ctx->comp_data->wasm_module->buf_code;
+ uint64_t end = func_ctx->aot_func->code
+ - comp_ctx->comp_data->wasm_module->buf_code
+ + func_ctx->aot_func->code_size;
+ if (function.GetStartAddress().GetOffset() <= start
+ && end <= function.GetEndAddress().GetOffset()) {
+ auto line_entry = sc.GetLineEntry();
+ location_info = LLVMDIBuilderCreateDebugLocation(
+ comp_ctx->context, line_entry.GetLine(),
+ line_entry.GetColumn(), func_ctx->debug_func, NULL);
+ // LOG_VERBOSE("Gen the location l:%d, c:%d at %lx",
+ // line_entry.GetLine(), line_entry.GetColumn(), vm_offset);
+ }
+ else
+ LOG_WARNING("the offset and function is not matched");
+ }
+ }
+ return location_info;
+}
+
+LLVMMetadataRef
+dwarf_gen_func_ret_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMMetadataRef func_info = NULL;
+ dwar_extractor *extractor;
+ uint64_t vm_offset;
+ AOTFunc *func = func_ctx->aot_func;
+ LLVMMetadataRef location_info = NULL;
+
+ if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
+ return NULL;
+
+ // A code address in DWARF for WebAssembly is the offset of an
+ // instruction relative within the Code section of the WebAssembly file.
+ // For this reason Section::GetFileAddress() must return zero for the
+ // Code section. (refert to ObjectFileWasm.cpp)
+ vm_offset = (func->code + func->code_size - 1)
+ - comp_ctx->comp_data->wasm_module->buf_code;
+ location_info = dwarf_gen_location(comp_ctx, func_ctx, vm_offset);
+
+ return location_info;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.h
new file mode 100644
index 000000000..449d4d57c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/debug/dwarf_extractor.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _DWARF_EXTRACTOR_H_
+#define _DWARF_EXTRACTOR_H_
+
+#include "llvm-c/DebugInfo.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int LLDBLangType;
+#define LLDB_TO_LLVM_LANG_TYPE(lldb_lang_type) \
+ (LLVMDWARFSourceLanguage)(((lldb_lang_type) > 0 ? (lldb_lang_type)-1 : 1))
+
+struct AOTCompData;
+typedef struct AOTCompData *aot_comp_data_t;
+typedef void *dwar_extractor_handle_t;
+
+struct AOTCompContext;
+typedef struct AOTCompContext AOTCompContext;
+
+struct AOTFuncContext;
+
+typedef struct AOTFuncContext AOTFuncContext;
+dwar_extractor_handle_t
+create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
+
+LLVMMetadataRef
+dwarf_gen_file_info(AOTCompContext *comp_ctx);
+
+LLVMMetadataRef
+dwarf_gen_comp_unit_info(AOTCompContext *comp_ctx);
+
+LLVMMetadataRef
+dwarf_gen_func_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+LLVMMetadataRef
+dwarf_gen_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint64_t vm_offset);
+
+LLVMMetadataRef
+dwarf_gen_func_ret_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+void
+dwarf_get_func_name(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ char *name, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/iwasm_compl.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/iwasm_compl.cmake
new file mode 100644
index 000000000..4ec460304
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/iwasm_compl.cmake
@@ -0,0 +1,26 @@
+set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${IWASM_COMPL_DIR})
+
+if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
+ file (GLOB_RECURSE source_all
+ ${IWASM_COMPL_DIR}/*.c
+ ${IWASM_COMPL_DIR}/*.cpp)
+else()
+ file (GLOB source_all
+ ${IWASM_COMPL_DIR}/simd/*.c
+ ${IWASM_COMPL_DIR}/simd/*.cpp
+ ${IWASM_COMPL_DIR}/*.c
+ ${IWASM_COMPL_DIR}/*.cpp)
+endif()
+
+set (IWASM_COMPL_SOURCE ${source_all})
+
+# Disalbe rtti to works with LLVM
+
+if (MSVC)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
+else()
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+endif()
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.c
new file mode 100644
index 000000000..4f43c35a9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_access_lanes.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+bool
+aot_compile_simd_shuffle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ const uint8 *frame_ip)
+{
+ LLVMValueRef vec1, vec2, mask, result;
+ uint8 imm[16] = { 0 };
+ int values[16];
+ unsigned i;
+
+ wasm_runtime_read_v128(frame_ip, (uint64 *)imm, (uint64 *)(imm + 8));
+ for (i = 0; i < 16; i++) {
+ values[i] = imm[i];
+ }
+
+ if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
+ "vec2"))) {
+ goto fail;
+ }
+
+ if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
+ "vec1"))) {
+ goto fail;
+ }
+
+ /* build a vector <16 x i32> */
+ if (!(mask = simd_build_const_integer_vector(comp_ctx, I32_TYPE, values,
+ 16))) {
+ goto fail;
+ }
+
+ if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, vec1, vec2, mask,
+ "new_vector"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ goto fail;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+
+fail:
+ return false;
+}
+
+/*TODO: llvm.experimental.vector.*/
+/* shufflevector is not an option, since it requires *mask as a const */
+bool
+aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector, mask, max_lanes, condition, mask_lanes, result;
+ LLVMTypeRef param_types[2];
+
+ if (!(mask = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
+ "mask"))) {
+ goto fail;
+ }
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i8x16_TYPE, "vec"))) {
+ goto fail;
+ }
+
+ /* icmp uge <16 x i8> mask, <16, 16, 16, 16, ...> */
+ if (!(max_lanes = simd_build_splat_const_integer_vector(comp_ctx, INT8_TYPE,
+ 16, 16))) {
+ goto fail;
+ }
+
+ /* if the highest bit of every i8 of mask is 1, means doesn't pick up
+ from vector */
+ /* select <16 x i1> %condition, <16 x i8> <0x80, 0x80, ...>,
+ <16 x i8> %mask */
+ if (!(mask_lanes = simd_build_splat_const_integer_vector(
+ comp_ctx, INT8_TYPE, 0x80, 16))) {
+ goto fail;
+ }
+
+ if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask,
+ max_lanes, "compare_with_16"))) {
+ HANDLE_FAILURE("LLVMBuldICmp");
+ goto fail;
+ }
+
+ if (!(mask = LLVMBuildSelect(comp_ctx->builder, condition, mask_lanes, mask,
+ "mask"))) {
+ HANDLE_FAILURE("LLVMBuildSelect");
+ goto fail;
+ }
+
+ param_types[0] = V128_i8x16_TYPE;
+ param_types[1] = V128_i8x16_TYPE;
+ if (!(result = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE,
+ param_types, 2, vector, mask))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ goto fail;
+ }
+
+ if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
+ "ret"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ PUSH_V128(result);
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector, mask, default_lane_value, condition, max_lane_id,
+ result, idx, id, replace_with_zero, elem, elem_or_zero, undef;
+ uint8 i;
+
+ if (!(mask = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
+ "mask"))) {
+ goto fail;
+ }
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i8x16_TYPE, "vec"))) {
+ goto fail;
+ }
+
+ if (!(undef = LLVMGetUndef(V128_i8x16_TYPE))) {
+ HANDLE_FAILURE("LLVMGetUndef");
+ goto fail;
+ }
+
+ /* icmp uge <16 x i8> mask, <16, 16, 16, 16, ...> */
+ if (!(max_lane_id = simd_build_splat_const_integer_vector(
+ comp_ctx, INT8_TYPE, 16, 16))) {
+ goto fail;
+ }
+
+ if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask,
+ max_lane_id, "out_of_range"))) {
+ HANDLE_FAILURE("LLVMBuldICmp");
+ goto fail;
+ }
+
+ /* if the id is out of range (>=16), set the id as 0 */
+ if (!(default_lane_value = simd_build_splat_const_integer_vector(
+ comp_ctx, INT8_TYPE, 0, 16))) {
+ goto fail;
+ }
+
+ if (!(idx = LLVMBuildSelect(comp_ctx->builder, condition,
+ default_lane_value, mask, "mask"))) {
+ HANDLE_FAILURE("LLVMBuildSelect");
+ goto fail;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (!(id = LLVMBuildExtractElement(comp_ctx->builder, idx, I8_CONST(i),
+ "id"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ goto fail;
+ }
+
+ if (!(replace_with_zero =
+ LLVMBuildExtractElement(comp_ctx->builder, condition,
+ I8_CONST(i), "replace_with_zero"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ goto fail;
+ }
+
+ if (!(elem = LLVMBuildExtractElement(comp_ctx->builder, vector, id,
+ "vector[mask[i]]"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ goto fail;
+ }
+
+ if (!(elem_or_zero =
+ LLVMBuildSelect(comp_ctx->builder, replace_with_zero,
+ I8_CONST(0), elem, "elem_or_zero"))) {
+ HANDLE_FAILURE("LLVMBuildSelect");
+ goto fail;
+ }
+
+ if (!(undef =
+ LLVMBuildInsertElement(comp_ctx->builder, undef, elem_or_zero,
+ I8_CONST(i), "new_vector"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ goto fail;
+ }
+ }
+
+ if (!(result = LLVMBuildBitCast(comp_ctx->builder, undef, V128_i64x2_TYPE,
+ "ret"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ PUSH_V128(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ if (is_target_x86(comp_ctx)) {
+ return aot_compile_simd_swizzle_x86(comp_ctx, func_ctx);
+ }
+ else {
+ return aot_compile_simd_swizzle_common(comp_ctx, func_ctx);
+ }
+}
+
+static bool
+aot_compile_simd_extract(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 lane_id, bool need_extend, bool is_signed,
+ LLVMTypeRef vector_type, LLVMTypeRef result_type,
+ unsigned aot_value_type)
+{
+ LLVMValueRef vector, lane, result;
+
+ if (!(lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ /* bitcast <2 x i64> %0 to <vector_type> */
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec"))) {
+ goto fail;
+ }
+
+ /* extractelement <vector_type> %vector, i8 lane_id*/
+ if (!(result = LLVMBuildExtractElement(comp_ctx->builder, vector, lane,
+ "element"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ goto fail;
+ }
+
+ if (need_extend) {
+ if (is_signed) {
+ /* sext <element_type> %element to <result_type> */
+ if (!(result = LLVMBuildSExt(comp_ctx->builder, result, result_type,
+ "ret"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ goto fail;
+ }
+ }
+ else {
+ /* sext <element_type> %element to <result_type> */
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, result, result_type,
+ "ret"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ goto fail;
+ }
+ }
+ }
+
+ PUSH(result, aot_value_type);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id,
+ bool is_signed)
+{
+ return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, true,
+ is_signed, V128_i8x16_TYPE, I32_TYPE,
+ VALUE_TYPE_I32);
+}
+
+bool
+aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id,
+ bool is_signed)
+{
+ return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, true,
+ is_signed, V128_i16x8_TYPE, I32_TYPE,
+ VALUE_TYPE_I32);
+}
+
+bool
+aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
+ V128_i32x4_TYPE, I32_TYPE, VALUE_TYPE_I32);
+}
+
+bool
+aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
+ V128_i64x2_TYPE, I64_TYPE, VALUE_TYPE_I64);
+}
+
+bool
+aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
+ V128_f32x4_TYPE, F32_TYPE, VALUE_TYPE_F32);
+}
+
+bool
+aot_compile_simd_extract_f64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
+ V128_f64x2_TYPE, F64_TYPE, VALUE_TYPE_F64);
+}
+
+static bool
+aot_compile_simd_replace(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 lane_id, unsigned new_value_type,
+ LLVMTypeRef vector_type, bool need_reduce,
+ LLVMTypeRef element_type)
+{
+ LLVMValueRef vector, new_value, lane, result;
+
+ POP(new_value, new_value_type);
+
+ if (!(lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id))) {
+ goto fail;
+ }
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec"))) {
+ goto fail;
+ }
+
+ /* trunc <new_value_type> to <element_type> */
+ if (need_reduce) {
+ if (!(new_value = LLVMBuildTrunc(comp_ctx->builder, new_value,
+ element_type, "element"))) {
+ HANDLE_FAILURE("LLVMBuildTrunc");
+ goto fail;
+ }
+ }
+
+ /* insertelement <vector_type> %vector, <element_type> %element,
+ i32 lane */
+ if (!(result = LLVMBuildInsertElement(comp_ctx->builder, vector, new_value,
+ lane, "new_vector"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ goto fail;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "reesult");
+
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_replace_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I32,
+ V128_i8x16_TYPE, true, INT8_TYPE);
+}
+
+bool
+aot_compile_simd_replace_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I32,
+ V128_i16x8_TYPE, true, INT16_TYPE);
+}
+
+bool
+aot_compile_simd_replace_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I32,
+ V128_i32x4_TYPE, false, I32_TYPE);
+}
+
+bool
+aot_compile_simd_replace_i64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I64,
+ V128_i64x2_TYPE, false, I64_TYPE);
+}
+
+bool
+aot_compile_simd_replace_f32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_F32,
+ V128_f32x4_TYPE, false, F32_TYPE);
+}
+
+bool
+aot_compile_simd_replace_f64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id)
+{
+ return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_F64,
+ V128_f64x2_TYPE, false, F64_TYPE);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.h
new file mode 100644
index 000000000..75ca71ced
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_access_lanes.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_ACCESS_LANES_H_
+#define _SIMD_ACCESS_LANES_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_shuffle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ const uint8 *frame_ip);
+
+bool
+aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id,
+ bool is_signed);
+
+bool
+aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id,
+ bool is_signed);
+
+bool
+aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_extract_f64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_replace_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_replace_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_replace_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_replace_i64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_replace_f32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_replace_f64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, uint8 lane_id);
+
+bool
+aot_compile_simd_load8_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 lane_id);
+
+bool
+aot_compile_simd_load16_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 lane_id);
+
+bool
+aot_compile_simd_load32_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 lane_id);
+
+bool
+aot_compile_simd_load64_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 lane_id);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_ACCESS_LANES_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.c
new file mode 100644
index 000000000..675ffbcfe
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_bit_shifts.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+enum integer_shift {
+ e_shift_i8x16,
+ e_shift_i16x8,
+ e_shift_i32x4,
+ e_shift_i64x2,
+};
+
+static bool
+simd_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op, enum integer_shift itype)
+{
+ LLVMValueRef vector, offset, result = NULL;
+ LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
+ V128_i32x4_TYPE, V128_i64x2_TYPE };
+ LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE };
+
+ LLVMValueRef undef[] = { LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef),
+ LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef) };
+ LLVMValueRef mask[] = { LLVM_CONST(i8x16_vec_zero),
+ LLVM_CONST(i16x8_vec_zero),
+ LLVM_CONST(i32x4_vec_zero),
+ LLVM_CONST(i64x2_vec_zero) };
+ LLVMValueRef lane_bits[] = {
+ LLVM_CONST(i32_eight),
+ LLVMConstInt(I32_TYPE, 16, true),
+ LLVMConstInt(I32_TYPE, 32, true),
+ LLVMConstInt(I32_TYPE, 64, true),
+ };
+
+ POP_I32(offset);
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ vector_type[itype], "vec"))) {
+ return false;
+ }
+
+ /* offset mod LaneBits */
+ if (!lane_bits[itype]
+ || !(offset = LLVMBuildSRem(comp_ctx->builder, offset, lane_bits[itype],
+ "offset_fix"))) {
+ HANDLE_FAILURE("LLVMBuildSRem");
+ return false;
+ }
+
+ /* change type */
+ if (itype < e_shift_i32x4) {
+ offset = LLVMBuildTrunc(comp_ctx->builder, offset, element_type[itype],
+ "offset_trunc");
+ }
+ else if (itype == e_shift_i64x2) {
+ offset = LLVMBuildZExt(comp_ctx->builder, offset, element_type[itype],
+ "offset_ext");
+ }
+
+ if (!offset) {
+ HANDLE_FAILURE("LLVMBuildZext/LLVMBuildTrunc");
+ return false;
+ }
+
+ /* splat to a vector */
+ if (!(offset =
+ LLVMBuildInsertElement(comp_ctx->builder, undef[itype], offset,
+ I32_ZERO, "offset_vector_base"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ return false;
+ }
+
+ if (!(offset =
+ LLVMBuildShuffleVector(comp_ctx->builder, offset, undef[itype],
+ mask[itype], "offset_vector"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ switch (shift_op) {
+ case INT_SHL:
+ {
+ result = LLVMBuildShl(comp_ctx->builder, vector, offset, "shl");
+ break;
+ }
+ case INT_SHR_S:
+ {
+ result = LLVMBuildAShr(comp_ctx->builder, vector, offset, "ashr");
+ break;
+ }
+ case INT_SHR_U:
+ {
+ result = LLVMBuildLShr(comp_ctx->builder, vector, offset, "lshr");
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ if (!result) {
+ HANDLE_FAILURE("LLVMBuildShl/LLVMBuildLShr/LLVMBuildAShr");
+ goto fail;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op)
+{
+ return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i8x16);
+}
+
+bool
+aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op)
+{
+ return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i16x8);
+}
+
+bool
+aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op)
+{
+ return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i32x4);
+}
+
+bool
+aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op)
+{
+ return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i64x2);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.h
new file mode 100644
index 000000000..06e86cad0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_BIT_SHIFTS_H_
+#define _SIMD_BIT_SHIFTS_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op);
+
+bool
+aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op);
+
+bool
+aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op);
+
+bool
+aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntShift shift_op);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_BIT_SHIFTS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.c
new file mode 100644
index 000000000..67d965426
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_bitmask_extracts.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+enum integer_bitmask_type {
+ e_bitmask_i8x16,
+ e_bitmask_i16x8,
+ e_bitmask_i32x4,
+ e_bitmask_i64x2,
+};
+
+/* TODO: should use a much clever intrinsic */
+static bool
+simd_build_bitmask(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx,
+ enum integer_bitmask_type itype)
+{
+ LLVMValueRef vector, mask, result;
+ uint8 i;
+ LLVMTypeRef vector_ext_type;
+
+ uint32 lanes[] = { 16, 8, 4, 2 };
+ uint32 lane_bits[] = { 8, 16, 32, 64 };
+ LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE };
+ LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
+ V128_i32x4_TYPE, V128_i64x2_TYPE };
+ int32 mask_element[16] = { 0 };
+ const char *intrinsic[] = {
+ "llvm.vector.reduce.or.v16i64",
+ "llvm.vector.reduce.or.v8i64",
+ "llvm.vector.reduce.or.v4i64",
+ "llvm.vector.reduce.or.v2i64",
+ };
+
+ LLVMValueRef ashr_distance;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ vector_type[itype], "vec"))) {
+ goto fail;
+ }
+
+ /* fill every bit in a lange with its sign bit */
+ if (!(ashr_distance = simd_build_splat_const_integer_vector(
+ comp_ctx, element_type[itype], lane_bits[itype] - 1,
+ lanes[itype]))) {
+ goto fail;
+ }
+
+ if (!(vector = LLVMBuildAShr(comp_ctx->builder, vector, ashr_distance,
+ "vec_ashr"))) {
+ HANDLE_FAILURE("LLVMBuildAShr");
+ goto fail;
+ }
+
+ if (!(vector_ext_type = LLVMVectorType(I64_TYPE, lanes[itype]))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ goto fail;
+ }
+
+ if (e_bitmask_i64x2 != itype) {
+ if (!(vector = LLVMBuildSExt(comp_ctx->builder, vector, vector_ext_type,
+ "zext_to_i64"))) {
+ goto fail;
+ }
+ }
+
+ for (i = 0; i < 16; i++) {
+ mask_element[i] = 0x1 << i;
+ }
+
+ if (!(mask = simd_build_const_integer_vector(comp_ctx, I64_TYPE,
+ mask_element, lanes[itype]))) {
+ goto fail;
+ }
+
+ if (!(vector =
+ LLVMBuildAnd(comp_ctx->builder, vector, mask, "mask_bits"))) {
+ HANDLE_FAILURE("LLVMBuildAnd");
+ goto fail;
+ }
+
+ if (!(result =
+ aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype],
+ I64_TYPE, &vector_ext_type, 1, vector))) {
+ goto fail;
+ }
+
+ if (!(result =
+ LLVMBuildTrunc(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
+ HANDLE_FAILURE("LLVMBuildTrunc");
+ goto fail;
+ }
+
+ PUSH_I32(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i8x16);
+}
+
+bool
+aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i16x8);
+}
+
+bool
+aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i32x4);
+}
+
+bool
+aot_compile_simd_i64x2_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i64x2);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.h
new file mode 100644
index 000000000..aac4cc2ce
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_BITMASK_EXTRACTS_H_
+#define _SIMD_BITMASK_EXTRACTS_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i64x2_bitmask(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_BITMASK_EXTRACTS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.c
new file mode 100644
index 000000000..66aef3637
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_bitwise_ops.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+static bool
+v128_bitwise_two_component(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Bitwise bitwise_op)
+{
+ LLVMValueRef vector1, vector2, result;
+
+ POP_V128(vector2);
+ POP_V128(vector1);
+
+ switch (bitwise_op) {
+ case V128_AND:
+ if (!(result = LLVMBuildAnd(comp_ctx->builder, vector1, vector2,
+ "and"))) {
+ HANDLE_FAILURE("LLVMBuildAnd");
+ goto fail;
+ }
+ break;
+ case V128_OR:
+ if (!(result =
+ LLVMBuildOr(comp_ctx->builder, vector1, vector2, "or"))) {
+ HANDLE_FAILURE("LLVMBuildAnd");
+ goto fail;
+ }
+ break;
+ case V128_XOR:
+ if (!(result = LLVMBuildXor(comp_ctx->builder, vector1, vector2,
+ "xor"))) {
+ HANDLE_FAILURE("LLVMBuildAnd");
+ goto fail;
+ }
+ break;
+ case V128_ANDNOT:
+ {
+ /* v128.and(a, v128.not(b)) */
+ if (!(vector2 = LLVMBuildNot(comp_ctx->builder, vector2, "not"))) {
+ HANDLE_FAILURE("LLVMBuildNot");
+ goto fail;
+ }
+
+ if (!(result = LLVMBuildAnd(comp_ctx->builder, vector1, vector2,
+ "and"))) {
+ HANDLE_FAILURE("LLVMBuildAnd");
+ goto fail;
+ }
+
+ break;
+ }
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+
+ PUSH_V128(result);
+ return true;
+fail:
+ return false;
+}
+
+static bool
+v128_bitwise_not(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector, result;
+
+ POP_V128(vector);
+
+ if (!(result = LLVMBuildNot(comp_ctx->builder, vector, "not"))) {
+ HANDLE_FAILURE("LLVMBuildNot");
+ goto fail;
+ }
+
+ PUSH_V128(result);
+ return true;
+fail:
+ return false;
+}
+
+/* v128.or(v128.and(v1, c), v128.and(v2, v128.not(c))) */
+static bool
+v128_bitwise_bitselect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector1, vector2, vector3, result;
+
+ POP_V128(vector3);
+ POP_V128(vector2);
+ POP_V128(vector1);
+
+ if (!(vector1 =
+ LLVMBuildAnd(comp_ctx->builder, vector1, vector3, "a_and_c"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ goto fail;
+ }
+
+ if (!(vector3 = LLVMBuildNot(comp_ctx->builder, vector3, "not_c"))) {
+ HANDLE_FAILURE("LLVMBuildNot");
+ goto fail;
+ }
+
+ if (!(vector2 =
+ LLVMBuildAnd(comp_ctx->builder, vector2, vector3, "b_and_c"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ goto fail;
+ }
+
+ if (!(result =
+ LLVMBuildOr(comp_ctx->builder, vector1, vector2, "a_or_b"))) {
+ HANDLE_FAILURE("LLVMBuildOr");
+ goto fail;
+ }
+
+ PUSH_V128(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, V128Bitwise bitwise_op)
+{
+ switch (bitwise_op) {
+ case V128_AND:
+ case V128_OR:
+ case V128_XOR:
+ case V128_ANDNOT:
+ return v128_bitwise_two_component(comp_ctx, func_ctx, bitwise_op);
+ case V128_NOT:
+ return v128_bitwise_not(comp_ctx, func_ctx);
+ case V128_BITSELECT:
+ return v128_bitwise_bitselect(comp_ctx, func_ctx);
+ default:
+ bh_assert(0);
+ return false;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.h
new file mode 100644
index 000000000..ddf81c0b7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitwise_ops.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_BITWISE_OPS_H_
+#define _SIMD_BITWISE_OPS_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, V128Bitwise bitwise_op);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_BITWISE_OPS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.c
new file mode 100644
index 000000000..4607d680a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_bool_reductions.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+enum integer_all_true {
+ e_int_all_true_v16i8,
+ e_int_all_true_v8i16,
+ e_int_all_true_v4i32,
+ e_int_all_true_v2i64,
+};
+
+static bool
+simd_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ enum integer_all_true itype)
+{
+ LLVMValueRef vector, result;
+ LLVMTypeRef vector_i1_type;
+ LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
+ V128_i32x4_TYPE, V128_i64x2_TYPE };
+ uint32 lanes[] = { 16, 8, 4, 2 };
+ const char *intrinsic[] = {
+ "llvm.vector.reduce.and.v16i1",
+ "llvm.vector.reduce.and.v8i1",
+ "llvm.vector.reduce.and.v4i1",
+ "llvm.vector.reduce.and.v2i1",
+ };
+ LLVMValueRef zero[] = {
+ LLVM_CONST(i8x16_vec_zero),
+ LLVM_CONST(i16x8_vec_zero),
+ LLVM_CONST(i32x4_vec_zero),
+ LLVM_CONST(i64x2_vec_zero),
+ };
+
+ if (!(vector_i1_type = LLVMVectorType(INT1_TYPE, lanes[itype]))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ goto fail;
+ }
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ vector_type[itype], "vector"))) {
+ goto fail;
+ }
+
+ /* compare with zero */
+ if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, vector,
+ zero[itype], "ne_zero"))) {
+ HANDLE_FAILURE("LLVMBuildICmp");
+ goto fail;
+ }
+
+ /* check zero */
+ if (!(result =
+ aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype],
+ INT1_TYPE, &vector_i1_type, 1, result))) {
+ goto fail;
+ }
+
+ if (!(result =
+ LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ goto fail;
+ }
+
+ PUSH_I32(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v16i8);
+}
+
+bool
+aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v8i16);
+}
+
+bool
+aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v4i32);
+}
+
+bool
+aot_compile_simd_i64x2_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v2i64);
+}
+
+bool
+aot_compile_simd_v128_any_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMTypeRef vector_type;
+ LLVMValueRef vector, result;
+
+ if (!(vector_type = LLVMVectorType(INT1_TYPE, 128))) {
+ return false;
+ }
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vector"))) {
+ goto fail;
+ }
+
+ if (!(result = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx, "llvm.vector.reduce.or.v128i1", INT1_TYPE,
+ &vector_type, 1, vector))) {
+ goto fail;
+ }
+
+ if (!(result =
+ LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ goto fail;
+ }
+
+ PUSH_I32(result);
+
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.h
new file mode 100644
index 000000000..649d5a5e2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bool_reductions.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_BOOL_REDUCTIONS_H_
+#define _SIMD_BOOL_REDUCTIONS_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i64x2_all_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_v128_any_true(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_BOOL_REDUCTIONS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.c
new file mode 100644
index 000000000..95bcdfdb0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_common.h"
+
+LLVMValueRef
+simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, LLVMTypeRef vec_type,
+ const char *name)
+{
+ LLVMValueRef number;
+
+ POP_V128(number);
+
+ if (!(number =
+ LLVMBuildBitCast(comp_ctx->builder, number, vec_type, name))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ return number;
+fail:
+ return NULL;
+}
+
+bool
+simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, LLVMValueRef vector,
+ const char *name)
+{
+ if (!(vector = LLVMBuildBitCast(comp_ctx->builder, vector, V128_i64x2_TYPE,
+ name))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ /* push result into the stack */
+ PUSH_V128(vector);
+
+ return true;
+fail:
+ return false;
+}
+
+LLVMValueRef
+simd_lane_id_to_llvm_value(AOTCompContext *comp_ctx, uint8 lane_id)
+{
+ LLVMValueRef lane_indexes[] = {
+ LLVM_CONST(i32_zero), LLVM_CONST(i32_one),
+ LLVM_CONST(i32_two), LLVM_CONST(i32_three),
+ LLVM_CONST(i32_four), LLVM_CONST(i32_five),
+ LLVM_CONST(i32_six), LLVM_CONST(i32_seven),
+ LLVM_CONST(i32_eight), LLVM_CONST(i32_nine),
+ LLVM_CONST(i32_ten), LLVM_CONST(i32_eleven),
+ LLVM_CONST(i32_twelve), LLVM_CONST(i32_thirteen),
+ LLVM_CONST(i32_fourteen), LLVM_CONST(i32_fifteen),
+ };
+
+ return lane_id < 16 ? lane_indexes[lane_id] : NULL;
+}
+
+LLVMValueRef
+simd_build_const_integer_vector(const AOTCompContext *comp_ctx,
+ const LLVMTypeRef element_type,
+ const int *element_value, uint32 length)
+{
+ LLVMValueRef vector = NULL;
+ LLVMValueRef *elements;
+ unsigned i;
+
+ if (!(elements = wasm_runtime_malloc(sizeof(LLVMValueRef) * length))) {
+ return NULL;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (!(elements[i] =
+ LLVMConstInt(element_type, element_value[i], true))) {
+ HANDLE_FAILURE("LLVMConstInst");
+ goto fail;
+ }
+ }
+
+ if (!(vector = LLVMConstVector(elements, length))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ goto fail;
+ }
+
+fail:
+ wasm_runtime_free(elements);
+ return vector;
+}
+
+LLVMValueRef
+simd_build_splat_const_integer_vector(const AOTCompContext *comp_ctx,
+ const LLVMTypeRef element_type,
+ const int64 element_value, uint32 length)
+{
+ LLVMValueRef vector = NULL, element;
+ LLVMValueRef *elements;
+ unsigned i;
+
+ if (!(elements = wasm_runtime_malloc(sizeof(LLVMValueRef) * length))) {
+ return NULL;
+ }
+
+ if (!(element = LLVMConstInt(element_type, element_value, true))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ for (i = 0; i < length; i++) {
+ elements[i] = element;
+ }
+
+ if (!(vector = LLVMConstVector(elements, length))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ goto fail;
+ }
+
+fail:
+ wasm_runtime_free(elements);
+ return vector;
+}
+
+LLVMValueRef
+simd_build_splat_const_float_vector(const AOTCompContext *comp_ctx,
+ const LLVMTypeRef element_type,
+ const float element_value, uint32 length)
+{
+ LLVMValueRef vector = NULL, element;
+ LLVMValueRef *elements;
+ unsigned i;
+
+ if (!(elements = wasm_runtime_malloc(sizeof(LLVMValueRef) * length))) {
+ return NULL;
+ }
+
+ if (!(element = LLVMConstReal(element_type, element_value))) {
+ HANDLE_FAILURE("LLVMConstReal");
+ goto fail;
+ }
+
+ for (i = 0; i < length; i++) {
+ elements[i] = element;
+ }
+
+ if (!(vector = LLVMConstVector(elements, length))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ goto fail;
+ }
+
+fail:
+ wasm_runtime_free(elements);
+ return vector;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.h
new file mode 100644
index 000000000..c7a08dbc7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_common.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_COMMON_H_
+#define _SIMD_COMMON_H_
+
+#include "../aot_compiler.h"
+
+static inline bool
+is_target_x86(AOTCompContext *comp_ctx)
+{
+ return !strncmp(comp_ctx->target_arch, "x86_64", 6)
+ || !strncmp(comp_ctx->target_arch, "i386", 4);
+}
+
+LLVMValueRef
+simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, LLVMTypeRef vec_type,
+ const char *name);
+
+bool
+simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx,
+ const AOTFuncContext *func_ctx, LLVMValueRef vector,
+ const char *name);
+
+LLVMValueRef
+simd_lane_id_to_llvm_value(AOTCompContext *comp_ctx, uint8 lane_id);
+
+LLVMValueRef
+simd_build_const_integer_vector(const AOTCompContext *comp_ctx,
+ const LLVMTypeRef element_type,
+ const int *element_value, uint32 length);
+
+LLVMValueRef
+simd_build_splat_const_integer_vector(const AOTCompContext *comp_ctx,
+ const LLVMTypeRef element_type,
+ const int64 element_value, uint32 length);
+
+LLVMValueRef
+simd_build_splat_const_float_vector(const AOTCompContext *comp_ctx,
+ const LLVMTypeRef element_type,
+ const float element_value, uint32 length);
+#endif /* _SIMD_COMMON_H_ */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.c
new file mode 100644
index 000000000..8a87ab25b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_comparisons.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+static bool
+float_cond_2_predicate(FloatCond cond, LLVMRealPredicate *out)
+{
+ switch (cond) {
+ case FLOAT_EQ:
+ *out = LLVMRealOEQ;
+ break;
+ case FLOAT_NE:
+ *out = LLVMRealUNE;
+ break;
+ case FLOAT_LT:
+ *out = LLVMRealOLT;
+ break;
+ case FLOAT_GT:
+ *out = LLVMRealOGT;
+ break;
+ case FLOAT_LE:
+ *out = LLVMRealOLE;
+ break;
+ case FLOAT_GE:
+ *out = LLVMRealOGE;
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+int_cond_2_predicate(IntCond cond, LLVMIntPredicate *out)
+{
+ switch (cond) {
+ case INT_EQZ:
+ case INT_EQ:
+ *out = LLVMIntEQ;
+ break;
+ case INT_NE:
+ *out = LLVMIntNE;
+ break;
+ case INT_LT_S:
+ *out = LLVMIntSLT;
+ break;
+ case INT_LT_U:
+ *out = LLVMIntULT;
+ break;
+ case INT_GT_S:
+ *out = LLVMIntSGT;
+ break;
+ case INT_GT_U:
+ *out = LLVMIntUGT;
+ break;
+ case INT_LE_S:
+ *out = LLVMIntSLE;
+ break;
+ case INT_LE_U:
+ *out = LLVMIntULE;
+ break;
+ case INT_GE_S:
+ *out = LLVMIntSGE;
+ break;
+ case INT_GE_U:
+ *out = LLVMIntUGE;
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+interger_vector_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ IntCond cond, LLVMTypeRef vector_type)
+{
+ LLVMValueRef vec1, vec2, result;
+ LLVMIntPredicate int_pred;
+
+ if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec2"))) {
+ goto fail;
+ }
+
+ if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec1"))) {
+ goto fail;
+ }
+
+ if (!int_cond_2_predicate(cond, &int_pred)) {
+ HANDLE_FAILURE("int_cond_2_predicate");
+ goto fail;
+ }
+ /* icmp <N x iX> %vec1, %vec2 */
+ if (!(result =
+ LLVMBuildICmp(comp_ctx->builder, int_pred, vec1, vec2, "cmp"))) {
+ HANDLE_FAILURE("LLVMBuildICmp");
+ goto fail;
+ }
+
+ /* sext <N x i1> %result to <N x iX> */
+ if (!(result =
+ LLVMBuildSExt(comp_ctx->builder, result, vector_type, "ext"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ goto fail;
+ }
+
+ /* bitcast <N x iX> %result to <2 x i64> */
+ if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
+ "result"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ PUSH_V128(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond)
+{
+ return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i8x16_TYPE);
+}
+
+bool
+aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond)
+{
+ return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i16x8_TYPE);
+}
+
+bool
+aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond)
+{
+ return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i32x4_TYPE);
+}
+
+bool
+aot_compile_simd_i64x2_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond)
+{
+ return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i64x2_TYPE);
+}
+
+static bool
+float_vector_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatCond cond, LLVMTypeRef vector_type,
+ LLVMTypeRef result_type)
+{
+ LLVMValueRef vec1, vec2, result;
+ LLVMRealPredicate real_pred;
+
+ if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec2"))) {
+ goto fail;
+ }
+
+ if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec1"))) {
+ goto fail;
+ }
+
+ if (!float_cond_2_predicate(cond, &real_pred)) {
+ HANDLE_FAILURE("float_cond_2_predicate");
+ goto fail;
+ }
+ /* fcmp <N x iX> %vec1, %vec2 */
+ if (!(result =
+ LLVMBuildFCmp(comp_ctx->builder, real_pred, vec1, vec2, "cmp"))) {
+ HANDLE_FAILURE("LLVMBuildFCmp");
+ goto fail;
+ }
+
+ /* sext <N x i1> %result to <N x iX> */
+ if (!(result =
+ LLVMBuildSExt(comp_ctx->builder, result, result_type, "ext"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ goto fail;
+ }
+
+ /* bitcast <N x iX> %result to <2 x i64> */
+ if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
+ "result"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ goto fail;
+ }
+
+ PUSH_V128(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, FloatCond cond)
+{
+ return float_vector_compare(comp_ctx, func_ctx, cond, V128_f32x4_TYPE,
+ V128_i32x4_TYPE);
+}
+
+bool
+aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, FloatCond cond)
+{
+ return float_vector_compare(comp_ctx, func_ctx, cond, V128_f64x2_TYPE,
+ V128_i64x2_TYPE);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.h
new file mode 100644
index 000000000..322ebefb2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_comparisons.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_COMPARISONS_H_
+#define _SIMD_COMPARISONS_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond);
+
+bool
+aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond);
+
+bool
+aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond);
+
+bool
+aot_compile_simd_i64x2_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, IntCond cond);
+
+bool
+aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, FloatCond cond);
+
+bool
+aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, FloatCond cond);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_COMPARISONS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.c
new file mode 100644
index 000000000..ceb09e370
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_common.h"
+#include "simd_construct_values.h"
+#include "../aot_emit_exception.h"
+#include "../interpreter/wasm_opcode.h"
+#include "../../aot/aot_runtime.h"
+
+bool
+aot_compile_simd_v128_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ const uint8 *imm_bytes)
+{
+ uint64 imm1, imm2;
+ LLVMValueRef first_long, agg1, second_long, agg2;
+
+ wasm_runtime_read_v128(imm_bytes, &imm1, &imm2);
+
+ /* %agg1 = insertelement <2 x i64> undef, i16 0, i64 ${*imm} */
+ if (!(first_long = I64_CONST(imm1))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ goto fail;
+ }
+
+ if (!(agg1 =
+ LLVMBuildInsertElement(comp_ctx->builder, LLVM_CONST(i64x2_undef),
+ first_long, I32_ZERO, "agg1"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ goto fail;
+ }
+
+ /* %agg2 = insertelement <2 x i64> %agg1, i16 1, i64 ${*(imm + 1)} */
+ if (!(second_long = I64_CONST(imm2))) {
+ HANDLE_FAILURE("LLVMGetUndef");
+ goto fail;
+ }
+
+ if (!(agg2 = LLVMBuildInsertElement(comp_ctx->builder, agg1, second_long,
+ I32_ONE, "agg2"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ goto fail;
+ }
+
+ PUSH_V128(agg2);
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode)
+{
+ uint32 opcode_index = opcode - SIMD_i8x16_splat;
+ LLVMValueRef value = NULL, base, new_vector;
+ LLVMValueRef undefs[] = {
+ LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef),
+ LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef),
+ LLVM_CONST(f32x4_undef), LLVM_CONST(f64x2_undef),
+ };
+ LLVMValueRef masks[] = {
+ LLVM_CONST(i32x16_zero), LLVM_CONST(i32x8_zero), LLVM_CONST(i32x4_zero),
+ LLVM_CONST(i32x2_zero), LLVM_CONST(i32x4_zero), LLVM_CONST(i32x2_zero),
+ };
+
+ switch (opcode) {
+ case SIMD_i8x16_splat:
+ {
+ LLVMValueRef input;
+ POP_I32(input);
+ /* trunc i32 %input to i8 */
+ value =
+ LLVMBuildTrunc(comp_ctx->builder, input, INT8_TYPE, "trunc");
+ break;
+ }
+ case SIMD_i16x8_splat:
+ {
+ LLVMValueRef input;
+ POP_I32(input);
+ /* trunc i32 %input to i16 */
+ value =
+ LLVMBuildTrunc(comp_ctx->builder, input, INT16_TYPE, "trunc");
+ break;
+ }
+ case SIMD_i32x4_splat:
+ {
+ POP_I32(value);
+ break;
+ }
+ case SIMD_i64x2_splat:
+ {
+ POP(value, VALUE_TYPE_I64);
+ break;
+ }
+ case SIMD_f32x4_splat:
+ {
+ POP(value, VALUE_TYPE_F32);
+ break;
+ }
+ case SIMD_f64x2_splat:
+ {
+ POP(value, VALUE_TYPE_F64);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ if (!value) {
+ goto fail;
+ }
+
+ /* insertelement <n x ty> undef, ty %value, i32 0 */
+ if (!(base = LLVMBuildInsertElement(comp_ctx->builder, undefs[opcode_index],
+ value, I32_ZERO, "base"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ goto fail;
+ }
+
+ /* shufflevector <ty1> %base, <ty2> undef, <n x i32> zeroinitializer */
+ if (!(new_vector = LLVMBuildShuffleVector(
+ comp_ctx->builder, base, undefs[opcode_index],
+ masks[opcode_index], "new_vector"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ goto fail;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, new_vector, "result");
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.h
new file mode 100644
index 000000000..8cd50c88b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_construct_values.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_CONSTRUCT_VALUES_H_
+#define _SIMD_CONSTRUCT_VALUES_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_v128_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ const uint8 *imm_bytes);
+
+bool
+aot_compile_simd_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 splat_opcode);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_CONSTRUCT_VALUES_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.c
new file mode 100644
index 000000000..e9d30bfcb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_conversions.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../aot_emit_numberic.h"
+#include "../../aot/aot_runtime.h"
+
+static bool
+simd_integer_narrow_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef in_vector_type, LLVMTypeRef out_vector_type,
+ const char *instrinsic)
+{
+ LLVMValueRef vector1, vector2, result;
+ LLVMTypeRef param_types[2] = { in_vector_type, in_vector_type };
+
+ if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type, "vec2"))
+ || !(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type, "vec1"))) {
+ return false;
+ }
+
+ if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, instrinsic,
+ out_vector_type, param_types, 2,
+ vector1, vector2))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+enum integer_sat_type {
+ e_sat_i16x8 = 0,
+ e_sat_i32x4,
+ e_sat_i64x2,
+ e_sat_i32x8,
+};
+
+static LLVMValueRef
+simd_saturate(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ enum integer_sat_type itype, LLVMValueRef vector,
+ LLVMValueRef min, LLVMValueRef max, bool is_signed)
+{
+ LLVMValueRef result;
+ LLVMTypeRef vector_type;
+
+ LLVMTypeRef param_types[][2] = {
+ { V128_i16x8_TYPE, V128_i16x8_TYPE },
+ { V128_i32x4_TYPE, V128_i32x4_TYPE },
+ { V128_i64x2_TYPE, V128_i64x2_TYPE },
+ { 0 },
+ };
+
+ const char *smin_intrinsic[] = {
+ "llvm.smin.v8i16",
+ "llvm.smin.v4i32",
+ "llvm.smin.v2i64",
+ "llvm.smin.v8i32",
+ };
+
+ const char *umin_intrinsic[] = {
+ "llvm.umin.v8i16",
+ "llvm.umin.v4i32",
+ "llvm.umin.v2i64",
+ "llvm.umin.v8i32",
+ };
+
+ const char *smax_intrinsic[] = {
+ "llvm.smax.v8i16",
+ "llvm.smax.v4i32",
+ "llvm.smax.v2i64",
+ "llvm.smax.v8i32",
+ };
+
+ const char *umax_intrinsic[] = {
+ "llvm.umax.v8i16",
+ "llvm.umax.v4i32",
+ "llvm.umax.v2i64",
+ "llvm.umax.v8i32",
+ };
+
+ if (e_sat_i32x8 == itype) {
+ if (!(vector_type = LLVMVectorType(I32_TYPE, 8))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return NULL;
+ }
+
+ param_types[itype][0] = vector_type;
+ param_types[itype][1] = vector_type;
+ }
+
+ if (!(result = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx,
+ is_signed ? smin_intrinsic[itype] : umin_intrinsic[itype],
+ param_types[itype][0], param_types[itype], 2, vector, max))
+ || !(result = aot_call_llvm_intrinsic(
+ comp_ctx, func_ctx,
+ is_signed ? smax_intrinsic[itype] : umax_intrinsic[itype],
+ param_types[itype][0], param_types[itype], 2, result, min))) {
+ return NULL;
+ }
+
+ return result;
+}
+
+static bool
+simd_integer_narrow_common(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ enum integer_sat_type itype, bool is_signed)
+{
+ LLVMValueRef vec1, vec2, min, max, mask, result;
+ LLVMTypeRef in_vector_type[] = { V128_i16x8_TYPE, V128_i32x4_TYPE,
+ V128_i64x2_TYPE };
+ LLVMTypeRef min_max_type[] = { INT16_TYPE, I32_TYPE, I64_TYPE };
+ LLVMTypeRef trunc_type[3] = { 0 };
+ uint8 length[] = { 8, 4, 2 };
+
+ int64 smin[] = { 0xff80, 0xffFF8000, 0xffFFffFF80000000 };
+ int64 umin[] = { 0x0, 0x0, 0x0 };
+ int64 smax[] = { 0x007f, 0x00007fff, 0x000000007fFFffFF };
+ int64 umax[] = { 0x00ff, 0x0000ffff, 0x00000000ffFFffFF };
+
+ LLVMValueRef mask_element[] = {
+ LLVM_CONST(i32_zero), LLVM_CONST(i32_one),
+ LLVM_CONST(i32_two), LLVM_CONST(i32_three),
+ LLVM_CONST(i32_four), LLVM_CONST(i32_five),
+ LLVM_CONST(i32_six), LLVM_CONST(i32_seven),
+ LLVM_CONST(i32_eight), LLVM_CONST(i32_nine),
+ LLVM_CONST(i32_ten), LLVM_CONST(i32_eleven),
+ LLVM_CONST(i32_twelve), LLVM_CONST(i32_thirteen),
+ LLVM_CONST(i32_fourteen), LLVM_CONST(i32_fifteen),
+ };
+
+ if (!(trunc_type[0] = LLVMVectorType(INT8_TYPE, 8))
+ || !(trunc_type[1] = LLVMVectorType(INT16_TYPE, 4))
+ || !(trunc_type[2] = LLVMVectorType(I32_TYPE, 2))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return false;
+ }
+
+ if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type[itype], "vec2"))
+ || !(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type[itype], "vec1"))) {
+ return false;
+ }
+
+ if (!(max = simd_build_splat_const_integer_vector(
+ comp_ctx, min_max_type[itype],
+ is_signed ? smax[itype] : umax[itype], length[itype]))
+ || !(min = simd_build_splat_const_integer_vector(
+ comp_ctx, min_max_type[itype],
+ is_signed ? smin[itype] : umin[itype], length[itype]))) {
+ return false;
+ }
+
+ /* sat */
+ if (!(vec1 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec1, min, max,
+ is_signed))
+ || !(vec2 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec2, min,
+ max, is_signed))) {
+ return false;
+ }
+
+ /* trunc */
+ if (!(vec1 = LLVMBuildTrunc(comp_ctx->builder, vec1, trunc_type[itype],
+ "vec1_trunc"))
+ || !(vec2 = LLVMBuildTrunc(comp_ctx->builder, vec2, trunc_type[itype],
+ "vec2_trunc"))) {
+ HANDLE_FAILURE("LLVMBuildTrunc");
+ return false;
+ }
+
+ /* combine */
+ if (!(mask = LLVMConstVector(mask_element, (length[itype] << 1)))) {
+ HANDLE_FAILURE("LLVMConstInt");
+ return false;
+ }
+
+ if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, vec1, vec2, mask,
+ "vec_shuffle"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ if (is_target_x86(comp_ctx)) {
+ return simd_integer_narrow_x86(
+ comp_ctx, func_ctx, V128_i16x8_TYPE, V128_i8x16_TYPE,
+ is_signed ? "llvm.x86.sse2.packsswb.128"
+ : "llvm.x86.sse2.packuswb.128");
+ }
+ else {
+ return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i16x8,
+ is_signed);
+ }
+}
+
+bool
+aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ if (is_target_x86(comp_ctx)) {
+ return simd_integer_narrow_x86(comp_ctx, func_ctx, V128_i32x4_TYPE,
+ V128_i16x8_TYPE,
+ is_signed ? "llvm.x86.sse2.packssdw.128"
+ : "llvm.x86.sse41.packusdw");
+ }
+ else {
+ return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i32x4,
+ is_signed);
+ }
+}
+
+bool
+aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ /* TODO: x86 intrinsics */
+ return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i64x2,
+ is_signed);
+}
+
+enum integer_extend_type {
+ e_ext_i8x16,
+ e_ext_i16x8,
+ e_ext_i32x4,
+};
+
+static LLVMValueRef
+simd_integer_extension(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ enum integer_extend_type itype, LLVMValueRef vector,
+ bool lower_half, bool is_signed)
+{
+ LLVMValueRef mask, sub_vector, result;
+ LLVMValueRef bits[] = {
+ LLVM_CONST(i32_zero), LLVM_CONST(i32_one),
+ LLVM_CONST(i32_two), LLVM_CONST(i32_three),
+ LLVM_CONST(i32_four), LLVM_CONST(i32_five),
+ LLVM_CONST(i32_six), LLVM_CONST(i32_seven),
+ LLVM_CONST(i32_eight), LLVM_CONST(i32_nine),
+ LLVM_CONST(i32_ten), LLVM_CONST(i32_eleven),
+ LLVM_CONST(i32_twelve), LLVM_CONST(i32_thirteen),
+ LLVM_CONST(i32_fourteen), LLVM_CONST(i32_fifteen),
+ };
+ LLVMTypeRef out_vector_type[] = { V128_i16x8_TYPE, V128_i32x4_TYPE,
+ V128_i64x2_TYPE };
+ LLVMValueRef undef[] = { LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef),
+ LLVM_CONST(i32x4_undef) };
+ uint32 sub_vector_length[] = { 8, 4, 2 };
+
+ if (!(mask = lower_half ? LLVMConstVector(bits, sub_vector_length[itype])
+ : LLVMConstVector(bits + sub_vector_length[itype],
+ sub_vector_length[itype]))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ return false;
+ }
+
+ /* retrive the low or high half */
+ if (!(sub_vector = LLVMBuildShuffleVector(comp_ctx->builder, vector,
+ undef[itype], mask, "half"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ if (is_signed) {
+ if (!(result = LLVMBuildSExt(comp_ctx->builder, sub_vector,
+ out_vector_type[itype], "sext"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ return false;
+ }
+ }
+ else {
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, sub_vector,
+ out_vector_type[itype], "zext"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ return false;
+ }
+ }
+
+ return result;
+}
+
+static bool
+simd_integer_extension_wrapper(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ enum integer_extend_type itype, bool lower_half,
+ bool is_signed)
+{
+ LLVMValueRef vector, result;
+
+ LLVMTypeRef in_vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
+ V128_i32x4_TYPE };
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type[itype], "vec"))) {
+ return false;
+ }
+
+ if (!(result = simd_integer_extension(comp_ctx, func_ctx, itype, vector,
+ lower_half, is_signed))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed)
+{
+ return simd_integer_extension_wrapper(comp_ctx, func_ctx, e_ext_i8x16,
+ lower_half, is_signed);
+}
+
+bool
+aot_compile_simd_i32x4_extend_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed)
+{
+ return simd_integer_extension_wrapper(comp_ctx, func_ctx, e_ext_i16x8,
+ lower_half, is_signed);
+}
+
+bool
+aot_compile_simd_i64x2_extend_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed)
+{
+ return simd_integer_extension_wrapper(comp_ctx, func_ctx, e_ext_i32x4,
+ lower_half, is_signed);
+}
+
+static LLVMValueRef
+simd_trunc_sat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ const char *intrinsics, LLVMTypeRef in_vector_type,
+ LLVMTypeRef out_vector_type)
+{
+ LLVMValueRef vector, result;
+ LLVMTypeRef param_types[] = { in_vector_type };
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, in_vector_type,
+ "vector"))) {
+ return false;
+ }
+
+ if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsics,
+ out_vector_type, param_types, 1,
+ vector))) {
+ return false;
+ }
+
+ return result;
+}
+
+bool
+aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ LLVMValueRef result;
+ if (!(result = simd_trunc_sat(comp_ctx, func_ctx,
+ is_signed ? "llvm.fptosi.sat.v4i32.v4f32"
+ : "llvm.fptoui.sat.v4i32.v4f32",
+ V128_f32x4_TYPE, V128_i32x4_TYPE))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i32x4_trunc_sat_f64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ LLVMValueRef result, zero, mask;
+ LLVMTypeRef out_vector_type;
+ LLVMValueRef lanes[] = {
+ LLVM_CONST(i32_zero),
+ LLVM_CONST(i32_one),
+ LLVM_CONST(i32_two),
+ LLVM_CONST(i32_three),
+ };
+
+ if (!(out_vector_type = LLVMVectorType(I32_TYPE, 2))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return false;
+ }
+
+ if (!(result = simd_trunc_sat(comp_ctx, func_ctx,
+ is_signed ? "llvm.fptosi.sat.v2i32.v2f64"
+ : "llvm.fptoui.sat.v2i32.v2f64",
+ V128_f64x2_TYPE, out_vector_type))) {
+ return false;
+ }
+
+ if (!(zero = LLVMConstNull(out_vector_type))) {
+ HANDLE_FAILURE("LLVMConstNull");
+ return false;
+ }
+
+ /* v2i32 -> v4i32 */
+ if (!(mask = LLVMConstVector(lanes, 4))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ return false;
+ }
+
+ if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result, zero, mask,
+ "extend"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+static LLVMValueRef
+simd_integer_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool is_signed, LLVMValueRef vector,
+ LLVMTypeRef out_vector_type)
+
+{
+ LLVMValueRef result;
+ result = is_signed ? LLVMBuildSIToFP(comp_ctx->builder, vector,
+ out_vector_type, "converted")
+ : LLVMBuildUIToFP(comp_ctx->builder, vector,
+ out_vector_type, "converted");
+ if (!result) {
+ HANDLE_FAILURE("LLVMBuildSIToFP/LLVMBuildUIToFP");
+ }
+
+ return result;
+}
+
+bool
+aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ LLVMValueRef vector, result;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i32x4_TYPE, "vec"))) {
+ return false;
+ }
+
+ if (!(result = simd_integer_convert(comp_ctx, func_ctx, is_signed, vector,
+ V128_f32x4_TYPE))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_f64x2_convert_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed)
+{
+ LLVMValueRef vector, mask, result;
+ LLVMValueRef lanes[] = {
+ LLVM_CONST(i32_zero),
+ LLVM_CONST(i32_one),
+ };
+ LLVMTypeRef out_vector_type;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i32x4_TYPE, "vec"))) {
+ return false;
+ }
+
+ if (!(out_vector_type = LLVMVectorType(F64_TYPE, 4))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return false;
+ }
+
+ if (!(result = simd_integer_convert(comp_ctx, func_ctx, is_signed, vector,
+ out_vector_type))) {
+ return false;
+ }
+
+ /* v4f64 -> v2f64 */
+ if (!(mask = LLVMConstVector(lanes, 2))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ return false;
+ }
+
+ if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result, result,
+ mask, "trunc"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+static bool
+simd_extadd_pairwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef in_vector_type, LLVMTypeRef out_vector_type,
+ bool is_signed)
+{
+ LLVMValueRef vector, even_mask, odd_mask, sub_vector_even, sub_vector_odd,
+ result;
+
+ LLVMValueRef even_element[] = {
+ LLVM_CONST(i32_zero), LLVM_CONST(i32_two), LLVM_CONST(i32_four),
+ LLVM_CONST(i32_six), LLVM_CONST(i32_eight), LLVM_CONST(i32_ten),
+ LLVM_CONST(i32_twelve), LLVM_CONST(i32_fourteen),
+ };
+
+ LLVMValueRef odd_element[] = {
+ LLVM_CONST(i32_one), LLVM_CONST(i32_three),
+ LLVM_CONST(i32_five), LLVM_CONST(i32_seven),
+ LLVM_CONST(i32_nine), LLVM_CONST(i32_eleven),
+ LLVM_CONST(i32_thirteen), LLVM_CONST(i32_fifteen),
+ };
+
+ /* assumption about i16x8 from i8x16 and i32x4 from i16x8 */
+ uint8 mask_length = V128_i16x8_TYPE == out_vector_type ? 8 : 4;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, in_vector_type,
+ "vector"))) {
+ return false;
+ }
+
+ if (!(even_mask = LLVMConstVector(even_element, mask_length))
+ || !(odd_mask = LLVMConstVector(odd_element, mask_length))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ return false;
+ }
+
+ /* shuffle a <16xi8> vector to two <8xi8> vectors */
+ if (!(sub_vector_even = LLVMBuildShuffleVector(
+ comp_ctx->builder, vector, vector, even_mask, "pick_even"))
+ || !(sub_vector_odd = LLVMBuildShuffleVector(
+ comp_ctx->builder, vector, vector, odd_mask, "pick_odd"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ /* sext/zext <8xi8> to <8xi16> */
+ if (is_signed) {
+ if (!(sub_vector_even =
+ LLVMBuildSExt(comp_ctx->builder, sub_vector_even,
+ out_vector_type, "even_sext"))
+ || !(sub_vector_odd =
+ LLVMBuildSExt(comp_ctx->builder, sub_vector_odd,
+ out_vector_type, "odd_sext"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ return false;
+ }
+ }
+ else {
+ if (!(sub_vector_even =
+ LLVMBuildZExt(comp_ctx->builder, sub_vector_even,
+ out_vector_type, "even_zext"))
+ || !(sub_vector_odd =
+ LLVMBuildZExt(comp_ctx->builder, sub_vector_odd,
+ out_vector_type, "odd_zext"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ return false;
+ }
+ }
+
+ if (!(result = LLVMBuildAdd(comp_ctx->builder, sub_vector_even,
+ sub_vector_odd, "sum"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i16x8_extadd_pairwise_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_signed)
+{
+ return simd_extadd_pairwise(comp_ctx, func_ctx, V128_i8x16_TYPE,
+ V128_i16x8_TYPE, is_signed);
+}
+
+bool
+aot_compile_simd_i32x4_extadd_pairwise_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_signed)
+{
+ return simd_extadd_pairwise(comp_ctx, func_ctx, V128_i16x8_TYPE,
+ V128_i32x4_TYPE, is_signed);
+}
+
+bool
+aot_compile_simd_i16x8_q15mulr_sat(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMValueRef lhs, rhs, pad, offset, min, max, result;
+ LLVMTypeRef vector_ext_type;
+
+ if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE,
+ "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i16x8_TYPE, "lhs"))) {
+ return false;
+ }
+
+ if (!(vector_ext_type = LLVMVectorType(I32_TYPE, 8))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return false;
+ }
+
+ if (!(lhs = LLVMBuildSExt(comp_ctx->builder, lhs, vector_ext_type,
+ "lhs_v8i32"))
+ || !(rhs = LLVMBuildSExt(comp_ctx->builder, rhs, vector_ext_type,
+ "rhs_v8i32"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ return false;
+ }
+
+ /* 0x4000 and 15*/
+ if (!(pad = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE,
+ 0x4000, 8))
+ || !(offset = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE,
+ 15, 8))) {
+ return false;
+ }
+
+ /* TODO: looking for x86 intrinsics about integer"fused multiply-and-add" */
+ /* S.SignedSaturate((x * y + 0x4000) >> 15) */
+ if (!(result = LLVMBuildMul(comp_ctx->builder, lhs, rhs, "mul"))) {
+ HANDLE_FAILURE("LLVMBuildMul");
+ return false;
+ }
+
+ if (!(result = LLVMBuildAdd(comp_ctx->builder, result, pad, "add"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ return false;
+ }
+
+ if (!(result = LLVMBuildAShr(comp_ctx->builder, result, offset, "ashr"))) {
+ HANDLE_FAILURE("LLVMBuildAShr");
+ return false;
+ }
+
+ if (!(min = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE,
+ 0xffff8000, 8))
+ || !(max = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE,
+ 0x00007fff, 8))) {
+ return false;
+ }
+
+ /* sat after trunc will let *sat* part be optimized */
+ if (!(result = simd_saturate(comp_ctx, func_ctx, e_sat_i32x8, result, min,
+ max, true))) {
+ return false;
+ }
+
+ if (!(result = LLVMBuildTrunc(comp_ctx->builder, result, V128_i16x8_TYPE,
+ "down_to_v8i16"))) {
+ HANDLE_FAILURE("LLVMBuidlTrunc");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+enum integer_extmul_type {
+ e_i16x8_extmul_i8x16,
+ e_i32x4_extmul_i16x8,
+ e_i64x2_extmul_i32x4,
+};
+
+static bool
+simd_integer_extmul(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ bool lower_half, bool is_signed,
+ enum integer_extmul_type itype)
+{
+ LLVMValueRef vec1, vec2, result;
+ enum integer_extend_type ext_type[] = {
+ e_ext_i8x16,
+ e_ext_i16x8,
+ e_ext_i32x4,
+ };
+ LLVMTypeRef in_vector_type[] = {
+ V128_i8x16_TYPE,
+ V128_i16x8_TYPE,
+ V128_i32x4_TYPE,
+ };
+
+ if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type[itype], "vec1"))
+ || !(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ in_vector_type[itype], "vec2"))) {
+ return false;
+ }
+
+ if (!(vec1 = simd_integer_extension(comp_ctx, func_ctx, ext_type[itype],
+ vec1, lower_half, is_signed))
+ || !(vec2 = simd_integer_extension(comp_ctx, func_ctx, ext_type[itype],
+ vec2, lower_half, is_signed))) {
+ return false;
+ }
+
+ if (!(result = LLVMBuildMul(comp_ctx->builder, vec1, vec2, "product"))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i16x8_extmul_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed)
+{
+ return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed,
+ e_i16x8_extmul_i8x16);
+}
+
+bool
+aot_compile_simd_i32x4_extmul_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed)
+{
+ return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed,
+ e_i32x4_extmul_i16x8);
+}
+
+bool
+aot_compile_simd_i64x2_extmul_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed)
+{
+ return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed,
+ e_i64x2_extmul_i32x4);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.h
new file mode 100644
index 000000000..87b8bd684
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_conversions.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_CONVERSIONS_H_
+#define _SIMD_CONVERSIONS_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed);
+
+bool
+aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed);
+
+bool
+aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed);
+
+bool
+aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_low,
+ bool is_signed);
+
+bool
+aot_compile_simd_i32x4_extend_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_low,
+ bool is_signed);
+
+bool
+aot_compile_simd_i64x2_extend_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed);
+
+bool
+aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_signed);
+
+bool
+aot_compile_simd_i32x4_trunc_sat_f64x2(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_signed);
+
+bool
+aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed);
+
+bool
+aot_compile_simd_f64x2_convert_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_signed);
+bool
+aot_compile_simd_i16x8_extadd_pairwise_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_signed);
+
+bool
+aot_compile_simd_i32x4_extadd_pairwise_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ bool is_signed);
+bool
+aot_compile_simd_i16x8_q15mulr_sat(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i16x8_extmul_i8x16(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_low,
+ bool is_signed);
+
+bool
+aot_compile_simd_i32x4_extmul_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool is_low,
+ bool is_signed);
+
+bool
+aot_compile_simd_i64x2_extmul_i32x4(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool lower_half,
+ bool is_signed);
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_CONVERSIONS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.c
new file mode 100644
index 000000000..d850fe8f7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_floating_point.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../aot_emit_numberic.h"
+#include "../../aot/aot_runtime.h"
+
+static bool
+simd_v128_float_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op, LLVMTypeRef vector_type)
+{
+ LLVMValueRef lhs, rhs, result = NULL;
+
+ if (!(rhs =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "lhs"))) {
+ return false;
+ }
+
+ switch (arith_op) {
+ case FLOAT_ADD:
+ result = LLVMBuildFAdd(comp_ctx->builder, lhs, rhs, "sum");
+ break;
+ case FLOAT_SUB:
+ result = LLVMBuildFSub(comp_ctx->builder, lhs, rhs, "difference");
+ break;
+ case FLOAT_MUL:
+ result = LLVMBuildFMul(comp_ctx->builder, lhs, rhs, "product");
+ break;
+ case FLOAT_DIV:
+ result = LLVMBuildFDiv(comp_ctx->builder, lhs, rhs, "quotient");
+ break;
+ default:
+ return false;
+ }
+
+ if (!result) {
+ HANDLE_FAILURE(
+ "LLVMBuildFAdd/LLVMBuildFSub/LLVMBuildFMul/LLVMBuildFDiv");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op)
+{
+ return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, V128_f32x4_TYPE);
+}
+
+bool
+aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op)
+{
+ return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, V128_f64x2_TYPE);
+}
+
+static bool
+simd_v128_float_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef vector_type)
+{
+ LLVMValueRef vector, result;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vector"))) {
+ return false;
+ }
+
+ if (!(result = LLVMBuildFNeg(comp_ctx->builder, vector, "neg"))) {
+ HANDLE_FAILURE("LLVMBuildFNeg");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_f32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_v128_float_neg(comp_ctx, func_ctx, V128_f32x4_TYPE);
+}
+
+bool
+aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_v128_float_neg(comp_ctx, func_ctx, V128_f64x2_TYPE);
+}
+
+static bool
+simd_float_intrinsic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef vector_type, const char *intrinsic)
+{
+ LLVMValueRef vector, result;
+ LLVMTypeRef param_types[1] = { vector_type };
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vector"))) {
+ return false;
+ }
+
+ if (!(result =
+ aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+ vector_type, param_types, 1, vector))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.fabs.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.fabs.v2f64");
+}
+
+bool
+aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.round.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.round.v2f64");
+}
+
+bool
+aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.sqrt.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.sqrt.v2f64");
+}
+
+bool
+aot_compile_simd_f32x4_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.ceil.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.ceil.v2f64");
+}
+
+bool
+aot_compile_simd_f32x4_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.floor.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.floor.v2f64");
+}
+
+bool
+aot_compile_simd_f32x4_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.trunc.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.trunc.v2f64");
+}
+
+bool
+aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ "llvm.rint.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ "llvm.rint.v2f64");
+}
+
+static bool
+simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op, LLVMTypeRef vector_type)
+{
+ LLVMValueRef lhs, rhs, result;
+ LLVMRealPredicate op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT;
+
+ if (!(rhs =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "lhs"))) {
+ return false;
+ }
+
+ if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
+ HANDLE_FAILURE("LLVMBuildFCmp");
+ return false;
+ }
+
+ if (!(result =
+ LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
+ HANDLE_FAILURE("LLVMBuildSelect");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+/*TODO: sugggest non-IA platforms check with "llvm.minimum.*" and
+ * "llvm.maximum.*" firstly */
+bool
+aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min)
+{
+ return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
+ V128_f32x4_TYPE);
+}
+
+bool
+aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min)
+{
+ return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
+ V128_f64x2_TYPE);
+}
+
+static bool
+simd_float_pmin_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef vector_type, const char *intrinsic)
+{
+ LLVMValueRef lhs, rhs, result;
+ LLVMTypeRef param_types[2];
+
+ param_types[0] = vector_type;
+ param_types[1] = vector_type;
+
+ if (!(rhs =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "lhs"))) {
+ return false;
+ }
+
+ if (!(result =
+ aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+ vector_type, param_types, 2, lhs, rhs))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min)
+{
+ return simd_float_pmin_max(comp_ctx, func_ctx, V128_f32x4_TYPE,
+ run_min ? "llvm.minnum.v4f32"
+ : "llvm.maxnum.v4f32");
+}
+
+bool
+aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min)
+{
+ return simd_float_pmin_max(comp_ctx, func_ctx, V128_f64x2_TYPE,
+ run_min ? "llvm.minnum.v2f64"
+ : "llvm.maxnum.v2f64");
+}
+
+bool
+aot_compile_simd_f64x2_demote(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector, elem_0, elem_1, result;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_f64x2_TYPE, "vector"))) {
+ return false;
+ }
+
+ if (!(elem_0 = LLVMBuildExtractElement(comp_ctx->builder, vector,
+ LLVM_CONST(i32_zero), "elem_0"))
+ || !(elem_1 = LLVMBuildExtractElement(comp_ctx->builder, vector,
+ LLVM_CONST(i32_one), "elem_1"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ return false;
+ }
+
+ /* fptrunc <f64> elem to <f32> */
+ if (!(elem_0 = LLVMBuildFPTrunc(comp_ctx->builder, elem_0, F32_TYPE,
+ "elem_0_trunc"))
+ || !(elem_1 = LLVMBuildFPTrunc(comp_ctx->builder, elem_1, F32_TYPE,
+ "elem_1_trunc"))) {
+ HANDLE_FAILURE("LLVMBuildFPTrunc");
+ return false;
+ }
+
+ if (!(result = LLVMBuildInsertElement(comp_ctx->builder,
+ LLVM_CONST(f32x4_vec_zero), elem_0,
+ LLVM_CONST(i32_zero), "new_vector_0"))
+ || !(result =
+ LLVMBuildInsertElement(comp_ctx->builder, result, elem_1,
+ LLVM_CONST(i32_one), "new_vector_1"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_f32x4_promote(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector, elem_0, elem_1, result;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_f32x4_TYPE, "vector"))) {
+ return false;
+ }
+
+ if (!(elem_0 = LLVMBuildExtractElement(comp_ctx->builder, vector,
+ LLVM_CONST(i32_zero), "elem_0"))
+ || !(elem_1 = LLVMBuildExtractElement(comp_ctx->builder, vector,
+ LLVM_CONST(i32_one), "elem_1"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ return false;
+ }
+
+ /* fpext <f32> elem to <f64> */
+ if (!(elem_0 =
+ LLVMBuildFPExt(comp_ctx->builder, elem_0, F64_TYPE, "elem_0_ext"))
+ || !(elem_1 = LLVMBuildFPExt(comp_ctx->builder, elem_1, F64_TYPE,
+ "elem_1_ext"))) {
+ HANDLE_FAILURE("LLVMBuildFPExt");
+ return false;
+ }
+
+ if (!(result = LLVMBuildInsertElement(comp_ctx->builder,
+ LLVM_CONST(f64x2_vec_zero), elem_0,
+ LLVM_CONST(i32_zero), "new_vector_0"))
+ || !(result =
+ LLVMBuildInsertElement(comp_ctx->builder, result, elem_1,
+ LLVM_CONST(i32_one), "new_vector_1"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.h
new file mode 100644
index 000000000..213b4391f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_floating_point.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_FLOATING_POINT_H_
+#define _SIMD_FLOATING_POINT_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op);
+
+bool
+aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ FloatArithmetic arith_op);
+
+bool
+aot_compile_simd_f32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_floor(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_floor(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_trunc(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_trunc(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min);
+
+bool
+aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min);
+
+bool
+aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min);
+
+bool
+aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx, bool run_min);
+
+bool
+aot_compile_simd_f64x2_demote(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_f32x4_promote(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_FLOATING_POINT_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.c
new file mode 100644
index 000000000..1d0e6967b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_int_arith.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+static bool
+simd_integer_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, LLVMTypeRef vector_type)
+{
+ LLVMValueRef lhs, rhs, result = NULL;
+
+ if (!(rhs =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "lhs"))) {
+ return false;
+ }
+
+ switch (arith_op) {
+ case V128_ADD:
+ result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "sum");
+ break;
+ case V128_SUB:
+ result = LLVMBuildSub(comp_ctx->builder, lhs, rhs, "difference");
+ break;
+ case V128_MUL:
+ result = LLVMBuildMul(comp_ctx->builder, lhs, rhs, "product");
+ break;
+ default:
+ HANDLE_FAILURE("Unsupport arith_op");
+ break;
+ }
+
+ if (!result) {
+ HANDLE_FAILURE("LLVMBuildAdd/LLVMBuildSub/LLVMBuildMul");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op)
+{
+ return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i8x16_TYPE);
+}
+
+bool
+aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op)
+{
+ return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i16x8_TYPE);
+}
+
+bool
+aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op)
+{
+ return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i32x4_TYPE);
+}
+
+bool
+aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op)
+{
+ return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i64x2_TYPE);
+}
+
+static bool
+simd_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMTypeRef type)
+{
+ LLVMValueRef vector, result;
+
+ if (!(vector =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, type, "vector"))) {
+ return false;
+ }
+
+ if (!(result = LLVMBuildNeg(comp_ctx->builder, vector, "neg"))) {
+ HANDLE_FAILURE("LLVMBuildNeg");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_neg(comp_ctx, func_ctx, V128_i8x16_TYPE);
+}
+
+bool
+aot_compile_simd_i16x8_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_neg(comp_ctx, func_ctx, V128_i16x8_TYPE);
+}
+
+bool
+aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_neg(comp_ctx, func_ctx, V128_i32x4_TYPE);
+}
+
+bool
+aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_neg(comp_ctx, func_ctx, V128_i64x2_TYPE);
+}
+
+bool
+aot_compile_simd_i8x16_popcnt(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vector, result;
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i8x16_TYPE, "vector"))) {
+ return false;
+ }
+
+ if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx,
+ "llvm.ctpop.v16i8", V128_i8x16_TYPE,
+ &V128_i8x16_TYPE, 1, vector))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+static bool
+simd_v128_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef vector_type, V128Arithmetic arith_op, bool is_signed)
+{
+ LLVMValueRef lhs, rhs, result;
+ LLVMIntPredicate op;
+
+ if (!(rhs =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "lhs"))) {
+ return false;
+ }
+
+ if (V128_MIN == arith_op) {
+ op = is_signed ? LLVMIntSLT : LLVMIntULT;
+ }
+ else {
+ op = is_signed ? LLVMIntSGT : LLVMIntUGT;
+ }
+
+ if (!(result = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
+ HANDLE_FAILURE("LLVMBuildICmp");
+ return false;
+ }
+
+ if (!(result =
+ LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
+ HANDLE_FAILURE("LLVMBuildSelect");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed)
+{
+ return simd_v128_cmp(comp_ctx, func_ctx, V128_i8x16_TYPE, arith_op,
+ is_signed);
+}
+
+bool
+aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed)
+{
+ return simd_v128_cmp(comp_ctx, func_ctx, V128_i16x8_TYPE, arith_op,
+ is_signed);
+}
+
+bool
+aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed)
+{
+ return simd_v128_cmp(comp_ctx, func_ctx, V128_i32x4_TYPE, arith_op,
+ is_signed);
+}
+
+/* llvm.abs.* */
+static bool
+simd_v128_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ char *intrinsic, LLVMTypeRef vector_type)
+{
+ LLVMValueRef vector, result;
+ LLVMTypeRef param_types[] = { vector_type, INT1_TYPE };
+
+ if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "vec"))) {
+ return false;
+ }
+
+ if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
+ vector_type, param_types, 2, vector,
+ /* is_int_min_poison */
+ LLVM_CONST(i1_zero)))) {
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v16i8", V128_i8x16_TYPE);
+}
+
+bool
+aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v8i16", V128_i16x8_TYPE);
+}
+
+bool
+aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v4i32", V128_i32x4_TYPE);
+}
+
+bool
+aot_compile_simd_i64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+ return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v2i64", V128_i64x2_TYPE);
+}
+
+enum integer_avgr_u {
+ e_avgr_u_i8x16,
+ e_avgr_u_i16x8,
+ e_avgr_u_i32x4,
+};
+
+/* TODO: try int_x86_mmx_pavg_b and int_x86_mmx_pavg_w */
+/* (v1 + v2 + 1) / 2 */
+static bool
+simd_v128_avg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ enum integer_avgr_u itype)
+{
+ LLVMValueRef lhs, rhs, ones, result;
+ LLVMTypeRef vector_ext_type;
+ LLVMTypeRef vector_type[] = {
+ V128_i8x16_TYPE,
+ V128_i16x8_TYPE,
+ V128_i32x4_TYPE,
+ };
+ unsigned lanes[] = { 16, 8, 4 };
+
+ if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ vector_type[itype], "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ vector_type[itype], "lhs"))) {
+ return false;
+ }
+
+ if (!(vector_ext_type = LLVMVectorType(I64_TYPE, lanes[itype]))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return false;
+ }
+
+ if (!(lhs = LLVMBuildZExt(comp_ctx->builder, lhs, vector_ext_type,
+ "zext_to_i64"))
+ || !(rhs = LLVMBuildZExt(comp_ctx->builder, rhs, vector_ext_type,
+ "zext_to_i64"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ return false;
+ }
+
+ /* by default, add will do signed/unsigned overflow */
+ if (!(result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "l_add_r"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ return false;
+ }
+
+ if (!(ones = simd_build_splat_const_integer_vector(comp_ctx, I64_TYPE, 1,
+ lanes[itype]))) {
+ return false;
+ }
+
+ if (!(result = LLVMBuildAdd(comp_ctx->builder, result, ones, "plus_1"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ return false;
+ }
+
+ if (!(result = LLVMBuildLShr(comp_ctx->builder, result, ones, "avg"))) {
+ HANDLE_FAILURE("LLVMBuildLShr");
+ return false;
+ }
+
+ if (!(result = LLVMBuildTrunc(comp_ctx->builder, result, vector_type[itype],
+ "to_orig_type"))) {
+ HANDLE_FAILURE("LLVMBuildTrunc");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i8x16);
+}
+
+bool
+aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i16x8);
+}
+
+bool
+aot_compile_simd_i32x4_avgr_u(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i32x4);
+}
+
+bool
+aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx)
+{
+ LLVMValueRef vec1, vec2, even_mask, odd_mask, zero, result;
+ LLVMTypeRef vector_ext_type;
+ LLVMValueRef even_element[] = {
+ LLVM_CONST(i32_zero),
+ LLVM_CONST(i32_two),
+ LLVM_CONST(i32_four),
+ LLVM_CONST(i32_six),
+ };
+ LLVMValueRef odd_element[] = {
+ LLVM_CONST(i32_one),
+ LLVM_CONST(i32_three),
+ LLVM_CONST(i32_five),
+ LLVM_CONST(i32_seven),
+ };
+
+ if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE,
+ "vec1"))
+ || !(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
+ V128_i16x8_TYPE, "vec2"))) {
+ return false;
+ }
+
+ if (!(vector_ext_type = LLVMVectorType(I32_TYPE, 8))) {
+ HANDLE_FAILURE("LLVMVectorType");
+ return false;
+ }
+
+ /* sext <v8i16> to <v8i32> */
+ if (!(vec1 = LLVMBuildSExt(comp_ctx->builder, vec1, vector_ext_type,
+ "vec1_v8i32"))
+ || !(vec2 = LLVMBuildSExt(comp_ctx->builder, vec2, vector_ext_type,
+ "vec2_v8i32"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ return false;
+ }
+
+ if (!(result = LLVMBuildMul(comp_ctx->builder, vec1, vec2, "product"))) {
+ HANDLE_FAILURE("LLVMBuildMul");
+ return false;
+ }
+
+ /* pick elements with even indexes and odd indexes */
+ if (!(even_mask = LLVMConstVector(even_element, 4))
+ || !(odd_mask = LLVMConstVector(odd_element, 4))) {
+ HANDLE_FAILURE("LLVMConstVector");
+ return false;
+ }
+
+ if (!(zero = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE, 0,
+ 8))) {
+ return false;
+ }
+
+ if (!(vec1 = LLVMBuildShuffleVector(comp_ctx->builder, result, zero,
+ even_mask, "even_result"))
+ || !(vec2 = LLVMBuildShuffleVector(comp_ctx->builder, result, zero,
+ odd_mask, "odd_result"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ if (!(result = LLVMBuildAdd(comp_ctx->builder, vec1, vec2, "new_vec"))) {
+ HANDLE_FAILURE("LLVMBuildAdd");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.h
new file mode 100644
index 000000000..a7a21170a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_int_arith.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_INT_ARITH_H_
+#define _SIMD_INT_ARITH_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic cond);
+
+bool
+aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic cond);
+
+bool
+aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic cond);
+
+bool
+aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic cond);
+
+bool
+aot_compile_simd_i8x16_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i16x8_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i8x16_popcnt(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed);
+
+bool
+aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed);
+
+bool
+aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed);
+
+bool
+aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i32x4_avgr_u(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+bool
+aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_INT_ARITH_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.c
new file mode 100644
index 000000000..d166e954c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_common.h"
+#include "simd_load_store.h"
+#include "../aot_emit_exception.h"
+#include "../aot_emit_memory.h"
+#include "../../aot/aot_runtime.h"
+#include "../../interpreter/wasm_opcode.h"
+
+/* data_length in bytes */
+static LLVMValueRef
+simd_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 align,
+ uint32 offset, uint32 data_length, LLVMTypeRef ptr_type,
+ LLVMTypeRef data_type)
+{
+ LLVMValueRef maddr, data;
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset,
+ data_length))) {
+ HANDLE_FAILURE("aot_check_memory_overflow");
+ return NULL;
+ }
+
+ if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, ptr_type,
+ "data_ptr"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ return NULL;
+ }
+
+ if (!(data = LLVMBuildLoad2(comp_ctx->builder, data_type, maddr, "data"))) {
+ HANDLE_FAILURE("LLVMBuildLoad");
+ return NULL;
+ }
+
+ LLVMSetAlignment(data, 1);
+
+ return data;
+}
+
+bool
+aot_compile_simd_v128_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset)
+{
+ LLVMValueRef result;
+
+ if (!(result = simd_load(comp_ctx, func_ctx, align, offset, 16,
+ V128_PTR_TYPE, V128_TYPE))) {
+ return false;
+ }
+
+ PUSH_V128(result);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_load_extend(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset)
+{
+ LLVMValueRef sub_vector, result;
+ uint32 opcode_index = opcode - SIMD_v128_load8x8_s;
+ bool signeds[] = { true, false, true, false, true, false };
+ LLVMTypeRef vector_types[] = {
+ V128_i16x8_TYPE, V128_i16x8_TYPE, V128_i32x4_TYPE,
+ V128_i32x4_TYPE, V128_i64x2_TYPE, V128_i64x2_TYPE,
+ };
+ LLVMTypeRef sub_vector_types[] = {
+ LLVMVectorType(INT8_TYPE, 8), LLVMVectorType(INT8_TYPE, 8),
+ LLVMVectorType(INT16_TYPE, 4), LLVMVectorType(INT16_TYPE, 4),
+ LLVMVectorType(I32_TYPE, 2), LLVMVectorType(I32_TYPE, 2),
+ };
+ LLVMTypeRef sub_vector_type, sub_vector_ptr_type;
+
+ bh_assert(opcode_index < 6);
+
+ sub_vector_type = sub_vector_types[opcode_index];
+
+ /* to vector ptr type */
+ if (!sub_vector_type
+ || !(sub_vector_ptr_type = LLVMPointerType(sub_vector_type, 0))) {
+ HANDLE_FAILURE("LLVMPointerType");
+ return false;
+ }
+
+ if (!(sub_vector = simd_load(comp_ctx, func_ctx, align, offset, 8,
+ sub_vector_ptr_type, sub_vector_type))) {
+ return false;
+ }
+
+ if (signeds[opcode_index]) {
+ if (!(result = LLVMBuildSExt(comp_ctx->builder, sub_vector,
+ vector_types[opcode_index], "vector"))) {
+ HANDLE_FAILURE("LLVMBuildSExt");
+ return false;
+ }
+ }
+ else {
+ if (!(result = LLVMBuildZExt(comp_ctx->builder, sub_vector,
+ vector_types[opcode_index], "vector"))) {
+ HANDLE_FAILURE("LLVMBuildZExt");
+ return false;
+ }
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_load_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset)
+{
+ uint32 opcode_index = opcode - SIMD_v128_load8_splat;
+ LLVMValueRef element, result;
+ LLVMTypeRef element_ptr_types[] = { INT8_PTR_TYPE, INT16_PTR_TYPE,
+ INT32_PTR_TYPE, INT64_PTR_TYPE };
+ LLVMTypeRef element_data_types[] = { INT8_TYPE, INT16_TYPE, I32_TYPE,
+ I64_TYPE };
+ uint32 data_lengths[] = { 1, 2, 4, 8 };
+ LLVMValueRef undefs[] = {
+ LLVM_CONST(i8x16_undef),
+ LLVM_CONST(i16x8_undef),
+ LLVM_CONST(i32x4_undef),
+ LLVM_CONST(i64x2_undef),
+ };
+ LLVMValueRef masks[] = {
+ LLVM_CONST(i32x16_zero),
+ LLVM_CONST(i32x8_zero),
+ LLVM_CONST(i32x4_zero),
+ LLVM_CONST(i32x2_zero),
+ };
+
+ bh_assert(opcode_index < 4);
+
+ if (!(element = simd_load(comp_ctx, func_ctx, align, offset,
+ data_lengths[opcode_index],
+ element_ptr_types[opcode_index],
+ element_data_types[opcode_index]))) {
+ return false;
+ }
+
+ if (!(result =
+ LLVMBuildInsertElement(comp_ctx->builder, undefs[opcode_index],
+ element, I32_ZERO, "base"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ return false;
+ }
+
+ if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result,
+ undefs[opcode_index],
+ masks[opcode_index], "vector"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_load_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset,
+ uint8 lane_id)
+{
+ LLVMValueRef element, vector;
+ uint32 opcode_index = opcode - SIMD_v128_load8_lane;
+ uint32 data_lengths[] = { 1, 2, 4, 8 };
+ LLVMTypeRef element_ptr_types[] = { INT8_PTR_TYPE, INT16_PTR_TYPE,
+ INT32_PTR_TYPE, INT64_PTR_TYPE };
+ LLVMTypeRef element_data_types[] = { INT8_TYPE, INT16_TYPE, I32_TYPE,
+ I64_TYPE };
+ LLVMTypeRef vector_types[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
+ V128_i32x4_TYPE, V128_i64x2_TYPE };
+ LLVMValueRef lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id);
+
+ bh_assert(opcode_index < 4);
+
+ if (!(vector = simd_pop_v128_and_bitcast(
+ comp_ctx, func_ctx, vector_types[opcode_index], "src"))) {
+ return false;
+ }
+
+ if (!(element = simd_load(comp_ctx, func_ctx, align, offset,
+ data_lengths[opcode_index],
+ element_ptr_types[opcode_index],
+ element_data_types[opcode_index]))) {
+ return false;
+ }
+
+ if (!(vector = LLVMBuildInsertElement(comp_ctx->builder, vector, element,
+ lane, "dst"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, vector, "result");
+}
+
+bool
+aot_compile_simd_load_zero(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset)
+{
+ LLVMValueRef element, result, mask;
+ uint32 opcode_index = opcode - SIMD_v128_load32_zero;
+ uint32 data_lengths[] = { 4, 8 };
+ LLVMTypeRef element_ptr_types[] = { INT32_PTR_TYPE, INT64_PTR_TYPE };
+ LLVMTypeRef element_data_types[] = { I32_TYPE, I64_TYPE };
+ LLVMValueRef zero[] = {
+ LLVM_CONST(i32x4_vec_zero),
+ LLVM_CONST(i64x2_vec_zero),
+ };
+ LLVMValueRef undef[] = {
+ LLVM_CONST(i32x4_undef),
+ LLVM_CONST(i64x2_undef),
+ };
+ uint32 mask_length[] = { 4, 2 };
+ LLVMValueRef mask_element[][4] = {
+ { LLVM_CONST(i32_zero), LLVM_CONST(i32_four), LLVM_CONST(i32_five),
+ LLVM_CONST(i32_six) },
+ { LLVM_CONST(i32_zero), LLVM_CONST(i32_two) },
+ };
+
+ bh_assert(opcode_index < 2);
+
+ if (!(element = simd_load(comp_ctx, func_ctx, align, offset,
+ data_lengths[opcode_index],
+ element_ptr_types[opcode_index],
+ element_data_types[opcode_index]))) {
+ return false;
+ }
+
+ if (!(result =
+ LLVMBuildInsertElement(comp_ctx->builder, undef[opcode_index],
+ element, I32_ZERO, "vector"))) {
+ HANDLE_FAILURE("LLVMBuildInsertElement");
+ return false;
+ }
+
+ /* fill in other lanes with zero */
+ if (!(mask = LLVMConstVector(mask_element[opcode_index],
+ mask_length[opcode_index]))) {
+ HANDLE_FAILURE("LLConstVector");
+ return false;
+ }
+
+ if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result,
+ zero[opcode_index], mask,
+ "fill_in_zero"))) {
+ HANDLE_FAILURE("LLVMBuildShuffleVector");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+/* data_length in bytes */
+static bool
+simd_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 align,
+ uint32 offset, uint32 data_length, LLVMValueRef value,
+ LLVMTypeRef value_ptr_type)
+{
+ LLVMValueRef maddr, result;
+
+ if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset,
+ data_length)))
+ return false;
+
+ if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, value_ptr_type,
+ "data_ptr"))) {
+ HANDLE_FAILURE("LLVMBuildBitCast");
+ return false;
+ }
+
+ if (!(result = LLVMBuildStore(comp_ctx->builder, value, maddr))) {
+ HANDLE_FAILURE("LLVMBuildStore");
+ return false;
+ }
+
+ LLVMSetAlignment(result, 1);
+
+ return true;
+}
+
+bool
+aot_compile_simd_v128_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset)
+{
+ LLVMValueRef value;
+
+ POP_V128(value);
+
+ return simd_store(comp_ctx, func_ctx, align, offset, 16, value,
+ V128_PTR_TYPE);
+fail:
+ return false;
+}
+
+bool
+aot_compile_simd_store_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset,
+ uint8 lane_id)
+{
+ LLVMValueRef element, vector;
+ uint32 data_lengths[] = { 1, 2, 4, 8 };
+ LLVMTypeRef element_ptr_types[] = { INT8_PTR_TYPE, INT16_PTR_TYPE,
+ INT32_PTR_TYPE, INT64_PTR_TYPE };
+ uint32 opcode_index = opcode - SIMD_v128_store8_lane;
+ LLVMTypeRef vector_types[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
+ V128_i32x4_TYPE, V128_i64x2_TYPE };
+ LLVMValueRef lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id);
+
+ bh_assert(opcode_index < 4);
+
+ if (!(vector = simd_pop_v128_and_bitcast(
+ comp_ctx, func_ctx, vector_types[opcode_index], "src"))) {
+ return false;
+ }
+
+ if (!(element = LLVMBuildExtractElement(comp_ctx->builder, vector, lane,
+ "element"))) {
+ HANDLE_FAILURE("LLVMBuildExtractElement");
+ return false;
+ }
+
+ return simd_store(comp_ctx, func_ctx, align, offset,
+ data_lengths[opcode_index], element,
+ element_ptr_types[opcode_index]);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.h
new file mode 100644
index 000000000..fd118ec1b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_load_store.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_LOAD_STORE_H_
+#define _SIMD_LOAD_STORE_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_v128_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset);
+
+bool
+aot_compile_simd_load_extend(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset);
+
+bool
+aot_compile_simd_load_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset);
+
+bool
+aot_compile_simd_load_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset,
+ uint8 lane_id);
+
+bool
+aot_compile_simd_load_zero(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset);
+
+bool
+aot_compile_simd_v128_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint32 align, uint32 offset);
+
+bool
+aot_compile_simd_store_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ uint8 opcode, uint32 align, uint32 offset,
+ uint8 lane_id);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_LOAD_STORE_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.c
new file mode 100644
index 000000000..1de4520a7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "simd_sat_int_arith.h"
+#include "simd_common.h"
+#include "../aot_emit_exception.h"
+#include "../../aot/aot_runtime.h"
+
+static bool
+simd_sat_int_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+ LLVMTypeRef vector_type, const char *intrinsics)
+{
+ LLVMValueRef lhs, rhs, result;
+ LLVMTypeRef param_types[2];
+
+ if (!(rhs =
+ simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+ || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+ "lhs"))) {
+ return false;
+ }
+
+ param_types[0] = vector_type;
+ param_types[1] = vector_type;
+
+ if (!(result =
+ aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsics,
+ vector_type, param_types, 2, lhs, rhs))) {
+ HANDLE_FAILURE("LLVMBuildCall");
+ return false;
+ }
+
+ return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+}
+
+bool
+aot_compile_simd_i8x16_saturate(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed)
+{
+ char *intrinsics[][2] = {
+ { "llvm.sadd.sat.v16i8", "llvm.uadd.sat.v16i8" },
+ { "llvm.ssub.sat.v16i8", "llvm.usub.sat.v16i8" },
+ };
+
+ return simd_sat_int_arith(comp_ctx, func_ctx, V128_i8x16_TYPE,
+ is_signed ? intrinsics[arith_op][0]
+ : intrinsics[arith_op][1]);
+}
+
+bool
+aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed)
+{
+ char *intrinsics[][2] = {
+ { "llvm.sadd.sat.v8i16", "llvm.uadd.sat.v8i16" },
+ { "llvm.ssub.sat.v8i16", "llvm.usub.sat.v8i16" },
+ };
+
+ return simd_sat_int_arith(comp_ctx, func_ctx, V128_i16x8_TYPE,
+ is_signed ? intrinsics[arith_op][0]
+ : intrinsics[arith_op][1]);
+}
+
+bool
+aot_compile_simd_i32x4_saturate(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed)
+{
+ char *intrinsics[][2] = {
+ { "llvm.sadd.sat.v4i32", "llvm.uadd.sat.v4i32" },
+ { "llvm.ssub.sat.v4i32", "llvm.usub.sat.v4i32" },
+ };
+
+ return simd_sat_int_arith(comp_ctx, func_ctx, V128_i16x8_TYPE,
+ is_signed ? intrinsics[arith_op][0]
+ : intrinsics[arith_op][1]);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.h
new file mode 100644
index 000000000..e30acaaf4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_sat_int_arith.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SIMD_SAT_INT_ARITH_H_
+#define _SIMD_SAT_INT_ARITH_H_
+
+#include "../aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_simd_i8x16_saturate(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed);
+
+bool
+aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed);
+
+bool
+aot_compile_simd_i32x4_saturate(AOTCompContext *comp_ctx,
+ AOTFuncContext *func_ctx,
+ V128Arithmetic arith_op, bool is_signed);
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _SIMD_SAT_INT_ARITH_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/classic_interpreter.MD b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/classic_interpreter.MD
new file mode 100644
index 000000000..a607758e2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/classic_interpreter.MD
@@ -0,0 +1,5 @@
+# Classic interpreter
+
+## stack format
+
+![](./images/stack_format_ci.svg) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/export_function.excalidraw b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/export_function.excalidraw
new file mode 100644
index 000000000..b983af05b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/export_function.excalidraw
@@ -0,0 +1,5695 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
+ "elements": [
+ {
+ "type": "rectangle",
+ "version": 469,
+ "versionNonce": 587617691,
+ "isDeleted": false,
+ "id": "YQFdEhDm9LI_5UD2YjLU-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 238.99996948242188,
+ "y": 207.16673278808577,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 221.3333740234375,
+ "height": 94.629648844401,
+ "seed": 1964509979,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 318,
+ "versionNonce": 929539477,
+ "isDeleted": false,
+ "id": "pDkkkqvgrizIP6AYdFbkj",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 239.66665649414062,
+ "y": 161.83335876464827,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 96,
+ "height": 19,
+ "seed": 278267925,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModule",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule"
+ },
+ {
+ "type": "rectangle",
+ "version": 592,
+ "versionNonce": 276752955,
+ "isDeleted": false,
+ "id": "awCpIZpFN-gQRBgh6iG1X",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 228.33334350585938,
+ "y": 191.50007629394514,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 247.11109754774304,
+ "height": 265.6667175292969,
+ "seed": 1908273083,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 411,
+ "versionNonce": 1793600245,
+ "isDeleted": false,
+ "id": "TOmX9MwwNOgbfjNJ8V8j7",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 239.4444953070747,
+ "y": 233.9815283881292,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 211,
+ "height": 56,
+ "seed": 86392181,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "2NQmRBF_NE2Myp3-jqLfT",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": " WASMTable *tables;\n WASMMemory *memories;\n WASMGlobal *globals;",
+ "baseline": 52,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " WASMTable *tables;\n WASMMemory *memories;\n WASMGlobal *globals;"
+ },
+ {
+ "type": "text",
+ "version": 390,
+ "versionNonce": 1283272731,
+ "isDeleted": false,
+ "id": "FPUGB-iP7ep91gfoTuV2d",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 289.3334045410156,
+ "y": 374.1667327880857,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 165,
+ "height": 19,
+ "seed": 504570933,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "OdDm5a5O_NIoZbF3u0c0H",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMExport *exports;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMExport *exports;"
+ },
+ {
+ "type": "rectangle",
+ "version": 371,
+ "versionNonce": 692171541,
+ "isDeleted": false,
+ "id": "iP-OL8X-L4CE8z9CTp9qG",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 243.66677856445312,
+ "y": 359.5001068115232,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 216,
+ "height": 42.6666259765625,
+ "seed": 1531454875,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 336,
+ "versionNonce": 1261860027,
+ "isDeleted": false,
+ "id": "jkgMB1VHPK6x-xD6Wuey7",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 258.3335266113281,
+ "y": 370.16679382324196,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 15.33331298828125,
+ "height": 22.66668701171875,
+ "seed": 2028656021,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 286,
+ "versionNonce": 1775181787,
+ "isDeleted": false,
+ "id": "v4paccURicZAp-WeQNnlQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 585.7036675347218,
+ "y": 278.944342719184,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 156,
+ "height": 128.33334350585938,
+ "seed": 766182741,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 176,
+ "versionNonce": 907517781,
+ "isDeleted": false,
+ "id": "blxQLl_yf7DMD76qHC5rc",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 587.9629041883677,
+ "y": 256.3147176106771,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 97,
+ "height": 19,
+ "seed": 1409110677,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "OdDm5a5O_NIoZbF3u0c0H",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMExport",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMExport"
+ },
+ {
+ "type": "text",
+ "version": 216,
+ "versionNonce": 271871099,
+ "isDeleted": false,
+ "id": "xQPYBI_XdfyZkh2-U_YQB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 617.3703240288627,
+ "y": 289.2776862250434,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 88,
+ "height": 19,
+ "seed": 1776880725,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "char *name;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "char *name;"
+ },
+ {
+ "type": "text",
+ "version": 241,
+ "versionNonce": 217246901,
+ "isDeleted": false,
+ "id": "lB_sRHE0gMYdFdpT2Dvja",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 614.7036370171439,
+ "y": 321.6110602484809,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 75,
+ "height": 19,
+ "seed": 1312575355,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "uint8 kind;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "uint8 kind;"
+ },
+ {
+ "type": "text",
+ "version": 230,
+ "versionNonce": 562504987,
+ "isDeleted": false,
+ "id": "SQI7khDAbJL0pLh0deiej",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 610.0369805230033,
+ "y": 354.944342719184,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 93,
+ "height": 19,
+ "seed": 2114894261,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "C_HvFqwDiW4wGe01QNKFg",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "uint32 index;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "uint32 index;"
+ },
+ {
+ "type": "rectangle",
+ "version": 188,
+ "versionNonce": 2042465813,
+ "isDeleted": false,
+ "id": "sqBZGoR4vKErEsSE7jSJk",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 601.0370110405812,
+ "y": 284.9443579779731,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 120.66668701171875,
+ "height": 29.666671752929688,
+ "seed": 1817827573,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 255,
+ "versionNonce": 892979643,
+ "isDeleted": false,
+ "id": "xy3rvXCHxwYSjuQZAaa0Y",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 601.7036675347218,
+ "y": 320.6110602484809,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 118,
+ "height": 26.33331298828125,
+ "seed": 1394813013,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 190,
+ "versionNonce": 728564597,
+ "isDeleted": false,
+ "id": "noIblgsWe1zKM-bENF8Ev",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 599.0370110405812,
+ "y": 351.61102973090277,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 126,
+ "height": 29.666656494140625,
+ "seed": 410891355,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 174,
+ "versionNonce": 1447480533,
+ "isDeleted": false,
+ "id": "q8XZjMjkc5oaR7KNqOcGF",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 654.3703545464408,
+ "y": 385.7777167426215,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 20,
+ "height": 19,
+ "seed": 1931744507,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "[0]",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 177,
+ "versionNonce": 804837115,
+ "isDeleted": false,
+ "id": "cywWwhg521rh-6jpDBbTE",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 586.3703240288625,
+ "y": 407.94437323676215,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 158,
+ "height": 42,
+ "seed": 19921979,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "8dd-iKzlb9Z4V1eqnx9a-"
+ }
+ ],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 152,
+ "versionNonce": 165702197,
+ "isDeleted": false,
+ "id": "8dd-iKzlb9Z4V1eqnx9a-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 655.3703240288627,
+ "y": 419.44437323676215,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 20,
+ "height": 19,
+ "seed": 1593993467,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887720,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "[1]",
+ "baseline": 15,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "cywWwhg521rh-6jpDBbTE",
+ "originalText": "[1]"
+ },
+ {
+ "type": "rectangle",
+ "version": 191,
+ "versionNonce": 1381646235,
+ "isDeleted": false,
+ "id": "SsP3zaE3LuSyRa2Ma4ffB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 587.3703240288625,
+ "y": 450.94437323676215,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 158,
+ "height": 42,
+ "seed": 1216947029,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Ux1Agae75_DS0veGHXMuH"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 169,
+ "versionNonce": 1193237397,
+ "isDeleted": false,
+ "id": "Ux1Agae75_DS0veGHXMuH",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 654.3703240288627,
+ "y": 462.44437323676215,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 24,
+ "height": 19,
+ "seed": 982329467,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "[...]",
+ "baseline": 15,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "SsP3zaE3LuSyRa2Ma4ffB",
+ "originalText": "[...]"
+ },
+ {
+ "type": "text",
+ "version": 248,
+ "versionNonce": 1555249749,
+ "isDeleted": false,
+ "id": "o7FaW1SjzOKpt86xZNbly",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -71.58126068115234,
+ "y": 146.11661834716801,
+ "strokeColor": "#e67700",
+ "backgroundColor": "transparent",
+ "width": 171,
+ "height": 19,
+ "seed": 1768482683,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModuleInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 131,
+ "versionNonce": 1297489444,
+ "isDeleted": false,
+ "id": "MC9rQuxIk7iVRtsas7ICs",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -73.99992370605469,
+ "y": 180.9666107177734,
+ "strokeColor": "#d9480f",
+ "backgroundColor": "transparent",
+ "width": 210.66668701171875,
+ "height": 314.33334350585943,
+ "seed": 1805099445,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558426546,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 473,
+ "versionNonce": 1484728732,
+ "isDeleted": false,
+ "id": "6pGqkyRY8AHL4k5LTJ0Yl",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -51.000274658203125,
+ "y": 425.4667785644531,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174.66668701171875,
+ "height": 31.666625976562507,
+ "seed": 957429083,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558303924,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 499,
+ "versionNonce": 1368837668,
+ "isDeleted": false,
+ "id": "cDohxEkx3HhhoX-zcCc9Q",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -45.666961669921875,
+ "y": 433.1334350585937,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 63676885,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558303924,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 208,
+ "versionNonce": 1386190364,
+ "isDeleted": false,
+ "id": "kOP_SYX2hDGyTbKOLrSY7",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -25.66693115234375,
+ "y": 429.9667785644531,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 115,
+ "height": 20,
+ "seed": 697815547,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "xGVX08X1n0JU0OA60_t9A",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679558303924,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "export_tables",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "export_tables"
+ },
+ {
+ "type": "rectangle",
+ "version": 534,
+ "versionNonce": 1960518965,
+ "isDeleted": false,
+ "id": "FnISIa4MPRb3okZ9nUHSQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -58.66651916503906,
+ "y": 359.8333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174.66668701171875,
+ "height": 31.666625976562507,
+ "seed": 1723426171,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 562,
+ "versionNonce": 901559451,
+ "isDeleted": false,
+ "id": "KPco9Nm_8Olmg0Uq3NVQ1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -53.33320617675781,
+ "y": 367.5000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 135660469,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 260,
+ "versionNonce": 420132501,
+ "isDeleted": false,
+ "id": "8KE83CX20gDJQwJueCKwN",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -39.33323669433594,
+ "y": 365.66668701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 131,
+ "height": 20,
+ "seed": 788856347,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "v2uiV8UbBxa6_yEOLAehf",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "export_memories",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "export_memories"
+ },
+ {
+ "type": "rectangle",
+ "version": 477,
+ "versionNonce": 1527867707,
+ "isDeleted": false,
+ "id": "_CbJcjswexYEsNuWct5mC",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -51.99998474121094,
+ "y": 189.83334350585938,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174.66668701171875,
+ "height": 31.666625976562507,
+ "seed": 1344002453,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 505,
+ "versionNonce": 671161333,
+ "isDeleted": false,
+ "id": "hGw4Pp4LnIpkfSfU4PeRb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -46.66667175292969,
+ "y": 197.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 861402683,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 213,
+ "versionNonce": 690391515,
+ "isDeleted": false,
+ "id": "67MrbK1oKDTBrmUzIQlr1",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -26.666641235351562,
+ "y": 194.33334350585938,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 118,
+ "height": 20,
+ "seed": 1190518517,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "export_globals",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "export_globals"
+ },
+ {
+ "type": "rectangle",
+ "version": 400,
+ "versionNonce": 1237570901,
+ "isDeleted": false,
+ "id": "eMcaE0yc0BCbsQ4MrLuGP",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -51.33323669433594,
+ "y": 271.8333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174.66668701171875,
+ "height": 31.666625976562507,
+ "seed": 1337283029,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 429,
+ "versionNonce": 84842107,
+ "isDeleted": false,
+ "id": "rW76UbdBzelN0CWuqQjTc",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -45.99992370605469,
+ "y": 279.5000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 778117627,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "4eMPasZehGc58H7vVusCf",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 136,
+ "versionNonce": 162030261,
+ "isDeleted": false,
+ "id": "NfPonNQyhbRCCPh50Ed7I",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -25.999893188476562,
+ "y": 276.3333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 136,
+ "height": 20,
+ "seed": 1026969397,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "4eMPasZehGc58H7vVusCf",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "export_functions",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "export_functions"
+ },
+ {
+ "type": "text",
+ "version": 121,
+ "versionNonce": 227282715,
+ "isDeleted": false,
+ "id": "ILDnCNxtBv4qdrhMb3QoZ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -365.33335876464844,
+ "y": 193.1666259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 193,
+ "height": 19,
+ "seed": 282525979,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMExportFuncInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMExportFuncInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 201,
+ "versionNonce": 1817461781,
+ "isDeleted": false,
+ "id": "2agHBzF-91Fb2ws0hYObd",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -354.33335876464844,
+ "y": 223.83334350585938,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 177.33331298828122,
+ "height": 121.00006103515625,
+ "seed": 1290367509,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "4eMPasZehGc58H7vVusCf",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 176,
+ "versionNonce": 1961256348,
+ "isDeleted": false,
+ "id": "aZL7IU5LEszDJmyyWcmtp",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -340.6666717529297,
+ "y": 239.83328247070312,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 117,
+ "height": 31,
+ "seed": 1714300347,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "P3_9LebxO4r1Nud8xISGk"
+ },
+ {
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679558297714,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 194,
+ "versionNonce": 2136035876,
+ "isDeleted": false,
+ "id": "P3_9LebxO4r1Nud8xISGk",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -334.6666717529297,
+ "y": 244.83328247070312,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 105,
+ "height": 21,
+ "seed": 2004641653,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297727,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "char* name ",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "aZL7IU5LEszDJmyyWcmtp",
+ "originalText": "char* name "
+ },
+ {
+ "type": "diamond",
+ "version": 159,
+ "versionNonce": 1002521691,
+ "isDeleted": false,
+ "id": "qdga26-o2AGoXkwH2yP4N",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -323.00001525878906,
+ "y": 284.1666259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 14.666656494140625,
+ "height": 17.666656494140625,
+ "seed": 444053083,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 216,
+ "versionNonce": 1328022229,
+ "isDeleted": false,
+ "id": "2onXRIpW3Znosk6O46QtY",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -338.33335876464844,
+ "y": 276.49993896484375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 128,
+ "height": 38,
+ "seed": 852078805,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Zrwh0TsrNxBSNhpJZIqbu"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 183,
+ "versionNonce": 1455378972,
+ "isDeleted": false,
+ "id": "Zrwh0TsrNxBSNhpJZIqbu",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -305.83335876464844,
+ "y": 285.49993896484375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 63,
+ "height": 21,
+ "seed": 2089169659,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297728,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "function",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "2onXRIpW3Znosk6O46QtY",
+ "originalText": "function"
+ },
+ {
+ "type": "arrow",
+ "version": 505,
+ "versionNonce": 2099961909,
+ "isDeleted": false,
+ "id": "nG4vs8WttuFFZPXDKIdNr",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -320.33335876464844,
+ "y": 293.49993896484375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 111.00001525878906,
+ "height": 184.2470495648475,
+ "seed": 476499509,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "7JcYtZ-KQ0WF1SDFDwvcV",
+ "gap": 1.2531640581994319,
+ "focus": -0.8059388021902064
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -111.00001525878906,
+ 33.166717529296875
+ ],
+ [
+ -35.26115412319115,
+ 184.2470495648475
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 531,
+ "versionNonce": 363532693,
+ "isDeleted": false,
+ "id": "7MNv-pmgV4-8yJ5lIFY1U",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 496.5186225043402,
+ "y": 71.31480577256946,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 235,
+ "height": 149,
+ "seed": 2074251419,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "type": "arrow"
+ },
+ {
+ "id": "2NQmRBF_NE2Myp3-jqLfT",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "name: shown to external\nindex: refer to item idx for export \n in current kind\nkind: total 4 export kinds:\n- function\n- globals\n- memory\n- table",
+ "baseline": 145,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "name: shown to external\nindex: refer to item idx for export \n in current kind\nkind: total 4 export kinds:\n- function\n- globals\n- memory\n- table"
+ },
+ {
+ "type": "rectangle",
+ "version": 81,
+ "versionNonce": 997735995,
+ "isDeleted": false,
+ "id": "orpW0tFerpELyreVDruzO",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -353.3333740234375,
+ "y": 343.99998474121094,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 940489147,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "KlcGzdua5BpLa_-0RGeFO"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 53,
+ "versionNonce": 1965780388,
+ "isDeleted": false,
+ "id": "KlcGzdua5BpLa_-0RGeFO",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -274.3333740234375,
+ "y": 350.1666564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 22,
+ "height": 21,
+ "seed": 1399452699,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297729,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[1]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "orpW0tFerpELyreVDruzO",
+ "originalText": "[1]"
+ },
+ {
+ "type": "text",
+ "version": 71,
+ "versionNonce": 1609219803,
+ "isDeleted": false,
+ "id": "da0XYl9R6gkV-BQ4X1JdF",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -278.166748046875,
+ "y": 324.33338928222656,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 848835675,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 109,
+ "versionNonce": 528755579,
+ "isDeleted": false,
+ "id": "oVhH9XqC6rs2uaPMH4x2B",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -353.0001220703125,
+ "y": 377.50006103515625,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 1099143605,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "wu6BDVXXPWLo-Z-l7TYGW"
+ },
+ {
+ "id": "Eda9W8eaZom6PATRAm5EX",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 83,
+ "versionNonce": 1472638620,
+ "isDeleted": false,
+ "id": "wu6BDVXXPWLo-Z-l7TYGW",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -278.5001220703125,
+ "y": 383.66673278808594,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 21,
+ "seed": 1029949467,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297730,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "oVhH9XqC6rs2uaPMH4x2B",
+ "originalText": "[...]"
+ },
+ {
+ "type": "rectangle",
+ "version": 134,
+ "versionNonce": 1882593572,
+ "isDeleted": false,
+ "id": "t8xOhAVyJcx51xJsmWC6j",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -352.33331298828125,
+ "y": 408.5001220703125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 31,
+ "seed": 883564757,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "F09zazRYIO_G3oM7DmBbr"
+ },
+ {
+ "id": "Eda9W8eaZom6PATRAm5EX",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679558297730,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 111,
+ "versionNonce": 1756265244,
+ "isDeleted": false,
+ "id": "F09zazRYIO_G3oM7DmBbr",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -274.83331298828125,
+ "y": 418.5001220703125,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 25,
+ "height": 21,
+ "seed": 1529135867,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297738,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[n]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "t8xOhAVyJcx51xJsmWC6j",
+ "originalText": "[n]"
+ },
+ {
+ "type": "line",
+ "version": 284,
+ "versionNonce": 350603451,
+ "isDeleted": false,
+ "id": "XphCtXmoQONIDWT15UPmf",
+ "fillStyle": "hachure",
+ "strokeWidth": 4,
+ "strokeStyle": "dotted",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 169.00015258789057,
+ "y": 21.389623853895444,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 1.66656494140625,
+ "height": 838.3330154418943,
+ "seed": 395797243,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 1.66656494140625,
+ 838.3330154418943
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 156,
+ "versionNonce": 1808036981,
+ "isDeleted": false,
+ "id": "4eMPasZehGc58H7vVusCf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -40.66667175292969,
+ "y": 278.5517677558588,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 133.01236173861167,
+ "height": 54.587889349881976,
+ "seed": 526956341,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "NfPonNQyhbRCCPh50Ed7I",
+ "focus": -0.6897037086038879,
+ "gap": 14.666778564453125
+ },
+ "endBinding": {
+ "elementId": "2agHBzF-91Fb2ws0hYObd",
+ "focus": -1.0127197558064842,
+ "gap": 3.3210122848258408
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -133.01236173861167,
+ -54.587889349881976
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 227,
+ "versionNonce": 2017655131,
+ "isDeleted": false,
+ "id": "7JcYtZ-KQ0WF1SDFDwvcV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -362,
+ "y": 478.3334655761719,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 223.3334655761719,
+ "height": 33.00015258789055,
+ "seed": 857261429,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nG4vs8WttuFFZPXDKIdNr",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 351,
+ "versionNonce": 1552424405,
+ "isDeleted": false,
+ "id": "QLOWRmBSKHUu_NrX66JPt",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -355.3333740234375,
+ "y": 486.00006103515625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 208,
+ "height": 20,
+ "seed": 513338651,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nG4vs8WttuFFZPXDKIdNr",
+ "type": "arrow"
+ },
+ {
+ "id": "Vhva2LNBhtrohj4Y3bGV9",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(refer to function diagam)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(refer to function diagam)"
+ },
+ {
+ "type": "text",
+ "version": 94,
+ "versionNonce": 636556795,
+ "isDeleted": false,
+ "id": "R3bNKi3-D-UlbcoafRHR5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -40.6666259765625,
+ "y": 316.9998779296875,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 154,
+ "height": 20,
+ "seed": 1038062939,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Eda9W8eaZom6PATRAm5EX",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "export_func_count",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "export_func_count"
+ },
+ {
+ "type": "arrow",
+ "version": 162,
+ "versionNonce": 1037015861,
+ "isDeleted": false,
+ "id": "Eda9W8eaZom6PATRAm5EX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -51.354154838890395,
+ "y": 333.9999084472656,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 192.10502044691845,
+ "height": 89.91317165306509,
+ "seed": 518031893,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "mZobbVjOOfzbAK_1alOcK",
+ "focus": 0.6974503894293331,
+ "gap": 1
+ },
+ "endBinding": {
+ "elementId": "oVhH9XqC6rs2uaPMH4x2B",
+ "focus": 0.8116332021918504,
+ "gap": 14.079675559315092
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -81.97918866696898,
+ 54.666717529296875
+ ],
+ [
+ -192.10502044691845,
+ 89.91317165306509
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 71,
+ "versionNonce": 2013293717,
+ "isDeleted": false,
+ "id": "mZobbVjOOfzbAK_1alOcK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -50.66668701171875,
+ "y": 311.333251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 172.666748046875,
+ "height": 31.66668701171875,
+ "seed": 1172380085,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Eda9W8eaZom6PATRAm5EX",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 417,
+ "versionNonce": 1255150069,
+ "isDeleted": false,
+ "id": "YyGWHpfM0OE4uzGAFwZ12",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 484.1481289333766,
+ "y": 65.53704833984384,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 287.70376925998266,
+ "height": 162.29637824164502,
+ "seed": 274906523,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 1048,
+ "versionNonce": 392819675,
+ "isDeleted": false,
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 743.579402430669,
+ "y": 225.04108862166348,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 21.48420572561895,
+ "height": 53.29342358325337,
+ "seed": 1380550619,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "7MNv-pmgV4-8yJ5lIFY1U",
+ "focus": -0.6782971803849929,
+ "gap": 12.953770184814061
+ },
+ "endBinding": {
+ "elementId": "sqBZGoR4vKErEsSE7jSJk",
+ "focus": 0.7448990456524555,
+ "gap": 10.515841746169144
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 10.124343093419043,
+ 26.347898601643806
+ ],
+ [
+ -11.359862632199906,
+ 53.29342358325337
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 264,
+ "versionNonce": 1665403733,
+ "isDeleted": false,
+ "id": "sRzZXOvjblsPsAM89sUXa",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -705.3333892822266,
+ "y": 113.58320617675781,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 192,
+ "height": 19,
+ "seed": 700308213,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMExportGlobInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMExportGlobInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 348,
+ "versionNonce": 1800716411,
+ "isDeleted": false,
+ "id": "xWPtNuyAqazMMUyouKnhf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -694.3333892822266,
+ "y": 144.2499237060547,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 177.33331298828122,
+ "height": 121.00006103515625,
+ "seed": 1037646555,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "RxhU0Qr-hmqzklRZdxsvn",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 323,
+ "versionNonce": 467621028,
+ "isDeleted": false,
+ "id": "7uYVutqCDMjhS1LtgrSpl",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -680.6667022705078,
+ "y": 160.24986267089844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 117,
+ "height": 31,
+ "seed": 328250453,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "PlRFeDiD1tywOAk_rJgHg"
+ }
+ ],
+ "updated": 1679558297741,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 337,
+ "versionNonce": 334018460,
+ "isDeleted": false,
+ "id": "PlRFeDiD1tywOAk_rJgHg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -674.6667022705078,
+ "y": 165.24986267089844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 105,
+ "height": 21,
+ "seed": 843261819,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297749,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "char* name ",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "7uYVutqCDMjhS1LtgrSpl",
+ "originalText": "char* name "
+ },
+ {
+ "type": "diamond",
+ "version": 301,
+ "versionNonce": 2143222293,
+ "isDeleted": false,
+ "id": "01IysLeEkWSJyxI9NbVb8",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -663.0000457763672,
+ "y": 204.5832061767578,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 14.666656494140625,
+ "height": 17.666656494140625,
+ "seed": 1686200757,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 360,
+ "versionNonce": 458563003,
+ "isDeleted": false,
+ "id": "lWjh1xjt4eB1XKwJJx59D",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -678.3333892822266,
+ "y": 196.91651916503906,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 128,
+ "height": 38,
+ "seed": 671514651,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "VQ0ymOLfMpjFiupR01ZFb"
+ }
+ ],
+ "updated": 1679555887721,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 327,
+ "versionNonce": 97853476,
+ "isDeleted": false,
+ "id": "VQ0ymOLfMpjFiupR01ZFb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -637.3333892822266,
+ "y": 205.91651916503906,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 46,
+ "height": 21,
+ "seed": 565535509,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297750,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "global",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "lWjh1xjt4eB1XKwJJx59D",
+ "originalText": "global"
+ },
+ {
+ "type": "arrow",
+ "version": 624,
+ "versionNonce": 2147462747,
+ "isDeleted": false,
+ "id": "E_RGDiJbGUf1aNH6jDnvz",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -660.3333892822266,
+ "y": 213.91651916503906,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 111.00001525878906,
+ "height": 176.67764729852638,
+ "seed": 152421563,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "KWKN5CpCB6zVtYZd6txj9",
+ "focus": -0.8240578974308156,
+ "gap": 7.457318223231596
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -111.00001525878906,
+ 33.166717529296875
+ ],
+ [
+ -17.790676987880033,
+ 176.67764729852638
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 225,
+ "versionNonce": 1372149301,
+ "isDeleted": false,
+ "id": "uLMWTXI90CGAIKI4zHJML",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -693.3334045410156,
+ "y": 264.41656494140625,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 1208836565,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "AGXBiW0dSLHn3nGEzduCY"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 196,
+ "versionNonce": 1168598044,
+ "isDeleted": false,
+ "id": "AGXBiW0dSLHn3nGEzduCY",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -614.3334045410156,
+ "y": 270.58323669433594,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 22,
+ "height": 21,
+ "seed": 324145659,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297750,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[1]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "uLMWTXI90CGAIKI4zHJML",
+ "originalText": "[1]"
+ },
+ {
+ "type": "text",
+ "version": 213,
+ "versionNonce": 2064304021,
+ "isDeleted": false,
+ "id": "QvT_bIR-th1HBXIOu8j7Y",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -618.1667785644531,
+ "y": 244.74996948242188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 269246261,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 253,
+ "versionNonce": 630646843,
+ "isDeleted": false,
+ "id": "zom5ZNn_gBWzVI1PMMYQo",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -693.0001525878906,
+ "y": 297.91664123535156,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 215227035,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "U2e2lWVjWzkRt9x6FkfeD"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 226,
+ "versionNonce": 1443199908,
+ "isDeleted": false,
+ "id": "U2e2lWVjWzkRt9x6FkfeD",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -618.5001525878906,
+ "y": 304.08331298828125,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 21,
+ "seed": 1845801109,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297751,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "zom5ZNn_gBWzVI1PMMYQo",
+ "originalText": "[...]"
+ },
+ {
+ "type": "rectangle",
+ "version": 278,
+ "versionNonce": 333217948,
+ "isDeleted": false,
+ "id": "IbfRch-fWorg9yld9Wih5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -692.3333435058594,
+ "y": 328.9167022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 31,
+ "seed": 1716260667,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "So5vnnPiQUj6m6ZH6HSMP"
+ }
+ ],
+ "updated": 1679558297752,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 254,
+ "versionNonce": 111044388,
+ "isDeleted": false,
+ "id": "So5vnnPiQUj6m6ZH6HSMP",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -614.8333435058594,
+ "y": 338.9167022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 25,
+ "height": 21,
+ "seed": 2141967861,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297758,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[n]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "IbfRch-fWorg9yld9Wih5",
+ "originalText": "[n]"
+ },
+ {
+ "type": "rectangle",
+ "version": 257,
+ "versionNonce": 494949755,
+ "isDeleted": false,
+ "id": "KWKN5CpCB6zVtYZd6txj9",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -670.666748046875,
+ "y": 392.7500457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 196.00015258789062,
+ "height": 39.33346557617187,
+ "seed": 35418075,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "E_RGDiJbGUf1aNH6jDnvz",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 415,
+ "versionNonce": 964039605,
+ "isDeleted": false,
+ "id": "uEz53YqVhDB8JRuE5hMcU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -659.3334655761719,
+ "y": 402.41664123535156,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 164,
+ "height": 20,
+ "seed": 268914517,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMGlobalInstance",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMGlobalInstance"
+ },
+ {
+ "type": "text",
+ "version": 236,
+ "versionNonce": 2005417979,
+ "isDeleted": false,
+ "id": "FiGf5f4dzHNrO5L3NMiwT",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -604.5001068115234,
+ "y": 504.4166564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 193,
+ "height": 19,
+ "seed": 1644818613,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "v2uiV8UbBxa6_yEOLAehf",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMExportMemInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMExportMemInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 316,
+ "versionNonce": 1410863413,
+ "isDeleted": false,
+ "id": "tgz_9er4fEh_TbaYDZF6u",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -593.5001068115234,
+ "y": 535.0833740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 177.33331298828122,
+ "height": 121.00006103515625,
+ "seed": 273834267,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 295,
+ "versionNonce": 104467740,
+ "isDeleted": false,
+ "id": "fZ94UaMm9ypc37Hwvn9SX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -579.8334197998047,
+ "y": 551.0833129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 117,
+ "height": 31,
+ "seed": 492048917,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "QBs13zYnt2LZX4M9cdFuH"
+ }
+ ],
+ "updated": 1679558297759,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 308,
+ "versionNonce": 470672036,
+ "isDeleted": false,
+ "id": "QBs13zYnt2LZX4M9cdFuH",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -573.8334197998047,
+ "y": 556.0833129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 105,
+ "height": 21,
+ "seed": 524125627,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297764,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "char* name ",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "fZ94UaMm9ypc37Hwvn9SX",
+ "originalText": "char* name "
+ },
+ {
+ "type": "diamond",
+ "version": 271,
+ "versionNonce": 424590651,
+ "isDeleted": false,
+ "id": "nqJwiZ18KG3vCMfANM8aQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -562.1667633056641,
+ "y": 595.4166564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 14.666656494140625,
+ "height": 17.666656494140625,
+ "seed": 563283829,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 332,
+ "versionNonce": 1978861557,
+ "isDeleted": false,
+ "id": "HEJvi8QjWRiMWcoZPLHIl",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -577.5001068115234,
+ "y": 587.7499694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 128,
+ "height": 38,
+ "seed": 983242331,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "HU6nOicEloKkqYD55hBWR"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 304,
+ "versionNonce": 1580337564,
+ "isDeleted": false,
+ "id": "HU6nOicEloKkqYD55hBWR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -540.5001068115234,
+ "y": 596.7499694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 54,
+ "height": 21,
+ "seed": 554455253,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297765,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "memory",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "HEJvi8QjWRiMWcoZPLHIl",
+ "originalText": "memory"
+ },
+ {
+ "type": "arrow",
+ "version": 546,
+ "versionNonce": 1519927637,
+ "isDeleted": false,
+ "id": "O2ixOO7WSexT4tbgcUDGA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -559.5001068115234,
+ "y": 604.7499694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 111.00001525878906,
+ "height": 176.67764729852638,
+ "seed": 20812539,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "Sn4zW4Qj5F8AgPuajBnRy",
+ "focus": -0.8240578974308156,
+ "gap": 7.457318223231596
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -111.00001525878906,
+ 33.166717529296875
+ ],
+ [
+ -17.790676987880033,
+ 176.67764729852638
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 371,
+ "versionNonce": 1795615355,
+ "isDeleted": false,
+ "id": "XjbCYdp81z8HsAXal748C",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -794.1667785644531,
+ "y": 589.7500152587891,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 190,
+ "height": 20,
+ "seed": 1767206453,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(WASMMemoryInstance*)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(WASMMemoryInstance*)"
+ },
+ {
+ "type": "rectangle",
+ "version": 197,
+ "versionNonce": 1561284277,
+ "isDeleted": false,
+ "id": "8-N4VCgO26s4M3_joLoAg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -592.5001220703125,
+ "y": 655.2500152587891,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 329743259,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "_zHc4H95qdMAwSfBAe4ji"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 167,
+ "versionNonce": 1560407588,
+ "isDeleted": false,
+ "id": "_zHc4H95qdMAwSfBAe4ji",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -513.5001220703125,
+ "y": 661.4166870117188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 22,
+ "height": 21,
+ "seed": 2035539861,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297766,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[1]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "8-N4VCgO26s4M3_joLoAg",
+ "originalText": "[1]"
+ },
+ {
+ "type": "text",
+ "version": 183,
+ "versionNonce": 201175061,
+ "isDeleted": false,
+ "id": "8MK4DV6gTxwniJIipRt0r",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -517.33349609375,
+ "y": 635.5834197998047,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 1577799739,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 225,
+ "versionNonce": 313275,
+ "isDeleted": false,
+ "id": "tIAX2kAFoZpVqZ5qUAx0Z",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -592.1668701171875,
+ "y": 688.7500915527344,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 1463624949,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "2puZDaevwGxRcBgZ-ptc6"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 197,
+ "versionNonce": 1593210396,
+ "isDeleted": false,
+ "id": "2puZDaevwGxRcBgZ-ptc6",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -517.6668701171875,
+ "y": 694.9167633056641,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 21,
+ "seed": 575377627,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297767,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "tIAX2kAFoZpVqZ5qUAx0Z",
+ "originalText": "[...]"
+ },
+ {
+ "type": "rectangle",
+ "version": 250,
+ "versionNonce": 174623140,
+ "isDeleted": false,
+ "id": "N0OFLsAea9yT6OuliaHBO",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -591.5000610351562,
+ "y": 719.7501525878906,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 31,
+ "seed": 647413333,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "q7ppugt7g7qcpJ5yt5OdE"
+ }
+ ],
+ "updated": 1679558297767,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 225,
+ "versionNonce": 360272540,
+ "isDeleted": false,
+ "id": "q7ppugt7g7qcpJ5yt5OdE",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -514.0000610351562,
+ "y": 729.7501525878906,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 25,
+ "height": 21,
+ "seed": 1106951547,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297771,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[n]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "N0OFLsAea9yT6OuliaHBO",
+ "originalText": "[n]"
+ },
+ {
+ "type": "rectangle",
+ "version": 228,
+ "versionNonce": 647779579,
+ "isDeleted": false,
+ "id": "Sn4zW4Qj5F8AgPuajBnRy",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -569.8334655761719,
+ "y": 783.58349609375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 196.00015258789062,
+ "height": 39.33346557617187,
+ "seed": 2117479349,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "O2ixOO7WSexT4tbgcUDGA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 386,
+ "versionNonce": 1606143029,
+ "isDeleted": false,
+ "id": "ADaMm1yoqbZuEu8DJV90L",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -558.5001831054688,
+ "y": 793.2500915527344,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 170,
+ "height": 20,
+ "seed": 1213945371,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMMemoryInstance",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMMemoryInstance"
+ },
+ {
+ "type": "arrow",
+ "version": 134,
+ "versionNonce": 1991153820,
+ "isDeleted": false,
+ "id": "RxhU0Qr-hmqzklRZdxsvn",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -42.66673278808594,
+ "y": 209.66668701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 470.2476914752049,
+ "height": 74.33332824707031,
+ "seed": 1569902293,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679558440686,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "xWPtNuyAqazMMUyouKnhf",
+ "focus": -0.7987290948340221,
+ "gap": 4.085652030654501
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -274,
+ -74.33332824707031
+ ],
+ [
+ -470.2476914752049,
+ -62.82886586813058
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 214,
+ "versionNonce": 1329495445,
+ "isDeleted": false,
+ "id": "v2uiV8UbBxa6_yEOLAehf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -54.615555578359704,
+ "y": 386.91916605443436,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 362.7179252566011,
+ "height": 185.08100179224533,
+ "seed": 1266609179,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "8KE83CX20gDJQwJueCKwN",
+ "focus": 1.000586020261827,
+ "gap": 15.33355712890625
+ },
+ "endBinding": {
+ "elementId": "FiGf5f4dzHNrO5L3NMiwT",
+ "focus": 0.2798025099622999,
+ "gap": 11.916763305664062
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -132.71792525660123,
+ 185.08100179224533
+ ],
+ [
+ -362.7179252566011,
+ 148.41425374537033
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 48,
+ "versionNonce": 304349941,
+ "isDeleted": false,
+ "id": "VoO6IQkaaomgHGzvmdk9L",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -107.00004577636719,
+ "y": 551.3334197998047,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 184,
+ "height": 19,
+ "seed": 2114679797,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMExportTabInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMExportTabInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 353,
+ "versionNonce": 340366043,
+ "isDeleted": false,
+ "id": "cfV2B-j5UbmISEWVZNm_5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -108.33344268798828,
+ "y": 571.0000915527344,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 177.33331298828122,
+ "height": 121.00006103515625,
+ "seed": 2095295067,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 335,
+ "versionNonce": 393196836,
+ "isDeleted": false,
+ "id": "DJ8H7VUIn868NKonqg5gA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -94.66675567626953,
+ "y": 587.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 117,
+ "height": 31,
+ "seed": 1950809301,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "kVEW0vY1bUiCqI5IpX5ML"
+ },
+ {
+ "id": "xGVX08X1n0JU0OA60_t9A",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679558297772,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 346,
+ "versionNonce": 543989532,
+ "isDeleted": false,
+ "id": "kVEW0vY1bUiCqI5IpX5ML",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -88.66675567626953,
+ "y": 592.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 105,
+ "height": 21,
+ "seed": 357803771,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297776,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "char* name ",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "DJ8H7VUIn868NKonqg5gA",
+ "originalText": "char* name "
+ },
+ {
+ "type": "diamond",
+ "version": 308,
+ "versionNonce": 930974133,
+ "isDeleted": false,
+ "id": "gUolYbJIMeIJ_CDZqZFxE",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -77.0000991821289,
+ "y": 631.3333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 14.666656494140625,
+ "height": 17.666656494140625,
+ "seed": 1482332725,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 371,
+ "versionNonce": 809555995,
+ "isDeleted": false,
+ "id": "KIe-ngH8dNcYj_TNLGGa1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -92.33344268798828,
+ "y": 623.6666870117188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 128,
+ "height": 38,
+ "seed": 1675300763,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "NtF7gKcUrgH2P2tIg7Y1I"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 343,
+ "versionNonce": 1636135076,
+ "isDeleted": false,
+ "id": "NtF7gKcUrgH2P2tIg7Y1I",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -49.83344268798828,
+ "y": 632.6666870117188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 43,
+ "height": 21,
+ "seed": 651398037,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297777,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "table",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "KIe-ngH8dNcYj_TNLGGa1",
+ "originalText": "table"
+ },
+ {
+ "type": "rectangle",
+ "version": 236,
+ "versionNonce": 1212488891,
+ "isDeleted": false,
+ "id": "1vaZwH7ZrMW37Kus4v6s8",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -107.33345794677734,
+ "y": 691.1667327880859,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 179070011,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "EcHCtg-lwToZUzRwQtRqU"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 205,
+ "versionNonce": 2017614748,
+ "isDeleted": false,
+ "id": "EcHCtg-lwToZUzRwQtRqU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -28.333457946777344,
+ "y": 697.3334045410156,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 22,
+ "height": 21,
+ "seed": 266817781,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297777,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[1]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "1vaZwH7ZrMW37Kus4v6s8",
+ "originalText": "[1]"
+ },
+ {
+ "type": "text",
+ "version": 220,
+ "versionNonce": 748146011,
+ "isDeleted": false,
+ "id": "xnv1ofRPmnyf7Y75joBRd",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -32.166831970214844,
+ "y": 671.5001373291016,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 1101669595,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 264,
+ "versionNonce": 1671072213,
+ "isDeleted": false,
+ "id": "WhKSAa-6xEaKbFn82X5ru",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -107.00020599365234,
+ "y": 724.6668090820312,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 32.333343505859375,
+ "seed": 555444821,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "-gxwjWzmqS5WDjuFaNKFD"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 235,
+ "versionNonce": 1750580260,
+ "isDeleted": false,
+ "id": "-gxwjWzmqS5WDjuFaNKFD",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -32.500205993652344,
+ "y": 730.8334808349609,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 21,
+ "seed": 543609211,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297778,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "WhKSAa-6xEaKbFn82X5ru",
+ "originalText": "[...]"
+ },
+ {
+ "type": "rectangle",
+ "version": 289,
+ "versionNonce": 925665308,
+ "isDeleted": false,
+ "id": "10EyNsT35ULiP_xM9qv8Y",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -106.3333969116211,
+ "y": 755.6668701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 180,
+ "height": 31,
+ "seed": 457529269,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "x2msRpv4tJnWtZ_hp50wB"
+ }
+ ],
+ "updated": 1679558297778,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 263,
+ "versionNonce": 97818532,
+ "isDeleted": false,
+ "id": "x2msRpv4tJnWtZ_hp50wB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -28.833396911621094,
+ "y": 765.6668701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 25,
+ "height": 21,
+ "seed": 673507867,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297782,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[n]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "10EyNsT35ULiP_xM9qv8Y",
+ "originalText": "[n]"
+ },
+ {
+ "type": "text",
+ "version": 76,
+ "versionNonce": 375904405,
+ "isDeleted": false,
+ "id": "0XlRzavkxOV0TYo3Cru6q",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -307.66673278808594,
+ "y": 651.0002899169922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 171,
+ "height": 19,
+ "seed": 1584858171,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "GXMgwVG5yviwCuQz9-Jdx",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "(WASMTableInstance *)",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(WASMTableInstance *)"
+ },
+ {
+ "type": "arrow",
+ "version": 29,
+ "versionNonce": 1192191803,
+ "isDeleted": false,
+ "id": "GXMgwVG5yviwCuQz9-Jdx",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -67.33335876464844,
+ "y": 639.0001068115234,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 69.3333740234375,
+ "height": 18.333343505859375,
+ "seed": 1221178005,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "0XlRzavkxOV0TYo3Cru6q",
+ "focus": 0.6054948422392628,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -69.3333740234375,
+ 18.333343505859375
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 104,
+ "versionNonce": 1499556260,
+ "isDeleted": false,
+ "id": "xGVX08X1n0JU0OA60_t9A",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -41.0000457763672,
+ "y": 446.7786348431563,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 81.66662597656249,
+ "height": 127.22147196836715,
+ "seed": 1672312955,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679558303924,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "kOP_SYX2hDGyTbKOLrSY7",
+ "focus": 1.0138390872785434,
+ "gap": 15.333114624023438
+ },
+ "endBinding": {
+ "elementId": "DJ8H7VUIn868NKonqg5gA",
+ "focus": -0.9738124716848731,
+ "gap": 15.333290100097656
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -81.66662597656249,
+ 95.22147196836715
+ ],
+ [
+ -68.99999999999999,
+ 127.22147196836715
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 42,
+ "versionNonce": 548718555,
+ "isDeleted": false,
+ "id": "HULjVKYZds5RYxESw_kpb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -343.66673278808594,
+ "y": 454.3334197998047,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 173,
+ "height": 19,
+ "seed": 2051995003,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMFunctionInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunctionInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 116,
+ "versionNonce": 130053973,
+ "isDeleted": false,
+ "id": "kgRAri5TBI6AVeJYwZ0aO",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 291.8626718521118,
+ "y": 615.9665649414064,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 229.3333740234375,
+ "height": 71.33331298828125,
+ "seed": 1363010869,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "GHvOda4nqju-pWyZr-_zS"
+ }
+ ],
+ "updated": 1679555887722,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 70,
+ "versionNonce": 1629299868,
+ "isDeleted": false,
+ "id": "GHvOda4nqju-pWyZr-_zS",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 393.02935886383057,
+ "y": 642.0332214355467,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 27,
+ "height": 21,
+ "seed": 1441133723,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679558297783,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[..]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "kgRAri5TBI6AVeJYwZ0aO",
+ "originalText": "[..]"
+ },
+ {
+ "type": "text",
+ "version": 339,
+ "versionNonce": 1673577653,
+ "isDeleted": false,
+ "id": "oxCwJMeoYhRvkKNPtKeha",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 292.13729763031006,
+ "y": 587.3669616699217,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 211,
+ "height": 20,
+ "seed": 1528133269,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Vhva2LNBhtrohj4Y3bGV9",
+ "type": "arrow"
+ },
+ {
+ "id": "tV8skfel8ww2IgWRNSntj",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMFunction (per module)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunction (per module)"
+ },
+ {
+ "type": "arrow",
+ "version": 77,
+ "versionNonce": 1227017499,
+ "isDeleted": false,
+ "id": "Vhva2LNBhtrohj4Y3bGV9",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -140.00001525878906,
+ "y": 499.6667022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 435.3333740234375,
+ "height": 121,
+ "seed": 975356629,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "QLOWRmBSKHUu_NrX66JPt",
+ "focus": -0.5172589859849054,
+ "gap": 7.3333587646484375
+ },
+ "endBinding": {
+ "elementId": "oxCwJMeoYhRvkKNPtKeha",
+ "focus": -1.2215352226224219,
+ "gap": 13.29974060058612
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 230,
+ 35.33331298828125
+ ],
+ [
+ 435.3333740234375,
+ 121
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 220,
+ "versionNonce": 1520753525,
+ "isDeleted": false,
+ "id": "kby0LOGKuGuYeMzR0L7Pt",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 602.3332366943359,
+ "y": 559.4166564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 47414645,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 241,
+ "versionNonce": 12821717,
+ "isDeleted": false,
+ "id": "J-wnUXeWDAfVNvwQHeW06",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 601.9998626708984,
+ "y": 592.5832824707031,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 785254101,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 226,
+ "versionNonce": 441810683,
+ "isDeleted": false,
+ "id": "qpSAJ6K0S6TvU6i2Uflep",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 625.9998626708984,
+ "y": 600.2499389648438,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1914322171,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "euj5CRuv6EoS2abVhp14P",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 229,
+ "versionNonce": 2130854453,
+ "isDeleted": false,
+ "id": "yCRds2HRNFQhi2l_NRv1E",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 601.6665496826172,
+ "y": 625.9166259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 24142901,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "tV8skfel8ww2IgWRNSntj",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 238,
+ "versionNonce": 451012507,
+ "isDeleted": false,
+ "id": "XQ_n6PzQRK1pjOIbTF09C",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 600.3331756591797,
+ "y": 653.5832824707031,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1465836955,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 219,
+ "versionNonce": 1782985621,
+ "isDeleted": false,
+ "id": "dQpthmaEJfLeEUR4UsOsg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 622.9998626708984,
+ "y": 661.9166259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 2124420501,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 231,
+ "versionNonce": 1796750395,
+ "isDeleted": false,
+ "id": "lRGlqO5nnxQXGumLJpnO9",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 624.3332366943359,
+ "y": 630.8333282470703,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1262844475,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 90,
+ "versionNonce": 516225269,
+ "isDeleted": false,
+ "id": "bCPa9rRVzubIpa31jwl73",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 574.0000152587891,
+ "y": 532.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 177.33334350585938,
+ "seed": 294820597,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "6EZFlJGbMoYN4RDYkSEYP",
+ "type": "arrow"
+ },
+ {
+ "id": "euj5CRuv6EoS2abVhp14P",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 534,
+ "versionNonce": 1457192155,
+ "isDeleted": false,
+ "id": "C_HvFqwDiW4wGe01QNKFg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 715.7036827935111,
+ "y": 367.61115180121527,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00552481453781,
+ "height": 1.0071746818260863,
+ "seed": 1379035003,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "SQI7khDAbJL0pLh0deiej",
+ "focus": 0.39512687910745115,
+ "gap": 12.666702270507812
+ },
+ "endBinding": {
+ "elementId": "2jRIgxhs5VlnfeDeDJXss",
+ "focus": 0.24394927767367422,
+ "gap": 2.171731894901793
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 70.00552481453781,
+ -1.0071746818260863
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 48,
+ "versionNonce": 163359099,
+ "isDeleted": false,
+ "id": "tV8skfel8ww2IgWRNSntj",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 622.6667327880859,
+ "y": 610.3333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 105.3333740234375,
+ "height": 3.666656494140625,
+ "seed": 1040768149,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "yCRds2HRNFQhi2l_NRv1E",
+ "focus": 1.968489954492859,
+ "gap": 15.583236694335938
+ },
+ "endBinding": {
+ "elementId": "oxCwJMeoYhRvkKNPtKeha",
+ "focus": 1.5212851912013483,
+ "gap": 14.196061134338379
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -105.3333740234375,
+ 3.666656494140625
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 138,
+ "versionNonce": 2094596021,
+ "isDeleted": false,
+ "id": "lbEH3IbUKE-BUvPaOCKOp",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 705.7037133110892,
+ "y": 358.277838812934,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 13.33331298828125,
+ "height": 11.666671752929688,
+ "seed": 638517691,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 133,
+ "versionNonce": 419414555,
+ "isDeleted": false,
+ "id": "dTPwE9k9B6K3ksCQBb5OL",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 535.0371958414713,
+ "y": 506.51877678765186,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 176,
+ "height": 20,
+ "seed": 121765525,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::functions",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::functions"
+ },
+ {
+ "type": "rectangle",
+ "version": 456,
+ "versionNonce": 1301726907,
+ "isDeleted": false,
+ "id": "2J2sR-bPrGrF9OxiUqIF0",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 868.2591145833333,
+ "y": 158.1759851243761,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 1128772501,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "hFcIrFVFFLvSiAWOYE-xZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 284,
+ "versionNonce": 154931515,
+ "isDeleted": false,
+ "id": "ZZLxhvBfAsVbp2PY6VOfR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 851.2592061360676,
+ "y": 129.7593591478136,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 153.00003051757812,
+ "seed": 1437253909,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "hFcIrFVFFLvSiAWOYE-xZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 356,
+ "versionNonce": 1161098229,
+ "isDeleted": false,
+ "id": "FdRdG15cLuW_kygoS9kFB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 862.5927598741318,
+ "y": 332.1297662523058,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 159,
+ "height": 20,
+ "seed": 1076709051,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::globals",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::globals"
+ },
+ {
+ "type": "rectangle",
+ "version": 458,
+ "versionNonce": 196882907,
+ "isDeleted": false,
+ "id": "ev_sIxuEomRo18wQcVOAi",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 863.5926411946614,
+ "y": 195.926084306505,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 1597294293,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "hFcIrFVFFLvSiAWOYE-xZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 469,
+ "versionNonce": 1119661397,
+ "isDeleted": false,
+ "id": "2AbM31Y4eYzNJdn6ccO7X",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 870.2593892415364,
+ "y": 231.25939729478625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 1887403259,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "6EZFlJGbMoYN4RDYkSEYP",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 193,
+ "versionNonce": 499530421,
+ "isDeleted": false,
+ "id": "2jRIgxhs5VlnfeDeDJXss",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 787.7037285698783,
+ "y": 359.277838812934,
+ "strokeColor": "#000000",
+ "backgroundColor": "#7950f2",
+ "width": 16,
+ "height": 19.000091552734375,
+ "seed": 1552112411,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [
+ {
+ "id": "C_HvFqwDiW4wGe01QNKFg",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 445,
+ "versionNonce": 1861688341,
+ "isDeleted": false,
+ "id": "hFcIrFVFFLvSiAWOYE-xZ",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 797.8519422743055,
+ "y": 365.2778930664062,
+ "strokeColor": "#000000",
+ "backgroundColor": "#7950f2",
+ "width": 60.463513970850386,
+ "height": 155.0348750393585,
+ "seed": 1134283957,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "ev_sIxuEomRo18wQcVOAi",
+ "focus": 0.8021785743382612,
+ "gap": 5.277184949505454
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 26.18546210394959,
+ -121.94443088107656
+ ],
+ [
+ 60.463513970850386,
+ -155.0348750393585
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 485,
+ "versionNonce": 1957174203,
+ "isDeleted": false,
+ "id": "qGE55eCk3NIsUQpSP-g6Y",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 888.4441562228732,
+ "y": 390.84254328409827,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 983648475,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 316,
+ "versionNonce": 507826549,
+ "isDeleted": false,
+ "id": "c3AswZE8rY-ZsD8gGAzgg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 871.4442477756076,
+ "y": 362.42591730753577,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 153.00003051757812,
+ "seed": 832079445,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 343,
+ "versionNonce": 1916988507,
+ "isDeleted": false,
+ "id": "6YL2S8HdLuD8PaiWGA-vU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 829.5925801595051,
+ "y": 102.42615678575305,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 156,
+ "height": 20,
+ "seed": 920221051,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::tables",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::tables"
+ },
+ {
+ "type": "rectangle",
+ "version": 542,
+ "versionNonce": 2029312725,
+ "isDeleted": false,
+ "id": "50mTV_vbZA4UToji5TAhb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 882.0739339192708,
+ "y": 431.5186000400119,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 1438577589,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "OjoiFuv7ZOtNkq4SpgOL-",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 553,
+ "versionNonce": 1635428603,
+ "isDeleted": false,
+ "id": "Aa3QPT7Ps924J0klBEGMw",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 888.7406819661458,
+ "y": 466.85191302829315,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 547556891,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 424,
+ "versionNonce": 1473368475,
+ "isDeleted": false,
+ "id": "WMOLdrP9c0TFV1JLcmfzK",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 233.66656494140625,
+ "y": 236.33336639404277,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 17.3333740234375,
+ "height": 13.000015258789062,
+ "seed": 1272865237,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 442,
+ "versionNonce": 606202261,
+ "isDeleted": false,
+ "id": "XVo2iBeciuaFiIrP3DUw5",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 235.66656494140625,
+ "y": 252.66669464111305,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 17.3333740234375,
+ "height": 13.000015258789062,
+ "seed": 823202299,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "6EZFlJGbMoYN4RDYkSEYP",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 427,
+ "versionNonce": 377153083,
+ "isDeleted": false,
+ "id": "InatpictpQQa0Op1qByFJ",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 235.66656494140625,
+ "y": 268.33336639404274,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 17.3333740234375,
+ "height": 13.000015258789062,
+ "seed": 682826293,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "6EZFlJGbMoYN4RDYkSEYP",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 609,
+ "versionNonce": 1207751547,
+ "isDeleted": false,
+ "id": "6EZFlJGbMoYN4RDYkSEYP",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 257.1755919962603,
+ "y": 432.4837343704476,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 350.4818452518821,
+ "height": 113.7944575139108,
+ "seed": 1046151995,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "bCPa9rRVzubIpa31jwl73",
+ "focus": 0.6467798007705062,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -33.87912050646,
+ 40.47938005012526
+ ],
+ [
+ 316.60272474542205,
+ 113.7944575139108
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 380,
+ "versionNonce": 1636332981,
+ "isDeleted": false,
+ "id": "qUXi_zQbiA8lmV5c_r8ta",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 875.0742831759982,
+ "y": 534.6482721964519,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 172,
+ "height": 20,
+ "seed": 2104268027,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::memories",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::memories"
+ },
+ {
+ "type": "rectangle",
+ "version": 511,
+ "versionNonce": 833268763,
+ "isDeleted": false,
+ "id": "rfTE9QxqtEjzOzoCNZT01",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 900.9256795247394,
+ "y": 593.3610492282444,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 1292864565,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "4NjPz6Olqru3m83OxGXGX",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 342,
+ "versionNonce": 347731733,
+ "isDeleted": false,
+ "id": "RzznX4k1tfSt8AyuJuF2D",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 883.9257710774738,
+ "y": 564.9444232516819,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 153.00003051757812,
+ "seed": 1990606235,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "4NjPz6Olqru3m83OxGXGX",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 566,
+ "versionNonce": 626290875,
+ "isDeleted": false,
+ "id": "GEQFwoUvMYOSit62JGwLM",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 894.5554572211371,
+ "y": 634.037105984158,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 1545223573,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 578,
+ "versionNonce": 1559514229,
+ "isDeleted": false,
+ "id": "IvFYTMyYUBhJe6Ob5YAGg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 901.2222052680121,
+ "y": 669.3704189724392,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70.00006103515625,
+ "height": 25.66668701171874,
+ "seed": 937546299,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 43,
+ "versionNonce": 1419551067,
+ "isDeleted": false,
+ "id": "ZMwf8VnKqa7gp45PnuQWi",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 780.3335876464843,
+ "y": 45.92599826388881,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 286.66666666666686,
+ "height": 707.0370313856337,
+ "seed": 876902971,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "YidAloK-3ikBBzvuu-S22",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 138,
+ "versionNonce": 1241314773,
+ "isDeleted": false,
+ "id": "2NQmRBF_NE2Myp3-jqLfT",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 418.1839375016565,
+ "y": 222.9630296495223,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 351.7376685654755,
+ "height": 202.59258694118918,
+ "seed": 1011740277,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "TOmX9MwwNOgbfjNJ8V8j7",
+ "focus": 0.48971428325717553,
+ "gap": 11.018498738606851
+ },
+ "endBinding": {
+ "elementId": "7MNv-pmgV4-8yJ5lIFY1U",
+ "focus": 1.3268339026620566,
+ "gap": 13.16658528645857
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 82.8903795827618,
+ -202.59258694118918
+ ],
+ [
+ 351.7376685654755,
+ -175.99734962527606
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 58,
+ "versionNonce": 416660987,
+ "isDeleted": false,
+ "id": "OjoiFuv7ZOtNkq4SpgOL-",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 796.6298048231338,
+ "y": 366.6667785644529,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 82.96305338541652,
+ "height": 65.92593722873261,
+ "seed": 275987509,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "50mTV_vbZA4UToji5TAhb",
+ "focus": -0.4434608130384178,
+ "gap": 2.481075710720461
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 82.96305338541652,
+ 65.92593722873261
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 131,
+ "versionNonce": 1458139957,
+ "isDeleted": false,
+ "id": "4NjPz6Olqru3m83OxGXGX",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 796.6298726399739,
+ "y": 372.96306355794246,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.51854112413207,
+ "height": 227.77777777777777,
+ "seed": 1888354747,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "rfTE9QxqtEjzOzoCNZT01",
+ "focus": -0.6184957089704255,
+ "gap": 5.7772657606334406
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 46.66673448350696,
+ 191.48159450954864
+ ],
+ [
+ 98.51854112413207,
+ 227.77777777777777
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 105,
+ "versionNonce": 2097301147,
+ "isDeleted": false,
+ "id": "euj5CRuv6EoS2abVhp14P",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 792.9261237250435,
+ "y": 375.55566745334175,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 140,
+ "height": 233.33346896701386,
+ "seed": 856817851,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887723,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "qpSAJ6K0S6TvU6i2Uflep",
+ "focus": 1.8857122566967692,
+ "gap": 14.01957438916057
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -30.37034776475707,
+ 147.77781168619794
+ ],
+ [
+ -140,
+ 233.33346896701386
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 404,
+ "versionNonce": 2049173,
+ "isDeleted": false,
+ "id": "0836mka_gP8EntAw7Pvzh",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 285.4076097276477,
+ "y": 424.0742221408418,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 198,
+ "height": 19,
+ "seed": 1302236763,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887724,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMFunction **functions;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunction **functions;"
+ },
+ {
+ "type": "rectangle",
+ "version": 385,
+ "versionNonce": 131382075,
+ "isDeleted": false,
+ "id": "Fv3xwjCOvQ9-pJ5ui2sV2",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 239.7409837510852,
+ "y": 409.4075961642793,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 216,
+ "height": 42.6666259765625,
+ "seed": 1276926165,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887724,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 350,
+ "versionNonce": 424929781,
+ "isDeleted": false,
+ "id": "IibWA_jM89ndxmrceQLmE",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 254.4077317979602,
+ "y": 420.07428317599806,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 15.33331298828125,
+ "height": 22.66668701171875,
+ "seed": 1427245819,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887724,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 133,
+ "versionNonce": 1169136603,
+ "isDeleted": false,
+ "id": "OdDm5a5O_NIoZbF3u0c0H",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 442.5558098687066,
+ "y": 370.37052747938344,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 138.34606629993374,
+ "height": 88.15863628949046,
+ "seed": 967352763,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679555887724,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "FPUGB-iP7ep91gfoTuV2d",
+ "focus": 0.6557614629211577,
+ "gap": 3.7962053087022696
+ },
+ "endBinding": {
+ "elementId": "blxQLl_yf7DMD76qHC5rc",
+ "focus": -0.24942508137542688,
+ "gap": 9.870619032117872
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 61.48149278428815,
+ -72.22222222222217
+ ],
+ [
+ 138.34606629993374,
+ -88.15863628949046
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 35,
+ "versionNonce": 1670177621,
+ "isDeleted": false,
+ "id": "armvxVMuT0bX77T30wPV4",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -39.66648017035561,
+ "y": 230.37051052517361,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 165,
+ "height": 20,
+ "seed": 587722005,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887724,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "export_global_count",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "export_global_count"
+ },
+ {
+ "type": "rectangle",
+ "version": 502,
+ "versionNonce": 312830075,
+ "isDeleted": false,
+ "id": "nUlAmf5jmsJoZ2lStTbBw",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -52.18503146701369,
+ "y": 226.01867336697043,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174.66668701171875,
+ "height": 25.37032402886292,
+ "seed": 1476753525,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679555887724,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Mznw_08SMS746JVePQe3h",
+ "type": "text",
+ "x": -55.747947692871094,
+ "y": 396.450114440918,
+ "width": 174,
+ "height": 20,
+ "angle": 0,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "roundness": null,
+ "seed": 1392475036,
+ "version": 62,
+ "versionNonce": 452856732,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1679558398355,
+ "link": null,
+ "locked": false,
+ "text": "export_memory_count",
+ "fontSize": 16,
+ "fontFamily": 1,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "baseline": 14,
+ "containerId": null,
+ "originalText": "export_memory_count"
+ },
+ {
+ "id": "wyGG1OIhy3X499IvtJM3Z",
+ "type": "rectangle",
+ "x": -58.081260681152344,
+ "y": 394.9499618530274,
+ "width": 182.33331298828125,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "roundness": null,
+ "seed": 611257380,
+ "version": 32,
+ "versionNonce": 1973769116,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1679558406221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Gk4JYjHayAFkRDbQWId6b",
+ "type": "text",
+ "x": -42.081260681152344,
+ "y": 463.28327484130864,
+ "width": 162,
+ "height": 20,
+ "angle": 0,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "roundness": null,
+ "seed": 804003748,
+ "version": 47,
+ "versionNonce": 591391772,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1679558418472,
+ "link": null,
+ "locked": false,
+ "text": "export_table_count",
+ "fontSize": 16,
+ "fontFamily": 1,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "baseline": 14,
+ "containerId": null,
+ "originalText": "export_table_count"
+ },
+ {
+ "id": "Xb-aggFXlG4Dh_LtxGJ7l",
+ "type": "rectangle",
+ "x": -49.414573669433594,
+ "y": 462.28330535888676,
+ "width": 174.33331298828125,
+ "height": 24.33343505859375,
+ "angle": 0,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "roundness": null,
+ "seed": 572093348,
+ "version": 30,
+ "versionNonce": 1840351132,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1679558423043,
+ "link": null,
+ "locked": false
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.excalidraw b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.excalidraw
new file mode 100644
index 000000000..f2ade3b20
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.excalidraw
@@ -0,0 +1,2643 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
+ "elements": [
+ {
+ "type": "rectangle",
+ "version": 155,
+ "versionNonce": 1248561528,
+ "isDeleted": false,
+ "id": "fxSjNN3geJtdm-2MR7INN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 583.9999694824219,
+ "y": 276.33331298828114,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 427.66665649414057,
+ "height": 468.6667785644533,
+ "seed": 1226571556,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "zFlCnXyCuuvj85rH8yMcR",
+ "type": "arrow"
+ },
+ {
+ "id": "KiC12zdfqG7zXRbctXGmT",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679706874848,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 31,
+ "versionNonce": 726044059,
+ "isDeleted": false,
+ "id": "kKMhPpSUI7zZU0hhfGfSr",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 652,
+ "y": 310.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 91,
+ "height": 20,
+ "seed": 1323166748,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "v8qOyuaPyJmHPHCk-V90A",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679639568750,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "prev_frame",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "prev_frame"
+ },
+ {
+ "type": "text",
+ "version": 31,
+ "versionNonce": 213374372,
+ "isDeleted": false,
+ "id": "97vkuGwuf9dOgnbXL4nZW",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 652,
+ "y": 345.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 84,
+ "height": 20,
+ "seed": 123433892,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679617642914,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_inst ",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func_inst "
+ },
+ {
+ "type": "text",
+ "version": 31,
+ "versionNonce": 34601372,
+ "isDeleted": false,
+ "id": "IaZULBLAtP-VbIpB210WT",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 652,
+ "y": 380.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 13,
+ "height": 20,
+ "seed": 1157761180,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679617674900,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "ip",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "ip"
+ },
+ {
+ "type": "text",
+ "version": 37,
+ "versionNonce": 556583925,
+ "isDeleted": false,
+ "id": "H6AElOIjCOfKVDEzsEb8_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 648.3333435058594,
+ "y": 415.16668701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 160,
+ "height": 20,
+ "seed": 175464228,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638914768,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "opnd_stack_bottom",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "opnd_stack_bottom"
+ },
+ {
+ "type": "text",
+ "version": 31,
+ "versionNonce": 2114117339,
+ "isDeleted": false,
+ "id": "InrDJwTwyP1E7lpeGu0Tb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 652,
+ "y": 450.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 275,
+ "height": 20,
+ "seed": 158242076,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638694120,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "opnd_sp (point to opnd stack top)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "opnd_sp (point to opnd stack top)"
+ },
+ {
+ "type": "text",
+ "version": 31,
+ "versionNonce": 1005029461,
+ "isDeleted": false,
+ "id": "04QcPfm0Sc1zQpYDxmPVl",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 652,
+ "y": 485.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 163,
+ "height": 20,
+ "seed": 2051398308,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679638792159,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "label_stack_bottom",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "label_stack_bottom"
+ },
+ {
+ "type": "text",
+ "version": 31,
+ "versionNonce": 1565468827,
+ "isDeleted": false,
+ "id": "GD4urgWTuYKcn7FcwA5uj",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 652,
+ "y": 520.5,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 280,
+ "height": 20,
+ "seed": 429232540,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "AhNgHym2Ox-2Je47FlwkG",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638982669,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "label_sp (point to label stack top)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "label_sp (point to label stack top)"
+ },
+ {
+ "type": "text",
+ "version": 123,
+ "versionNonce": 458495496,
+ "isDeleted": false,
+ "id": "9TW8AADnHJOkmP9yPw86T",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 626,
+ "y": 586.1666564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 125,
+ "height": 20,
+ "seed": 561702436,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706667761,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func arguments:",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func arguments:"
+ },
+ {
+ "type": "text",
+ "version": 373,
+ "versionNonce": 180653176,
+ "isDeleted": false,
+ "id": "ZDnffzv8Hf65ecpMemz82",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 700.6666870117188,
+ "y": 669.1667785644531,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 131,
+ "height": 20,
+ "seed": 1157792164,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543900,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "<operand stack>",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "<operand stack>"
+ },
+ {
+ "type": "rectangle",
+ "version": 108,
+ "versionNonce": 628186232,
+ "isDeleted": false,
+ "id": "10UtZNhGhQIza4PqPLKs5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 622.6665954589844,
+ "y": 299.9999694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 378.3334655761719,
+ "height": 33.66670227050781,
+ "seed": 1281579428,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706899765,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 108,
+ "versionNonce": 1807107317,
+ "isDeleted": false,
+ "id": "lxiJENi5HY8EPwIeH7LA0",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 621.9999389648438,
+ "y": 343.3332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 377.6668090820312,
+ "height": 28.33332824707031,
+ "seed": 523845788,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679639010923,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 104,
+ "versionNonce": 114288661,
+ "isDeleted": false,
+ "id": "iBGNXVvcsdhIuK4rSyr24",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 621.333251953125,
+ "y": 377.9999694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 380.3333129882813,
+ "height": 24.666656494140625,
+ "seed": 1117299228,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679639014926,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 141,
+ "versionNonce": 1756531061,
+ "isDeleted": false,
+ "id": "hwgrctAuxGaA-SGuwFgEd",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 623.6665649414062,
+ "y": 413.66664123535156,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 190.33331298828125,
+ "height": 25.333358764648438,
+ "seed": 1885325596,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "2yVfQUtaAnW5BuEtoXRcA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638734395,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 135,
+ "versionNonce": 138906299,
+ "isDeleted": false,
+ "id": "V6DAmN9L5JPz2B1MGfa9C",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 624.6665954589844,
+ "y": 445.9999694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 377.6666564941406,
+ "height": 28.00003051757812,
+ "seed": 1058988452,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638756269,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 171,
+ "versionNonce": 755362101,
+ "isDeleted": false,
+ "id": "0m59R0bqJv_x7GbZ6hfyg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 624.6665954589844,
+ "y": 485.33331298828125,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 197.33340454101562,
+ "height": 23.33328247070314,
+ "seed": 1040920092,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638908118,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 191,
+ "versionNonce": 944635675,
+ "isDeleted": false,
+ "id": "Itqs7rL1-S3eIrmvfrr6i",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 625.333251953125,
+ "y": 516.3333129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 349.66674804687506,
+ "height": 34.66665649414062,
+ "seed": 498379804,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679639029205,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 169,
+ "versionNonce": 1525847816,
+ "isDeleted": false,
+ "id": "Yx4QpHhmHHvf267ot4QcW",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 623.333251953125,
+ "y": 582.6666259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 352.3333740234375,
+ "height": 31.666748046875,
+ "seed": 612410396,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543900,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 195,
+ "versionNonce": 335028795,
+ "isDeleted": false,
+ "id": "sWiDv3IP9Y4zn-pQPKT59",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 585.6668090820312,
+ "y": 203.99998474121094,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 424.3334045410156,
+ "height": 70.66668701171874,
+ "seed": 813710748,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "v8qOyuaPyJmHPHCk-V90A",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679639568750,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 255,
+ "versionNonce": 1953250680,
+ "isDeleted": false,
+ "id": "gS_VbgMS5NUoHmfxH0eEO",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 752.0001525878906,
+ "y": 624.3333129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 30.6666259765625,
+ "height": 19.000091552734375,
+ "seed": 2044515484,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543900,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 171,
+ "versionNonce": 227339384,
+ "isDeleted": false,
+ "id": "m89OexiP1cw5cN304gmQ-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 771.3336334228516,
+ "y": 587.8333282470703,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 37.999969482421875,
+ "height": 19.666748046875,
+ "seed": 2074557348,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706664521,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 174,
+ "versionNonce": 1205391112,
+ "isDeleted": false,
+ "id": "aAWksorEQDseQSDntTUKe",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 824.6669464111328,
+ "y": 589.1665802001953,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 35.999969482421875,
+ "height": 15.666778564453123,
+ "seed": 1851711260,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706659367,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 213,
+ "versionNonce": 1798283016,
+ "isDeleted": false,
+ "id": "IH4D4tHy91CnkLlP3kKJT",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 878.6669464111328,
+ "y": 588.8333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 35.999969482421875,
+ "height": 16.333435058593754,
+ "seed": 1835107492,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706677882,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 28,
+ "versionNonce": 1189712156,
+ "isDeleted": false,
+ "id": "OGXe0pARYj6FFaTw_LGLs",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 916.6667785644531,
+ "y": 348.3333435058594,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 13.33331298828125,
+ "height": 15.66668701171875,
+ "seed": 703955236,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "zFlCnXyCuuvj85rH8yMcR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679617654572,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 90,
+ "versionNonce": 1752012152,
+ "isDeleted": false,
+ "id": "zFlCnXyCuuvj85rH8yMcR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 930.9664201728779,
+ "y": 355.9093759200581,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 97.70041942673151,
+ "height": 3.156306335738577,
+ "seed": 1652552228,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706533823,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "OGXe0pARYj6FFaTw_LGLs",
+ "gap": 1,
+ "focus": -0.05520408889747474
+ },
+ "endBinding": {
+ "elementId": "fxSjNN3geJtdm-2MR7INN",
+ "gap": 17.000213623046875,
+ "focus": 0.6588609578759657
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 97.70041942673151,
+ 3.156306335738577
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 39,
+ "versionNonce": 2081828900,
+ "isDeleted": false,
+ "id": "cN9omEMJtZq2pKK3nPqeK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1033.3334655761719,
+ "y": 339.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 218,
+ "height": 37,
+ "seed": 1716587932,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "w-Fx4nTROv9qvnPqLigxc"
+ }
+ ],
+ "updated": 1679617661526,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 4,
+ "versionNonce": 727129976,
+ "isDeleted": false,
+ "id": "w-Fx4nTROv9qvnPqLigxc",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1051.3334655761719,
+ "y": 347.5000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 182,
+ "height": 20,
+ "seed": 1245620124,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706461629,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(current func instance)",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "cN9omEMJtZq2pKK3nPqeK",
+ "originalText": "(current func instance)"
+ },
+ {
+ "type": "diamond",
+ "version": 19,
+ "versionNonce": 1517445412,
+ "isDeleted": false,
+ "id": "YAWb1D32tq9r2NA9BjPC0",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 917.3334655761719,
+ "y": 381.3333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 12.6666259765625,
+ "height": 17.666656494140625,
+ "seed": 831940124,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679617681098,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 103,
+ "versionNonce": 437077525,
+ "isDeleted": false,
+ "id": "EUw5VCdUqXWdPh2cmFgTu",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1048.0000915527344,
+ "y": 390.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 224,
+ "height": 52,
+ "seed": 122854564,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "sQUYAdB_aJemE8MbtfUXU"
+ },
+ {
+ "id": "7cT6qctQMJuzVHVpt9gAe",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679643416466,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 89,
+ "versionNonce": 818328584,
+ "isDeleted": false,
+ "id": "sQUYAdB_aJemE8MbtfUXU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1066.0000915527344,
+ "y": 395.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 188,
+ "height": 40,
+ "seed": 1881253020,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706461630,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": " (next bytecode in code\nfor return)",
+ "baseline": 34,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "EUw5VCdUqXWdPh2cmFgTu",
+ "originalText": " (next bytecode in code\nfor return)"
+ },
+ {
+ "type": "arrow",
+ "version": 86,
+ "versionNonce": 44769845,
+ "isDeleted": false,
+ "id": "7cT6qctQMJuzVHVpt9gAe",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 928.0000915527344,
+ "y": 389.66668701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 118.6890752940651,
+ "height": 18.605575795885613,
+ "seed": 2073584156,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643418552,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "EUw5VCdUqXWdPh2cmFgTu",
+ "gap": 1.3109247059348494,
+ "focus": -0.23038166167021662
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 118.6890752940651,
+ 18.605575795885613
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 2,
+ "versionNonce": 504035291,
+ "isDeleted": false,
+ "id": "6fkbi-hv-WF274Ggup6O2",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1200.0001525878906,
+ "y": 619.8332824707031,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 0.333251953125,
+ "height": 0.333343505859375,
+ "seed": 1881722357,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [],
+ "updated": 1679638527376,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 237,
+ "versionNonce": 103104376,
+ "isDeleted": false,
+ "id": "TBY_IOcQ1nL2SbnoH6sFO",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 627.0001373291016,
+ "y": 660.5000610351562,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 357.33331298828125,
+ "height": 30.33352661132812,
+ "seed": 1619080725,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "type": "arrow"
+ },
+ {
+ "id": "2yVfQUtaAnW5BuEtoXRcA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679706543900,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 304,
+ "versionNonce": 1231721480,
+ "isDeleted": false,
+ "id": "2yVfQUtaAnW5BuEtoXRcA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1001.4951265607561,
+ "y": 435.4648501924554,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 69.86595546390652,
+ "height": 230.92727975758817,
+ "seed": 554350997,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "Q10gr2u0Ozc3e0iafNjrU",
+ "focus": -0.9749635321679403,
+ "gap": 1
+ },
+ "endBinding": {
+ "elementId": "TBY_IOcQ1nL2SbnoH6sFO",
+ "gap": 11.467449077109102,
+ "focus": 0.9687666106437038
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 64.17172829764229,
+ 132.70180630168522
+ ],
+ [
+ -5.694227166264227,
+ 230.92727975758817
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 579,
+ "versionNonce": 1040896776,
+ "isDeleted": false,
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 637.088614263612,
+ "y": 428.66374830753944,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 87.42185095794798,
+ "height": 243.67105886528202,
+ "seed": 1778263445,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "H6AElOIjCOfKVDEzsEb8_",
+ "focus": 1.022917371543073,
+ "gap": 11.244729242247331
+ },
+ "endBinding": {
+ "elementId": "zmGNXD3FjbK3cLzJQcTS7",
+ "focus": -0.9191849396644245,
+ "gap": 1.3880431063754486
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -87.42185095794798,
+ 127.50287766902306
+ ],
+ [
+ -10.80983302916718,
+ 243.67105886528202
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 146,
+ "versionNonce": 1195282552,
+ "isDeleted": false,
+ "id": "zmGNXD3FjbK3cLzJQcTS7",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 627.6668243408203,
+ "y": 662.8332824707031,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 207.333251953125,
+ "height": 25.333343505859375,
+ "seed": 2075064181,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "bzZuzwhAslOM0VOMpIFi4",
+ "type": "arrow"
+ },
+ {
+ "id": "PtPViQVeIOLGj_fGdcXae",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 252,
+ "versionNonce": 1380659720,
+ "isDeleted": false,
+ "id": "fdKDasbQmnSQhVWnuc6o0",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 892.2284992953181,
+ "y": 676.9139215503409,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 46.77163803378346,
+ "height": 0.7472955737783877,
+ "seed": 2138378229,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "triangle",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 46.77163803378346,
+ -0.7472955737783877
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 63,
+ "versionNonce": 2032367925,
+ "isDeleted": false,
+ "id": "ZwrESUGUwekFgJ8cot-D1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 821.6667327880859,
+ "y": 414.6666259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174,
+ "height": 20,
+ "seed": 795089589,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "2yVfQUtaAnW5BuEtoXRcA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679638757542,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "opnd_stack_boundary",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "opnd_stack_boundary"
+ },
+ {
+ "type": "rectangle",
+ "version": 32,
+ "versionNonce": 132303029,
+ "isDeleted": false,
+ "id": "VOinNwnsGZVJt9RUbM5gI",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 821.3334197998047,
+ "y": 409.8332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 184.3333740234375,
+ "height": 30.333328247070312,
+ "seed": 1069875285,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679638823023,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 255,
+ "versionNonce": 453362040,
+ "isDeleted": false,
+ "id": "PtPViQVeIOLGj_fGdcXae",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 979.6667327880859,
+ "y": 460.4999694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 140.89037965104183,
+ "height": 211.49970410546382,
+ "seed": 472939093,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "zmGNXD3FjbK3cLzJQcTS7",
+ "focus": 0.7843520090394333,
+ "gap": 6.109589831379935
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 2.33331298828125,
+ 145
+ ],
+ [
+ -138.55706666276058,
+ 211.49970410546382
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 19,
+ "versionNonce": 987485307,
+ "isDeleted": false,
+ "id": "u7bglMSX07f5CN_SyFAmd",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 967.0000457763672,
+ "y": 452.1666259765625,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 15,
+ "height": 15,
+ "seed": 764957403,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679638777911,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 43,
+ "versionNonce": 115610933,
+ "isDeleted": false,
+ "id": "shh1k5OswcF57jhAKAI6G",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 830.0000457763672,
+ "y": 486.8332824707031,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 176,
+ "height": 20,
+ "seed": 1994374395,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679638809874,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "label_stack_boundary",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "label_stack_boundary"
+ },
+ {
+ "type": "rectangle",
+ "version": 33,
+ "versionNonce": 1511042715,
+ "isDeleted": false,
+ "id": "H4lcjS3aIarViIGAHsLBU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 827.6667327880859,
+ "y": 480.83331298828125,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 181,
+ "height": 29.666656494140625,
+ "seed": 1492829339,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679638816247,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 372,
+ "versionNonce": 1764776968,
+ "isDeleted": false,
+ "id": "B1eH_aNspf4OoiXnvWu1V",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 630.0000915527344,
+ "y": 705.1667175292969,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 356.66662597656256,
+ "height": 31.333404541015625,
+ "seed": 710054491,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "X76to9wjER3VzqXb7tCwb",
+ "type": "arrow"
+ },
+ {
+ "id": "1Urs2i0MGQSQ9XbOVdbCH",
+ "type": "arrow"
+ },
+ {
+ "id": "KiC12zdfqG7zXRbctXGmT",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679706706153,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 332,
+ "versionNonce": 1981566984,
+ "isDeleted": false,
+ "id": "Tu7mkiWTjNwFrOsUa35N1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 633.3333740234375,
+ "y": 704.8334045410156,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 250.33328247070318,
+ "height": 26.66656494140625,
+ "seed": 1201312981,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "AhNgHym2Ox-2Je47FlwkG",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 250,
+ "versionNonce": 1696927496,
+ "isDeleted": false,
+ "id": "xQf_fS4j5XD1gPYVmnyQi",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 687,
+ "y": 709.8335876464844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 108,
+ "height": 20,
+ "seed": 1671092892,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "<lable stack>",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "<lable stack>"
+ },
+ {
+ "type": "diamond",
+ "version": 19,
+ "versionNonce": 167262267,
+ "isDeleted": false,
+ "id": "T43dNIeAePPWy65vsVjRw",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 629.0000457763672,
+ "y": 420.8332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 13.66668701171875,
+ "height": 9,
+ "seed": 1938681499,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679638923749,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 26,
+ "versionNonce": 1796989173,
+ "isDeleted": false,
+ "id": "Q10gr2u0Ozc3e0iafNjrU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 988.5000762939453,
+ "y": 431.9999542236328,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 13.66668701171875,
+ "height": 9,
+ "seed": 1339643477,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "2yVfQUtaAnW5BuEtoXRcA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679639079224,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 160,
+ "versionNonce": 1562882312,
+ "isDeleted": false,
+ "id": "X76to9wjER3VzqXb7tCwb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 633.6667327880859,
+ "y": 498.1665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 95,
+ "height": 226.4773119076067,
+ "seed": 332801877,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "B1eH_aNspf4OoiXnvWu1V",
+ "gap": 3.7751266782821933,
+ "focus": -0.9692106196282059
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -95,
+ 119
+ ],
+ [
+ -7.441767913633839,
+ 226.4773119076067
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 202,
+ "versionNonce": 791528312,
+ "isDeleted": false,
+ "id": "1Urs2i0MGQSQ9XbOVdbCH",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 993.6667327880859,
+ "y": 500.833251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 55.58884147480535,
+ "height": 215.3311147859538,
+ "seed": 385950459,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "_1a_M2hRRjsccFJTYD-i0",
+ "focus": -0.27052637703325505,
+ "gap": 2.7105616084241397
+ },
+ "endBinding": {
+ "elementId": "B1eH_aNspf4OoiXnvWu1V",
+ "focus": 0.9207393546998478,
+ "gap": 3.0779218308585996
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 51.666748046875,
+ 153.66668701171875
+ ],
+ [
+ -3.922093427930349,
+ 215.3311147859538
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 252,
+ "versionNonce": 1150719096,
+ "isDeleted": false,
+ "id": "AhNgHym2Ox-2Je47FlwkG",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 941.0000457763672,
+ "y": 533.833251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 73.73891815660659,
+ "height": 177.63880524698254,
+ "seed": 17032283,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "GD4urgWTuYKcn7FcwA5uj",
+ "focus": -1.0502037458670375,
+ "gap": 9.000045776367188
+ },
+ "endBinding": {
+ "elementId": "Tu7mkiWTjNwFrOsUa35N1",
+ "focus": 0.7914007600477917,
+ "gap": 2.5944100904637253
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 18.99993896484375,
+ 133.33340454101562
+ ],
+ [
+ -54.73897919176284,
+ 177.63880524698254
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 19,
+ "versionNonce": 987485307,
+ "isDeleted": false,
+ "id": "C2JNNEQlhQ4cFy2h16E4l",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 630.5000457763672,
+ "y": 491.333251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 15,
+ "height": 15,
+ "seed": 2047712475,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679638991963,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 19,
+ "versionNonce": 987485307,
+ "isDeleted": false,
+ "id": "xsWhegnNTDUvjVk1Hl20d",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 931.5000457763672,
+ "y": 523.333251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 15,
+ "height": 15,
+ "seed": 751530581,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679638994246,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 20,
+ "versionNonce": 2123101557,
+ "isDeleted": false,
+ "id": "_1a_M2hRRjsccFJTYD-i0",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 987.5000457763672,
+ "y": 503.333251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 15,
+ "height": 15,
+ "seed": 1838893435,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [
+ {
+ "id": "1Urs2i0MGQSQ9XbOVdbCH",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679639046142,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 122,
+ "versionNonce": 918373752,
+ "isDeleted": false,
+ "id": "_FzrYgawOp32aihqUkx8N",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 937.3333587646484,
+ "y": 722.4999084472656,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 31,
+ "height": 0.333343505859375,
+ "seed": 125027067,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "triangle",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 31,
+ 0.333343505859375
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 58,
+ "versionNonce": 1791510299,
+ "isDeleted": false,
+ "id": "v8qOyuaPyJmHPHCk-V90A",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 640.33349609375,
+ "y": 318.1665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 112.66668701171875,
+ "height": 114.41643468378521,
+ "seed": 1521072891,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679639586455,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "kKMhPpSUI7zZU0hhfGfSr",
+ "focus": -0.8312315870337287,
+ "gap": 11.66650390625
+ },
+ "endBinding": {
+ "elementId": "sWiDv3IP9Y4zn-pQPKT59",
+ "focus": 1.0049483520293248,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -112.66668701171875,
+ -61.99995422363281
+ ],
+ [
+ -55.63497828298284,
+ -114.41643468378521
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 23,
+ "versionNonce": 1760592469,
+ "isDeleted": false,
+ "id": "rizowRaNCY3sscSKdUoZ_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 637.6668090820312,
+ "y": 307.49993896484375,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 11.66668701171875,
+ "height": 17,
+ "seed": 599455541,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679639578366,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 241,
+ "versionNonce": 1517501429,
+ "isDeleted": false,
+ "id": "Mv8lernCpH2jNrVrNfqm5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 585.8334503173828,
+ "y": 130.833251953125,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 424.3334045410156,
+ "height": 70.66668701171874,
+ "seed": 1040624571,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "cl6Duxg7hC4_1chb5YNau",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679639602774,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 41,
+ "versionNonce": 926996117,
+ "isDeleted": false,
+ "id": "eQrRfUHvRypTcFfQ80nK5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 647.0000610351562,
+ "y": 219.33328247070312,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 91,
+ "height": 20,
+ "seed": 1884598901,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "cl6Duxg7hC4_1chb5YNau",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679639602774,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "prev_frame",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "prev_frame"
+ },
+ {
+ "type": "diamond",
+ "version": 32,
+ "versionNonce": 784602165,
+ "isDeleted": false,
+ "id": "w_RQs6dyVbTAM3iaX46G2",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 632.6668701171875,
+ "y": 216.33322143554688,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 11.66668701171875,
+ "height": 17,
+ "seed": 1918737243,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679639598842,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 135,
+ "versionNonce": 1953671957,
+ "isDeleted": false,
+ "id": "cl6Duxg7hC4_1chb5YNau",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 639.0001525878906,
+ "y": 224.16659545898438,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 80.33334350585938,
+ "height": 95,
+ "seed": 509490587,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679639608498,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "eQrRfUHvRypTcFfQ80nK5",
+ "focus": -0.7568501325114791,
+ "gap": 7.999908447265625
+ },
+ "endBinding": {
+ "elementId": "Mv8lernCpH2jNrVrNfqm5",
+ "focus": 1.0067042515978792,
+ "gap": 1.666656494140625
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -80.33334350585938,
+ -53.66668701171875
+ ],
+ [
+ -53.66668701171875,
+ -95
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 196,
+ "versionNonce": 1763609493,
+ "isDeleted": false,
+ "id": "7pum3cjupgQ0Fz7eY_3xD",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1026.33349609375,
+ "y": 123.83326721191406,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 109,
+ "height": 20,
+ "seed": 1300737371,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679640276534,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "Stack bottom",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "Stack bottom"
+ },
+ {
+ "type": "text",
+ "version": 310,
+ "versionNonce": 1972102043,
+ "isDeleted": false,
+ "id": "Su_2hWwLvhW5W8cNMx6hT",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1030.666748046875,
+ "y": 266.8333206176758,
+ "strokeColor": "#000000",
+ "backgroundColor": "#12b886",
+ "width": 110,
+ "height": 20,
+ "seed": 2131950293,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679640279741,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "current frame",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "current frame"
+ },
+ {
+ "type": "rectangle",
+ "version": 181,
+ "versionNonce": 1099516792,
+ "isDeleted": false,
+ "id": "jCBotdnPaPF-NkuwgrLyd",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 582.3333129882812,
+ "y": 744.8332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 429.666748046875,
+ "height": 48.333343505859396,
+ "seed": 1136750491,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706699607,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 167,
+ "versionNonce": 647398264,
+ "isDeleted": false,
+ "id": "BRMXHqjjvaWADtilYg0NV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 784.3333740234375,
+ "y": 775.8333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 57,
+ "height": 20,
+ "seed": 415943189,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "KiC12zdfqG7zXRbctXGmT",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679706708714,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "Unused",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "Unused"
+ },
+ {
+ "type": "text",
+ "version": 179,
+ "versionNonce": 1210985736,
+ "isDeleted": false,
+ "id": "6YoFb1tMeQkuEDMy5H4FV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1018.6668090820312,
+ "y": 778.8333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 122,
+ "height": 20,
+ "seed": 1257872437,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706711595,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "stack boundary",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "stack boundary"
+ },
+ {
+ "type": "text",
+ "version": 174,
+ "versionNonce": 314437128,
+ "isDeleted": false,
+ "id": "_e0Yy4p4UD9MNJUym2U_N",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1025.6666259765625,
+ "y": 732.8335113525391,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 80,
+ "height": 20,
+ "seed": 521361589,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "stack top",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "stack top"
+ },
+ {
+ "type": "rectangle",
+ "version": 126,
+ "versionNonce": 1927665272,
+ "isDeleted": false,
+ "id": "ATaMGJS9emfaD_vgxw4Wi",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 625.5619915078412,
+ "y": 621.4944998254441,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 358.66670227050787,
+ "height": 25.999969482421875,
+ "seed": 1247140509,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 268,
+ "versionNonce": 1190911752,
+ "isDeleted": false,
+ "id": "qlKC-UwDGQErtLa5oG6C3",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 625.3333740234375,
+ "y": 554.1666870117188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 236,
+ "height": 20,
+ "seed": 1957232156,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706639231,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "Wasm LOCALs (local.set/get):",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "Wasm LOCALs (local.set/get):"
+ },
+ {
+ "type": "rectangle",
+ "version": 264,
+ "versionNonce": 500451192,
+ "isDeleted": false,
+ "id": "CnBSoD9DNI5Himd9gJXwV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 787.8953006814252,
+ "y": 625.661102913823,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 30.6666259765625,
+ "height": 19.000091552734375,
+ "seed": 1737116886,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 259,
+ "versionNonce": 235932680,
+ "isDeleted": false,
+ "id": "z4Ye9_zQDUab5ewn2mujX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 827.5619876931439,
+ "y": 623.9944159021043,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 30.6666259765625,
+ "height": 19.000091552734375,
+ "seed": 1207868746,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 292,
+ "versionNonce": 600610936,
+ "isDeleted": false,
+ "id": "V3_r6rtZsp-pFDhmttdsh",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 865.5620487283002,
+ "y": 625.3277594079636,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 30.6666259765625,
+ "height": 19.000091552734375,
+ "seed": 974809482,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 266,
+ "versionNonce": 1061243656,
+ "isDeleted": false,
+ "id": "Tov8P7W3W8Zmma9a3S8gP",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 904.5620487283002,
+ "y": 626.661102913823,
+ "strokeColor": "#000000",
+ "backgroundColor": "#40c057",
+ "width": 30.6666259765625,
+ "height": 19.000091552734375,
+ "seed": 1423773654,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679706543901,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 148,
+ "versionNonce": 1167673464,
+ "isDeleted": false,
+ "id": "KiC12zdfqG7zXRbctXGmT",
+ "fillStyle": "hachure",
+ "strokeWidth": 4,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 806.4613995527118,
+ "y": 748.8279119958543,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 2.161352857758061,
+ "height": 20.33328247070324,
+ "seed": 167487754,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679706706153,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "B1eH_aNspf4OoiXnvWu1V",
+ "focus": 0.026931962058821583,
+ "gap": 12.327789925541765
+ },
+ "endBinding": {
+ "elementId": "fxSjNN3geJtdm-2MR7INN",
+ "focus": -0.06989783256192499,
+ "gap": 24.16110291382313
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 2.161352857758061,
+ 20.33328247070324
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 151,
+ "versionNonce": 1430888312,
+ "isDeleted": false,
+ "id": "wBnV18_fVimstqpfPY0KR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 631.4456683895414,
+ "y": 624.6666107177734,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 91,
+ "height": 20,
+ "seed": 1961347080,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": null,
+ "updated": 1679706671751,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func locals:",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func locals:"
+ },
+ {
+ "id": "8Y0Qz7jDPtVE84-d_UHu2",
+ "type": "rectangle",
+ "x": 613.2790118954008,
+ "y": 575.9999542236328,
+ "width": 384.0000305175781,
+ "height": 76.66668701171875,
+ "angle": 0,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "seed": 743618568,
+ "version": 80,
+ "versionNonce": 129563000,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1679706644458,
+ "link": null,
+ "locked": false
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.svg b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.svg
new file mode 100644
index 000000000..f054c4345
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/stack_format_ci.svg
@@ -0,0 +1,16 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 766.1088005500188 695.0001220703125" width="766.1088005500188" height="695.0001220703125">
+ <!-- svg-source:excalidraw -->
+
+ <defs>
+ <style class="style-fonts">
+ @font-face {
+ font-family: "Virgil";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Virgil.woff2");
+ }
+ @font-face {
+ font-family: "Cascadia";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Cascadia.woff2");
+ }
+ </style>
+ </defs>
+ <rect x="0" y="0" width="766.1088005500188" height="695.0001220703125" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(68.10867847970633 162.50004577636707) rotate(0 213.8333282470703 234.33338928222662)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.48 6.11 C0.81 4.26, 2.17 3.77, 5.28 0.23 M-0.28 6.35 C1 4.64, 2.91 2.91, 5.26 0.13 M-0.1 11.08 C1.02 8.41, 3.12 5.94, 10.55 -0.46 M0 11.58 C3.96 7.76, 7.38 3.2, 9.96 0.36 M0.99 19.37 C5.73 11.33, 10.12 4.27, 15.62 1.34 M-0.44 19.17 C3.67 13.44, 9.21 7.97, 15.41 0.99 M-0.55 22.39 C7.97 13.56, 16.86 5.32, 21.79 -2.02 M0.55 23.25 C5.64 18.07, 10.41 12.69, 21.81 0.47 M-0.93 32.48 C8.91 22.5, 15.83 13.49, 26.15 1.8 M-0.75 30.69 C6.99 22.39, 12.08 16.75, 25.86 -0.23 M-1.36 35.11 C8.16 30.12, 16.21 19.46, 30.65 0.15 M-0.82 35.92 C7.5 28.03, 17.35 17.12, 31.66 -0.93 M1.13 43.71 C12.24 25.77, 26.5 9.86, 36.06 2.06 M-0.59 42.74 C11.53 30.07, 22.78 17.73, 37.63 -0.44 M-1.01 50.62 C14.48 32, 28.59 16.82, 42.45 1.01 M-0.97 48.16 C15.89 29.25, 32.12 10.59, 42.16 -1 M1.99 54.64 C9.6 44.13, 19.3 33.94, 47.24 1.64 M0.1 54.8 C14.34 38.8, 30.25 20.25, 46.75 -0.62 M-0.78 59.71 C18.09 40.39, 37.08 19.13, 53.63 -1.48 M0.75 60.48 C15.98 43.77, 30.96 26.45, 53.58 0.53 M-1.07 66.49 C13.4 51.06, 26.23 36.23, 56.68 -1.07 M0.18 66.65 C18.44 44.27, 39.61 22.17, 58.71 -0.22 M1.84 71.28 C15.7 53.87, 34.11 32.55, 63.76 1.53 M1.06 72.2 C17.61 53.84, 33.74 35.88, 63.62 -0.48 M-1.65 81.09 C22.28 51.74, 46.46 24.25, 68.54 -0.8 M-0.09 79.39 C24.92 51.01, 49.85 20.74, 68.42 0.9 M0.48 85.08 C21.88 61.5, 45.2 36.79, 75.54 1.74 M0.12 84.19 C23.17 59.58, 45.79 34.04, 75.41 -0.62 M-0.21 93.39 C19.65 69.78, 41.2 46.1, 78.07 -1.39 M-0.97 91.93 C29.31 58.44, 55.2 27.8, 80.24 0.43 M-0.74 96.53 C22.46 70.5, 48.21 42.9, 86.78 -2.27 M-1.11 97.65 C16.55 76.19, 34.31 57.81, 85.52 -0.91 M-1.44 104.48 C32.19 62.46, 68.18 26.3, 91.65 0.17 M-0.66 103.99 C34.29 65, 68.62 26.82, 89.95 -0.37 M-0.64 109.64 C30.07 75.52, 60.81 42.98, 94.45 -1.04 M-0.28 109.08 C27.69 77.1, 55.66 44.66, 95.96 -0.83 M1.12 114.33 C25.77 84.62, 56.11 53.39, 98.79 1.79 M0.12 114.87 C31.22 80.78, 63.69 44.06, 100.8 -0.7 M-0.85 121.56 C37.69 82.15, 73.48 36.15, 106.6 -2.23 M0.44 122.81 C27.75 89.39, 55.57 57.67, 106.19 -0.28 M0.38 126.51 C29.91 93.85, 61.81 60.52, 112.13 0.22 M-0.6 128.16 C43.38 80.1, 85.76 31.06, 111.44 -0.16 M0.75 135.55 C35.71 90.5, 74.66 44.63, 117.79 2.12 M0.95 133.95 C38.39 87.65, 77.69 44.29, 116.43 1.17 M-1.64 141.23 C21.63 112.15, 46.68 82.59, 123.43 -0.88 M0.64 140.77 C41.86 91.92, 84.42 42.41, 121.99 -0.82 M1.42 145.77 C46.33 98.19, 88.69 45.6, 127.65 0.58 M0.62 145.21 C41.62 96.93, 84.49 46.78, 126.32 1.23 M-1.61 151.89 C35.73 109.49, 73.64 68.48, 131.68 0.9 M0.67 151.53 C44.66 102.1, 88.5 49.71, 132.03 0.74 M0.77 158.09 C55.61 93.67, 110.76 32.58, 137.02 -0.96 M-0.4 159.49 C28.5 124.58, 58.14 91.11, 137.03 -0.47 M-0.96 165.6 C31.09 125.05, 65.11 86.48, 142.65 -0.63 M0.66 163.76 C34.4 124, 69.38 83.81, 142.49 -0.13 M-0.01 170.64 C35.95 127.09, 76.59 81.31, 146.56 0.75 M-0.56 171.31 C40.27 123.77, 81.67 76.91, 147.64 0.15 M-1.26 177.24 C51.77 114.34, 108.48 52.54, 153.6 -1.51 M0.93 176.56 C48.72 121.98, 94.21 67.83, 153.66 -0.95 M0.6 183.09 C36.96 140.38, 73.55 99.64, 159.27 1 M0.83 182.79 C33.28 146.41, 64.82 110.3, 158.75 1.06 M1.14 188.74 C43.22 137.76, 90.15 86.63, 164.72 0.76 M-0.91 189.53 C50.68 129.61, 101.88 69.38, 163.73 0.08 M0.66 193.56 C65.32 121.54, 125.58 49.01, 170.67 1.2 M-0.31 194.7 C35.9 152.38, 71.02 113.08, 168.74 0.22 M1.19 201.91 C62.96 126.42, 126 52.26, 175.53 1.17 M-0.8 201.39 C40.32 154.17, 81.11 108.76, 175.41 -0.58 M0.93 205.75 C51.51 150.63, 99.96 91.86, 179.3 1.7 M-0.21 207.41 C51.61 150.19, 102.75 92, 180.47 0.13 M1.13 213.42 C64.39 141.58, 128.44 67.48, 184.9 0.57 M-0.46 212.77 C67.34 137.24, 135.26 59.73, 186.04 -0.22 M0.72 219.8 C53.07 160.49, 106.06 99.5, 189.25 -1.02 M0.34 220.14 C68.64 141.13, 136.92 63.14, 189.96 -0.31 M-0.06 224.79 C53.91 165.37, 105.66 104.27, 197.14 -1.1 M0.23 224.7 C71.89 141.22, 146.29 56.85, 195.84 0.22 M0.7 232.82 C51.36 174.26, 102.75 113.87, 200.52 0.74 M-0.78 231.19 C64.02 155.72, 131.73 79.4, 200.62 0.49 M-1.07 236.54 C69.65 154.55, 142.02 72.22, 206.81 0.99 M0.98 237.79 C59.25 167.74, 119.42 99.03, 207.47 -0.38 M-0.94 243.62 C52.15 184.29, 105.1 122.55, 212.5 -1.07 M-0.6 243.63 C53.47 183.29, 105.96 121.94, 212.2 -0.58 M0.73 249.1 C68.55 170.51, 135.96 89.5, 216.84 -0.71 M-0.88 250.24 C61.17 177.72, 124.24 105.81, 217.34 -0.52 M-0.41 255.12 C46.62 204.37, 93.37 150.41, 221.4 -0.74 M-0.4 256.48 C73.3 171.86, 145.76 88.36, 222.76 0.22 M0.98 262.56 C64.62 189.37, 129.64 114.62, 229.16 -0.29 M0.45 262.05 C70.04 181.54, 138.23 101.99, 228.58 -0.55 M-0.2 269.11 C61.58 196.69, 124.01 125.4, 233.71 0.74 M0.93 267.32 C74.71 181.81, 148.94 96.09, 232.88 -0.62 M1.2 273.3 C65.79 200.02, 130.86 123.86, 239.16 -0.2 M0.23 273.7 C52.57 211.54, 105.75 150.34, 237.81 -0.26 M-1.15 279.76 C65.96 204.35, 130.22 128.07, 244.53 -0.64 M-0.39 280.78 C86.61 182.8, 173.39 84.69, 243.91 -0.2 M0.31 286.59 C66.75 207.33, 135.29 128.85, 249.1 -0.52 M0.66 285.91 C74.1 199.13, 148.97 113.01, 248.53 0.5 M-0.27 293.5 C57.51 228.74, 114.01 162.68, 253.94 0.52 M-0.08 292.42 C76.33 204.56, 151.57 117.57, 254.32 0.14 M-0.78 299.28 C53.78 238.33, 104.22 179.1, 258.65 0.04 M-0.16 297.89 C88.48 198.81, 175.93 97.6, 259.28 0.19 M0.45 305.83 C73.34 219.89, 145.47 137.45, 266.03 -0.9 M-0.02 304.83 C100.6 188.16, 202.53 71.01, 264.75 0.14 M-0.26 311.07 C88.45 212.62, 173.7 111.23, 269.79 1.32 M-0.37 311.66 C80.3 219.78, 159.69 129.22, 270.19 -0.07 M-0.57 316.07 C83.24 221.08, 167.62 126.01, 275.12 -1.17 M0.61 317.13 C57.62 251.81, 113.03 186.72, 275.44 -0.64 M0.57 323.2 C70.83 241.12, 142.05 161.41, 281.58 0.47 M-0.04 323.4 C79.41 232.11, 158.94 140.47, 281.06 0.45 M1.04 329.24 C100.49 217.29, 199.13 102.08, 286.31 0.17 M0.16 328.39 C87.76 229.05, 173.75 130.36, 286.3 0.29 M0.45 336.13 C99.38 220.36, 198.35 107.51, 290.85 0.6 M-0.24 335.74 C112.79 206.45, 223.43 78.4, 291.44 0.11 M0.03 341.88 C112.83 209.51, 226.46 78.74, 297.52 -0.92 M0.22 341.3 C111.02 213.94, 222.45 86.21, 296.98 -0.12 M0.36 347.2 C83.87 247.68, 170.32 149.83, 302.13 -0.07 M0.31 347.17 C64.39 272.02, 128.73 198.1, 301.67 0.22 M-0.89 354.05 C103.11 236.14, 203.82 120.2, 308.49 -0.91 M0.03 353.87 C85.78 255.04, 173.1 155.39, 307.84 0.07 M0.73 359.11 C100.26 241.14, 202.89 122.54, 313.33 0.09 M0.62 358.96 C113.8 226.02, 229 94.19, 312.64 -0.15 M0.06 365.56 C78.96 274.67, 159.04 182.59, 318.65 -0.9 M0.45 365.44 C75.57 279.48, 150.05 193.23, 318.09 -0.37 M-0.81 372.63 C83.96 276.57, 167.26 182.25, 322.47 0.22 M-0.16 371.85 C124.83 229.53, 248.8 86.32, 323.17 -0.24 M-0.38 378.44 C117.07 244.61, 231.77 111.97, 328.81 -0.6 M0.04 377.91 C68.93 298.89, 136.57 220.82, 328.49 -0.17 M0.09 384.23 C66.48 308.53, 133.81 231.48, 333.87 0.81 M-0.3 384.13 C119.16 245.41, 239.39 108.05, 333.65 0.38 M1 389.26 C131.92 237.87, 263.44 87.92, 339.28 -0.23 M0.5 389.6 C108.68 266.62, 216.63 142.33, 339.41 0.01 M0.39 395.57 C78.77 302.71, 157.52 210.98, 344.77 0.27 M0.44 396.26 C120.27 259.6, 239.49 122.74, 344.19 0.4 M-0.13 403.01 C85.6 303.71, 173.05 203.44, 349.35 0.41 M0.17 402.68 C88.3 300.68, 176.77 198.96, 349.61 0.14 M0.71 408.62 C130.99 258.73, 260.31 110.08, 355.39 -0.25 M0.37 408.56 C127.83 263.48, 254.54 118.01, 355.49 -0.03 M-0.03 413.94 C135.54 259.91, 271.25 102.96, 359.97 0.32 M-0.05 414.47 C89.37 312.86, 178.57 209.88, 360.39 0.15 M-1 420.86 C133.9 267.02, 267.16 114.01, 365.58 -0.03 M-0.69 421.13 C128.21 271.86, 258.14 121.79, 365.6 -0.18 M-0.51 426.1 C128.99 274.49, 261.11 125.09, 371.36 0.36 M0.15 426.77 C110.2 298.16, 220.81 170.64, 370.83 0.47 M-0.33 433.46 C123.59 288.4, 250.06 143.74, 376.44 -0.41 M-0.37 433.22 C98.69 318.83, 199.37 203.48, 376.38 -0.26 M0.14 439.17 C117.06 304.79, 232.91 171.51, 380.84 0.15 M-0.08 438.87 C136.16 283.9, 272.39 127.01, 381.28 0.57 M-0.02 444.63 C121.62 305.43, 245.04 164.26, 387.14 0 M-0.09 445.37 C139.63 283.96, 280.94 121.48, 387.04 0.14 M-0.6 451.49 C119.01 316.3, 236.52 180.66, 391.8 0.48 M-0.08 451.41 C128.48 303.26, 256.67 155.66, 391.83 0.58 M0.71 457.74 C124.82 316.56, 247.62 175.37, 398.08 0.58 M-0.07 457.21 C116.33 325.48, 231.59 193.27, 397.38 -0.37 M-0.39 463.52 C142.64 300.4, 285.31 136.98, 402.47 0.08 M0.14 463.42 C108.3 336.72, 218.39 210.37, 402.36 0.44 M0.7 469.32 C98.39 355.16, 198.39 240.16, 407.7 0.23 M0.1 468.96 C94.52 360.09, 188.2 252.14, 408.55 -0.13 M5.05 469.13 C96.19 363.21, 187 258.48, 413.92 0.44 M5.91 469.21 C93 369.9, 180.12 270.02, 413.33 -0.09 M10.51 469.78 C92.93 374.57, 175.47 278.04, 418.91 -1 M11.05 469.42 C145.86 312.2, 282.18 155.74, 419.1 -0.07 M16.32 469.29 C103.39 371.74, 188.32 273.61, 423.69 -0.62 M16.56 468.87 C147.51 315.78, 279.34 164.3, 424.17 0.18 M20.99 468.44 C104.25 373.71, 188.61 276.54, 428.82 0.46 M21.41 468.95 C144.76 327.75, 268.47 185.8, 429.09 0.28 M27.19 468.28 C169.86 306.11, 311.74 142.51, 427.84 7.49 M27.1 468.48 C161.18 313.21, 296.84 157.41, 428.97 6.65 M31.5 468.47 C123.03 367.5, 210.96 265.29, 428.17 13.5 M31.7 468.87 C112.28 378.34, 191.08 287.78, 428.38 13.36 M37.26 469.48 C137.43 357.24, 234.34 245.37, 429.32 18.59 M37.73 468.67 C169.16 316.61, 302.29 163.99, 428.84 18.66 M42.68 469.41 C182.75 308.47, 323.53 146.96, 428.39 25.58 M43 468.71 C133.42 363.54, 226.19 256.82, 428.38 25.7 M48.98 469.38 C136.45 370.6, 222.44 270.95, 429.2 30.27 M48.42 469.09 C193.38 303.75, 336.87 139.11, 428.7 30.78 M53.21 468.74 C158.61 349.78, 262.86 228.34, 428.72 37.33 M53.75 469.45 C202.69 297.94, 350.34 127.98, 428.47 37.21 M59.65 468.85 C193.1 313.92, 328.2 158.36, 427.76 44.14 M58.91 468.42 C152.22 361.5, 243.78 255.55, 428.05 43.47 M64.61 468.3 C199.99 313.04, 336.75 157.28, 428.71 49.75 M63.78 468.67 C206.91 303.53, 349.58 139.64, 428.48 49.32 M68.77 469.05 C166.98 353.45, 267.76 238.1, 428.47 55.85 M68.86 469.11 C182.98 340.36, 295.74 210.84, 428.89 55.53 M74.87 469.46 C208.94 314.6, 343.73 159.9, 429.16 61.79 M74.31 469.38 C185.94 338.47, 298.21 208.83, 428.8 61.63 M79.07 470.02 C195.58 336.63, 310.87 203.36, 429.33 67.71 M79.68 469.58 C177.18 357.82, 275.03 244.77, 428.65 67.84 M84.81 468.37 C218.54 314.01, 353.29 160.52, 428.28 74.33 M85.5 468.83 C158.03 383.54, 231.81 298.39, 428.13 74.37 M90.93 468.84 C171.77 375.66, 252.58 282.48, 428.6 79.19 M90.57 469.54 C166.57 381.51, 242.25 294.68, 428.38 79.58 M96.52 468.71 C173.88 380.19, 250.81 291.07, 429.08 85.51 M95.72 468.87 C189.44 363.83, 281.45 257.1, 428.54 86.09 M100.26 469.36 C181.68 378.73, 260.4 287.15, 429.01 92.52 M101.17 469.37 C220.31 332.6, 340.44 195.24, 428.91 92.14 M106.93 468.91 C195.75 365.92, 285.36 263.22, 429.07 98.51 M106.29 468.8 C190.08 373.35, 274.09 276.51, 428.26 98.26 M112.27 468.53 C218.03 346.7, 325.93 222.95, 429.15 105.5 M111.73 469.26 C202.18 365.77, 293.17 260.88, 428.61 105.1 M117.41 468.52 C194.85 379.4, 271.19 292.32, 429.26 110.46 M117.56 468.51 C202.81 371.05, 288.8 272.44, 428.4 110.62 M121.98 469.51 C205.52 372.74, 290.35 277.16, 429.05 116.13 M122.18 469.26 C224.52 354.25, 325.24 238.27, 428.29 117.18 M127.28 468.29 C246.5 333.79, 366.18 196.18, 428.56 122.95 M127.91 468.59 C245.07 334.98, 361.38 201.03, 429.12 122.7 M132.41 469.85 C228.23 360.42, 323.42 249.98, 428 127.85 M133.21 469.19 C245.99 340.06, 359.06 209.55, 428.33 129.18 M139.26 468.62 C234.61 357.93, 329.4 247.98, 428.51 136.17 M137.96 468.56 C202.04 396.25, 264.31 324.14, 428.67 135.42 M142.79 470.03 C231.4 366.67, 319.62 266.04, 429.56 141.44 M143.31 469.65 C228.68 368.89, 315.38 270.44, 428.7 140.95 M149.97 469.37 C262.33 340.14, 372.19 213.73, 428.51 147.29 M149.28 468.67 C243.43 359.63, 339.81 249.65, 428.81 147.23 M153.88 470.01 C210.57 403.53, 268.97 335.55, 429.05 152.89 M153.54 469 C233.23 377.62, 312.8 285.87, 429.05 153.14 M159.14 469.76 C235.25 377.85, 314.91 288.89, 429.46 159.26 M160.16 468.94 C242.63 375.52, 323.76 281.83, 429.15 159.76 M163.81 469.15 C254.37 366.38, 342.27 264.51, 428.61 166.45 M164.93 469.48 C245.41 375.45, 327.77 280.53, 428.01 165.92 M170.64 468.19 C231.68 396.29, 295.63 324, 428.1 171.82 M170.49 469.17 C269.93 352.63, 369.42 237.69, 428.51 171.43 M174.56 468.37 C260.34 367.54, 348.78 267.29, 427.73 177.11 M174.78 468.84 C247.01 386.85, 319.72 302.56, 428.02 178.01 M181.31 469.33 C240.27 400.73, 300.04 334.43, 429.71 183.92 M181.03 468.84 C240.08 399.33, 299.53 330.62, 428.78 183.76 M185.48 468.09 C243.19 403.88, 298.69 336.96, 427.95 190.61 M185.71 469.03 C257.93 389.05, 327.93 307.11, 428.23 190.15 M191.21 468.7 C282.81 360.13, 377.78 254.32, 429.23 196.89 M190.41 469.09 C255.53 396.88, 320.02 323.23, 428.66 196.49 M197.8 468.07 C279.17 373.67, 362.69 278.69, 428.75 201.84 M196.62 469.54 C277.46 373.64, 359.19 278.88, 429.32 202.04 M201.92 468.37 C287.35 369.07, 373.34 267.97, 427.46 209.18 M201.37 469.89 C254.8 408.04, 307.29 348.51, 428.34 207.95 M207.01 469.96 C295.45 367.81, 382.89 269.61, 428.91 214.74 M207.15 469.45 C265.3 400.49, 322.82 333.32, 429.01 214.4 M212.51 469.81 C258.44 417.61, 301.15 366.65, 428.04 220.7 M211.79 469.31 C265.65 407.41, 319.31 347.1, 428.2 219.76 M218.4 469.3 C299.1 376.2, 379.08 284.42, 428.53 225.55 M217.9 468.75 C293.6 380.12, 370.66 291.25, 427.8 227.1 M222.05 470.17 C269.67 416.11, 318.29 359.83, 429.67 232.52 M222.42 469.62 C301.15 378.91, 380.23 288.7, 429.05 232.65 M228.79 468.77 C288.85 402.4, 345.73 336.02, 429.16 238.28 M229.14 468.62 C302.26 385.19, 373.98 301.44, 427.91 238.74 M234.72 468.28 C301.23 392.27, 367.48 312.96, 430.16 245.09 M233.71 468.69 C285.18 408.85, 336.42 348.93, 428.44 244.17 M239.86 467.66 C284.17 415.38, 331.27 363.1, 429.77 250.21 M239.26 468.56 C295.88 402.69, 353.9 335.41, 429.35 251.39 M245.46 468.07 C316.29 386.52, 387.72 306.6, 428.75 255.71 M244.2 469.84 C299.2 407.9, 353.02 346.25, 428.61 256.48 M249.74 467.39 C305.67 407.21, 361.68 341.14, 429.24 262.66 M249.11 469.21 C287.14 425.8, 325.32 380.98, 429.31 263.1 M254.13 469.98 C315.69 399.71, 376.78 328.89, 429.08 270.71 M254.95 468.64 C321.85 388.6, 390.55 309.39, 428.97 269.38 M258.82 468.67 C308.98 413.55, 357.84 357.34, 428.82 276.28 M260.81 469.34 C301.89 419.69, 345.12 369.79, 428.93 274.49 M266.39 470.32 C327.25 399.02, 385.56 328.53, 429.18 282.51 M265.09 469.46 C309.22 417.11, 353.48 365.84, 427.88 281.47 M270.16 468.04 C324.56 407.4, 377.9 346.16, 428.56 288.25 M271.3 468.86 C327.03 405.62, 382.14 342.38, 428.42 288.36 M274.44 470.67 C324.66 415.2, 369.82 359.95, 430.22 294.17 M276.5 468.48 C333.53 401.91, 390.99 336.1, 428.82 293.3 M283.03 467.47 C333.42 410.09, 383.74 349.57, 429.8 298.93 M281.78 468.98 C337.92 402.14, 394.24 338.06, 427.87 299.95 M286.09 468.39 C342.16 404.05, 397.03 343.55, 429.23 304.71 M287.37 469.69 C332.88 416.97, 377.27 364.5, 428.27 305.12 M292.24 468.21 C342.62 413.42, 390.12 356.72, 427.59 310.22 M291.35 468.95 C345.14 405.92, 398.66 344.48, 428.28 311.28 M298.63 470.28 C342.07 417.25, 389.65 361.59, 428.62 316.39 M296.91 468.22 C332.17 429.15, 368.14 388.56, 428.28 317.57 M301.44 467.57 C347.83 417.85, 392.2 368.39, 427.14 322.24 M301.41 470.15 C349.76 413.77, 398.26 358.85, 429.22 323.38 M308.16 468.04 C347.63 423.26, 386.7 377.21, 428.69 328.19 M307.43 469.33 C350.38 422.94, 391.03 375.42, 429.02 330.51 M312.41 471.17 C342.48 434.36, 372.92 398.66, 429.72 335.27 M313.5 469.19 C344.16 431.09, 377.71 393.67, 428.9 335.92 M316.95 470.74 C358.35 425.17, 396.03 380.18, 430.62 340.87 M319.19 468.84 C341.94 440.9, 366.93 413.12, 427.82 341.84 M323.89 469.71 C358.49 431.22, 393.55 388.43, 428.97 349.58 M324.14 468.62 C346.33 443.35, 369.02 416.77, 428.84 347.63 M327.12 466.98 C353.88 444.55, 374.75 416.85, 427.44 352.64 M329.69 469.71 C363.65 429.02, 396.88 390.53, 428.13 354.07 M334.38 468.1 C354.9 446.88, 372.44 422.21, 427.79 358.75 M334.05 469.76 C355.2 443.29, 379.57 418.19, 428.08 361.1 M339.73 468.09 C365.34 439.87, 388.36 413.08, 426.65 365.52 M339.87 468.53 C366.87 438.72, 392.69 409.8, 428.24 366.09 M345.53 470.11 C363.47 445.51, 383.59 423.43, 428.88 374.5 M345.41 469.49 C376.03 433.06, 407.03 398.37, 427.76 371.75 M350.97 468.28 C377.57 436.37, 410.58 402.47, 428.81 378.16 M350.12 469.46 C367.46 448.78, 386.19 429.62, 427.79 378.07 M354.08 470.39 C379.27 443.77, 399.78 415.84, 430.07 383.41 M355.81 468.25 C383.19 436.58, 413.44 403.04, 428.45 384.56 M360.18 468.64 C385.55 441.66, 410.17 411.95, 427.64 390.33 M360.26 468.24 C375.53 450.95, 391.6 433, 427.94 392.03 M367.93 470.45 C385.14 449.96, 401.98 430.34, 427.65 395.69 M366.31 470.05 C379.84 453.42, 394.77 435.63, 427.51 396.82 M369.81 469.13 C395.61 441.65, 418.41 415.44, 428.67 403.92 M371.55 468.13 C393.59 442.07, 414.92 417.68, 427.89 402.78 M378.09 470.7 C392.92 447.63, 409.24 428.25, 427 410.16 M377.38 468.44 C394.48 447.3, 414.71 424.38, 427.69 409.11 M381.41 468.58 C401.19 448.21, 418.81 426.64, 428.51 415.71 M382.68 468 C395.84 451.66, 410.64 436.75, 428.34 414.71 M386.69 470.39 C403.9 448.58, 418.89 433.17, 426.66 422.8 M386.93 468.58 C399.1 457.6, 410.08 443.31, 429.23 421.85 M391.69 468.69 C405.87 451.93, 417.67 435.93, 430.29 426.1 M393.81 468.26 C405.14 455.31, 417.1 441.68, 428.71 428.51 M398.99 467.69 C409.66 456.99, 419.87 443.59, 428.95 431.68 M398.33 469.13 C407.78 457.91, 416.83 447.6, 428.45 434.26 M404.48 470.06 C414.61 457.83, 423.74 447.54, 430.19 440.09 M404.49 468.87 C409.77 462.24, 416.68 453.67, 427.87 440.17 M407.37 467.62 C414.49 461.74, 417.93 457.33, 427.33 445.77 M408.36 468.37 C412.99 461.8, 419.39 456.8, 429.11 445.13 M414.71 468.13 C417.5 461.54, 425.39 458.03, 429.56 451.85 M413.74 469.37 C418.85 464.18, 423.53 458.69, 428.14 451.53 M419.28 469.74 C423.29 466.17, 426.08 460.67, 429.28 457.88 M419.21 468.37 C421.49 466.58, 423.94 464.45, 427.92 457.83 M424 469.59 C425.34 467.86, 427.04 465.68, 428.99 464.63 M423.84 469.45 C425.51 467.53, 426.81 466.12, 428.43 463.77" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M-0.54 -0.85 C154.12 -0.5, 307.43 -1.34, 428.36 0.88 M-0.09 0.26 C89.57 0.85, 178.88 1.38, 427.32 0.09 M428.48 0.79 C428.64 132.9, 428.98 264.85, 427.94 467.86 M427.94 0.09 C428.31 175.72, 428.19 350.97, 427.38 468.53 M427.69 468.04 C307.19 468.75, 186.52 468.97, 0.94 468.24 M428.12 468.34 C337.75 468.47, 247.4 468.43, -0.11 468.21 M0.67 469.21 C-0.8 349.65, -1.24 229.33, -0.71 -0.13 M0.38 468.35 C0.87 306.07, 1.36 143.13, -0.4 -0.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(136.10870899728445 196.66673278808594) rotate(0 45.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">prev_frame</text></g><g transform="translate(136.10870899728445 231.66673278808594) rotate(0 42 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_inst </text></g><g transform="translate(136.10870899728445 266.66673278808594) rotate(0 6.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">ip</text></g><g transform="translate(132.44205250314383 301.3334197998047) rotate(0 80 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">opnd_stack_bottom</text></g><g transform="translate(136.10870899728445 336.66673278808594) rotate(0 137.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">opnd_sp (point to opnd stack top)</text></g><g transform="translate(136.10870899728445 371.66673278808594) rotate(0 81.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">label_stack_bottom</text></g><g transform="translate(136.10870899728445 406.66673278808594) rotate(0 140 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">label_sp (point to label stack top)</text></g><g transform="translate(110.10870899728445 472.33338928222656) rotate(0 62.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func arguments:</text></g><g transform="translate(184.7753960090032 555.3335113525391) rotate(0 65.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">&lt;operand stack&gt;</text></g><g stroke-linecap="round" transform="translate(106.77530445626883 186.1667022705078) rotate(0 189.16673278808594 16.833351135253906)"><path d="M0.58 -0.77 C95 1.45, 190.96 2.08, 378.36 -0.73 M-0.27 0.55 C129.45 -2.06, 259.56 -1.59, 378.86 -0.38 M378.48 -0.43 C376.65 9.46, 379.13 22.19, 379.82 34.88 M378.29 -0.78 C378.42 10.54, 378.08 21.03, 379.17 32.96 M378.51 32.6 C278.38 34.19, 178.5 34.35, -0.41 33.32 M377.81 33.27 C281.04 35.44, 183.63 35.55, -0.18 33.17 M-1.7 34.12 C0.05 23.51, 1.54 12.52, -0.55 -0.72 M0.9 34.03 C0.04 25.26, 0.51 16.63, -0.05 -0.13" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(106.1086479621282 229.50003051757812) rotate(0 188.83340454101562 14.166664123535156)"><path d="M0.18 -0.75 C149.08 0.96, 297.55 0.51, 377.55 -0.95 M-0.06 -0.12 C80.08 -1, 159.23 -0.73, 377.39 -0.36 M377.34 0.35 C378.54 7.04, 377.82 13.35, 375.74 29.17 M377.09 -0.81 C378.04 6.74, 377.77 14.29, 376.79 27.67 M377.35 29.21 C303.21 27.29, 226.22 27.53, 0.05 28.53 M377.97 28.79 C285.78 25.99, 193.94 26.71, -0.01 28.21 M1.02 28.24 C-0.11 21.01, -0.53 17.16, -1.73 0.54 M0.66 28.99 C-0.73 20.49, -0.45 10.35, -0.07 -0.77" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(105.44196095040945 264.1667022705078) rotate(0 190.16665649414062 12.333328247070312)"><path d="M-1 0.6 C121.14 0.1, 239.6 0.48, 380.89 -0.01 M0 0.3 C106.25 0.7, 212.26 0.57, 380.77 -0.52 M379.92 1.32 C381.65 6.68, 381.8 15.3, 378.65 24.53 M380.6 -0.97 C379.99 5.73, 379.59 11.29, 379.5 24.79 M380.99 25.31 C269.88 25.64, 158.52 25.54, 1.2 25.2 M380.3 25.12 C248.79 26.26, 117.64 25.32, 0.13 25.14 M-0.77 23.62 C-1.33 17.38, 2.09 12.67, -1.77 0.8 M-0.62 24.79 C-0.47 15.51, -1.16 4.55, -0.96 -0.77" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(107.7752739386907 299.8333740234375) rotate(0 95.16665649414062 12.666679382324219)"><path d="M-1.5 0.42 C48.32 -0.72, 92.37 2.82, 189.56 -1.05 M-0.55 -0.88 C43.47 -0.89, 86.94 -2.04, 189.72 0.12 M189.2 -1.91 C188.94 8.75, 191.11 14.01, 189.87 23.68 M190.83 0.59 C190.15 8.49, 190.67 17.25, 189.93 26.24 M188.88 25.77 C135.38 25.95, 80.93 25.94, 1.5 23.95 M189.89 26.19 C128.61 26.88, 66.46 27.31, -0.03 25.91 M-1.68 23.82 C-0.37 14.11, -0.59 4.67, -0.72 -1.73 M0.86 25.37 C-0.09 20.27, 0.02 15.54, -0.14 0.71" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(108.77530445626883 332.1667022705078) rotate(0 188.8333282470703 14.000015258789062)"><path d="M0.88 1.13 C141.06 0.42, 283.81 -0.9, 378.38 0.23 M0.22 0.18 C111.52 -2.35, 223.98 -2.35, 377.51 -0.38 M376.3 -1.82 C379.14 7.47, 376.9 14.85, 377.36 28.76 M377.68 -0.52 C377.7 8.25, 377.21 16.98, 378.2 27.33 M376.58 29.18 C292.56 28.11, 208.16 29.21, 0.38 27.98 M377.11 27.89 C255.75 27.49, 132.92 28.07, -0.29 28.54 M0.64 29.32 C-1.01 17.52, 1.09 7.34, 1.52 -1.79 M0.56 28.19 C0.61 20.93, -0.66 15.2, 0.42 0.73" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(108.77530445626883 371.5000457763672) rotate(0 98.66670227050781 11.666641235351562)"><path d="M0.87 1.41 C66.79 -1.13, 138.28 -2.59, 196.47 1.29 M-0.73 -0.63 C45.41 2.33, 90.19 2.2, 196.62 -0.84 M198.47 -0.81 C196.87 8.03, 199.21 15.36, 195.61 22.03 M197.32 0.87 C196.89 8.39, 197.4 18.02, 196.53 24.28 M197.01 22.8 C143.53 25.68, 87.21 23.15, 1.69 22.74 M197.22 22.86 C149.41 22.68, 99.29 21.73, -0.01 23.65 M-0.7 24.83 C-0.21 13.81, -0.15 7.66, 0.04 -0.32 M0.56 24.32 C-0.16 14.53, -1.08 7.25, -0.85 -0.39" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(109.44196095040945 402.5000457763672) rotate(0 174.8333740234375 17.333328247070312)"><path d="M-0.62 0.91 C109.63 -0.77, 216.74 0.24, 350.08 0.52 M0.49 -0.09 C95.58 0.73, 192.26 0.81, 349.56 0.27 M351.64 0.09 C348.09 11.69, 349.46 25.17, 348.88 34.37 M349.29 -0.48 C349.88 8.36, 349.65 19.4, 349.54 35 M348.69 35.28 C220.91 34.28, 93.44 33.79, 1.12 33.84 M349.87 34.56 C272.89 37.01, 195.34 36.15, -0.33 35.01 M-2 32.78 C1.78 24.38, -1.94 11.56, 0.43 -1.96 M-0.64 35.42 C0.68 23.22, -1.08 11.45, -0.36 -0.9" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(107.44196095040945 468.83335876464844) rotate(0 176.16668701171875 15.8333740234375)"><path d="M0.96 0.54 C121.41 -0.7, 243.43 -2.21, 352.43 -1.03 M0.37 -0.07 C121.29 2.43, 241.7 1.57, 352.57 0.08 M352.99 -1.59 C351.89 12.4, 352.19 21.08, 351.17 33.44 M351.42 -0.28 C351.87 8, 352.73 17.16, 351.85 32.2 M353.26 30.41 C234.05 29.58, 113.84 28.25, -0.74 32.82 M352.7 31.41 C212.85 33.49, 73.35 34.13, -0.19 31.2 M-0.38 33.24 C0.27 25.68, 0.78 19.75, -1.14 -1.76 M-0.64 32.33 C-0.68 24.17, -0.07 16.5, -0.3 -0.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(69.7755180793157 90.16671752929688) rotate(0 212.1667022705078 35.333343505859375)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.48 6.85 C0.59 4.45, 3.06 3.49, 4.84 1.04 M-0.27 6.7 C1.58 4.04, 3.28 1.87, 5.18 0.55 M0.11 11.22 C4.04 6.34, 7.7 2.7, 10.74 -0.54 M-0.24 12.56 C2.44 9, 4.22 6.32, 10.86 -0.63 M-0.05 19.55 C5.92 13.26, 6.26 9.28, 16.28 0.78 M-0.43 18.97 C5.6 13.69, 8.6 7.05, 14.93 -0.5 M0.41 24.08 C9.14 15.72, 15.77 6.63, 22.18 -1.14 M0.68 24.41 C5.17 19.75, 8.46 14.72, 20.9 0.5 M-0.79 29.79 C11.21 17.84, 19.94 7.05, 24.32 1.5 M-0.4 30.53 C9.68 18.78, 19.94 8.05, 26.19 -0.43 M-0.54 38.02 C7.79 26.07, 14.13 19.59, 31.34 1.31 M0.5 37.05 C9.06 25.95, 18.12 15.17, 31 0.84 M0.46 43.83 C12.59 27.96, 21.68 18.14, 36.2 0.86 M0.8 42.53 C7.59 32.03, 16.65 22.62, 36.77 -0.29 M0.5 49.46 C9.47 37.9, 21.15 25.52, 42.15 -2.11 M0.75 49.01 C9.58 36.65, 21.28 26.53, 43.04 -0.87 M2.12 54.36 C15.26 34.31, 32.03 17.36, 46.25 -1.38 M-0.25 55.1 C11.59 41.14, 22.61 28.72, 47.79 0.04 M-0.28 60.41 C18.27 41.66, 35.56 20.72, 53.37 -1.08 M0.62 60.41 C19.89 38.75, 39.05 17.43, 52.39 -0.31 M0.8 65.96 C13.73 53.5, 27.22 34.37, 59.67 1.66 M-0.09 66.59 C18.19 45.86, 35.87 23.91, 57.9 0.09 M2.14 69.76 C17.76 50.15, 35.22 34.63, 62.65 -2.16 M0.82 70.52 C21.41 49.48, 39.31 28.76, 63.99 0.29 M4.51 72.52 C25.15 52.83, 42.15 33.81, 68.57 -0.02 M6.86 70.93 C27.57 46.21, 50.32 21.4, 69.32 0.84 M10.21 71.94 C36.22 46.4, 58.54 18.98, 74.51 -0.77 M12.2 70.53 C28.38 51.78, 42.84 33.41, 74.36 0.12 M17.01 71.88 C34.61 50.56, 51.27 30.82, 79.88 -1.27 M16.56 72.36 C38.59 46.37, 60.29 21.32, 79.84 0.72 M24.22 72.16 C41.79 50.54, 58.93 28.3, 84.36 -1.21 M22.12 70.66 C44.56 45.06, 66.99 18.94, 85.56 -0.18 M28.23 69.78 C42.43 53.23, 56.59 35.17, 91.45 -1.83 M27.9 71.28 C42.55 52.47, 58.56 36.01, 90.81 -0.43 M32.49 72.19 C50.85 51.01, 65.73 33.04, 94.45 -0.67 M32.67 72.02 C50.44 50.43, 68.09 31.12, 95.22 -0.55 M38.97 70.53 C60.65 48.09, 80.64 23.22, 99.98 1.67 M39.26 71.03 C62.21 43.49, 87.48 17.55, 101.14 0.68 M41.58 73.65 C56.49 53.47, 74 38.09, 105.95 -1.2 M42.85 71.91 C58.9 53.12, 74.94 34.64, 106.53 0.54 M48.87 73.58 C60.91 57.59, 77.92 42.37, 113.07 -0.24 M48.58 72.35 C72.99 45.24, 97.18 17.85, 111.31 0.8 M54.88 71.06 C77.05 46.5, 101.09 16.83, 118.2 -0.97 M53.21 72.79 C69.21 55.01, 86.07 36.02, 115.59 0.79 M60.44 73.51 C82.7 45.37, 105.88 14.98, 121.16 -1.95 M59.37 71.46 C74.5 56.68, 87.41 39.37, 121.34 0.07 M64.69 72.3 C85.13 45.77, 107.98 20.44, 127.43 -1.29 M63.88 72.84 C87.61 45.35, 110.95 19.66, 126.03 1.06 M71.08 72 C86.33 56.05, 97.75 39.21, 133.59 1.33 M70.68 71.98 C86.2 52.67, 101.17 35.77, 132.85 0.12 M74.86 71.63 C88.3 55.33, 100.13 43.67, 138.75 1.92 M75.19 72.91 C91.21 53.61, 106.82 33.68, 137.08 -0.05 M81.07 69.89 C103.41 48, 126.13 20.09, 142.58 1.46 M81.17 70.98 C102.42 47.81, 125.93 21.21, 142.98 -0.03 M84.08 70.44 C106.62 48.87, 129.87 25.18, 148.8 -0.9 M85.08 71.29 C106.39 48.57, 128.7 23.98, 148.17 0.7 M89.56 71.12 C106.36 51.33, 123.39 33.21, 155.2 1.45 M91 70.99 C111.57 48.03, 131.71 25.19, 154.47 0.11 M97.95 73.23 C115.68 48.24, 136.49 28.3, 157.11 -0.17 M96.99 71.72 C116.77 47.85, 137.95 24.35, 158.31 0.03 M102.55 70.76 C118.04 51.79, 131.41 35.6, 165.41 -0.54 M101.95 71.94 C124.22 46.89, 146.1 22.2, 163.6 0.46 M108.92 71.64 C121.31 53.31, 136.18 38.46, 170.06 0.79 M107.98 71.36 C127.56 48.69, 148.96 23.56, 170.07 0.05 M112.95 71.01 C133.34 45.57, 157 20.15, 174.06 0.72 M113.32 71.23 C131.42 50.38, 151.24 27.52, 174.21 0.37 M116.33 72.43 C138.37 44.12, 163.88 18.12, 180.94 1.83 M118.65 72.81 C140.06 44.92, 162.68 19.01, 179.58 0.36 M124.54 73.19 C144.72 46.91, 169.29 19.36, 184.84 1.63 M124 71.67 C140.49 51.21, 158.47 30.87, 185.73 0.64 M126.38 73.49 C151.44 45.05, 176.13 20.17, 189.9 1.87 M129.14 72.12 C140.31 58.02, 154.86 42.12, 190.54 -0.05 M135.95 69.75 C147.89 55.81, 162.41 36.21, 196.34 1.7 M134.43 71.53 C150.24 53.16, 165.11 35.06, 197.12 -0.52 M140.16 71.82 C162.73 45.48, 185.8 18.66, 199.94 -1 M139.19 72.76 C161.19 45.2, 186.41 18.7, 202.18 -0.72 M144.72 72.26 C164.37 48.59, 182.49 28.52, 206.02 -0.44 M144.61 70.5 C167.76 45, 189.74 19.57, 206.91 0.58 M149.63 71.56 C173.73 44.65, 193.81 18.96, 212.97 -1.59 M150.09 71.66 C171.58 49.18, 190.45 25.81, 211.34 0.23 M155.22 71.42 C177.84 42.3, 206.2 14.6, 218.22 0.97 M156.12 71.72 C172.13 50.01, 190.49 29.1, 217.22 -0.97 M161.62 71.97 C175.28 55.35, 187.74 43.13, 221.76 0.42 M160.68 71.16 C177.76 53.13, 193.8 33.64, 222.4 0.12 M166.09 73.8 C188.13 47.49, 211.84 21.16, 228.13 -1.18 M165.42 72.53 C183.19 54.05, 198.3 33.79, 227.69 -0.63 M169.84 71.43 C195.07 44.4, 214.66 19.38, 233.95 0.48 M171.37 71.07 C192.66 47.57, 214.48 23.76, 233.28 -0.28 M176.78 70.85 C198.7 46.41, 222.6 18.16, 237.2 1.87 M176.52 71.41 C191.59 53.95, 206.26 35.86, 238.9 0.34 M182.88 71.46 C194.99 54.32, 210.79 38.46, 244.07 1.17 M182.13 72.6 C198.36 54.74, 213.19 36.18, 243.51 -0.77 M187.65 71.39 C207.41 43.8, 230.31 17.87, 247.7 -0.25 M187.02 72.57 C209.69 45.59, 233.18 19.12, 248.95 -0.15 M192.19 72.68 C217.42 45.41, 240.92 17.98, 253.52 0.17 M192.51 72.43 C206.13 56.48, 219.71 39.48, 254.15 0.27 M198.61 70.61 C210.97 56.79, 225.96 41.19, 258.79 -0.53 M196.74 72.91 C212.05 53.39, 228.93 35.4, 259.52 -0.49 M204.11 70.87 C224.39 48.19, 244.43 24.62, 266.56 -1.68 M203.6 70.67 C217.15 55.23, 231.78 39.29, 265.82 -0.07 M208.42 70.85 C219.47 57.57, 232.39 42.26, 269.19 -1.59 M207.05 72.73 C228.8 47.51, 251.47 22.79, 270.53 -0.39 M211.84 72.89 C237.78 45.09, 259.67 18.75, 274.34 -0.44 M214.06 70.84 C225.55 57.55, 238.56 43.33, 274.73 0.71 M218.73 73.54 C238.29 49.72, 256.49 28.09, 280.48 1.09 M218.91 71.81 C239.88 44.99, 263.71 19.25, 281.46 -0.13 M223.48 72.77 C241.35 49.79, 263.24 27.8, 286.89 -1.04 M224.12 71.94 C237.7 57.46, 252.43 40.49, 286.62 0.56 M230.05 71.26 C249.71 49.69, 266.91 28.03, 293.13 -0.86 M228.8 71.34 C242.38 56.83, 254.61 42.44, 291.33 -0.53 M233.97 71.63 C256.65 45.8, 275.72 23.49, 297.09 -1.28 M235.55 72.37 C251.49 50.82, 269.77 31.55, 296.81 -1.13 M237.8 71.71 C254.93 50.54, 273.38 34.51, 302.46 -0.69 M238.81 71.96 C258.28 49.84, 275.94 28.82, 302.75 1.01 M245.16 69.75 C271.89 41.5, 293.14 15.88, 308.73 0.17 M245.72 72 C266.62 47.79, 285.28 25.6, 308.18 0.47 M252.23 73.71 C270.56 50.6, 290.34 24.36, 310.69 -0.49 M250.55 71.74 C263.5 55.76, 276.06 41.19, 311.87 0.54 M257.75 70.49 C268.48 56.92, 281.58 44.17, 316.44 -0.26 M255.53 72.11 C273.15 52.62, 290.48 33.86, 319.18 -0.4 M262.51 71.2 C278.45 54.35, 294.27 34.03, 322.9 0.72 M261.23 72.18 C277.33 51.53, 295.01 32.22, 322.43 -0.48 M267.33 72.38 C278.56 57.25, 292.93 42.49, 329.76 1.01 M267.46 71.44 C287.57 46.69, 308.8 22.05, 329.81 -0.03 M272.63 73.26 C291.04 50.86, 310.45 27.02, 335.04 -0.9 M271.6 72.25 C293.35 46.87, 316.75 20.06, 333.71 0.88 M275.7 73.79 C291.16 57.83, 304.05 41.1, 341.07 -1.32 M276.88 72.91 C297.7 47.62, 320.74 20.55, 339.63 -1.28 M281.51 72.09 C303.73 47.33, 327.93 22.44, 345.96 1.9 M281.98 72.32 C296.66 54.29, 313.19 35.69, 344.55 0.97 M285.51 73.99 C300.62 57.82, 310.22 43.56, 348.99 -0.67 M286.71 72.61 C300.94 56.83, 314.42 42.33, 349.13 1.18 M290.92 71.01 C312.49 46.98, 333.58 22.57, 353.35 -0.5 M292.23 72.22 C313 48.13, 332.79 24.94, 355.37 -0.41 M296.3 73.61 C317.16 50.14, 333.24 30.98, 360.97 -1.61 M297.44 72.33 C323.28 42.45, 347.89 14.44, 360.3 -0.17 M301.5 72.46 C319.43 50.5, 338.15 31.93, 365.82 1.41 M303.82 71.2 C319.33 54.06, 334.34 36.01, 366.14 -0.04 M307.16 71.66 C333.73 45.72, 357.85 16.61, 369.4 0.69 M307.82 72.57 C327.64 48.43, 347.3 26.6, 370.74 0.9 M312.77 70.02 C327.18 55.85, 342.24 39.47, 374.8 0.27 M313.74 71.98 C332.12 50.54, 350.03 30.92, 376.4 0.76 M320.06 70.28 C337.15 52.34, 356.08 29.56, 382.15 1.42 M318.11 71.23 C340.17 47.34, 361.11 21.17, 382.28 1.26 M323.12 72.38 C342.31 51.68, 364.04 29.61, 386.65 -0.16 M324.56 70.67 C336.98 56.81, 350.74 41.16, 387.25 0.08 M327.83 70.72 C343.97 55.91, 355.91 43.48, 390.01 -1.08 M330.17 71.66 C352.16 44.25, 376.49 17.77, 392.28 -0.77 M333.84 71.37 C350.67 52.88, 369.44 32.83, 398.56 -1 M334.41 70.87 C356.73 47.4, 378.45 22.54, 397.34 -0.54 M342.16 73.37 C359.02 48.87, 378.87 29.73, 402.62 -1.37 M339.42 72.68 C356.69 52.79, 372.88 34.57, 401.7 0.59 M345.07 69.93 C368.06 44.34, 392.9 17.74, 406.62 -0.23 M344.98 71.56 C367.7 45.66, 389.78 20.75, 408.9 -0.1 M349.66 73.74 C369.62 52.14, 385.29 31.9, 412.5 1.11 M350.82 72.49 C374.62 43.42, 399.4 15.61, 413.04 0.52 M355.83 70.14 C376.32 49.74, 390.83 29.88, 417.79 -0.73 M357.52 71.22 C372.98 51.61, 391.48 33.49, 419.72 -0.21 M359.77 70.46 C384.73 46.11, 407.85 21.27, 423.05 2.07 M360.91 72.77 C379.87 51, 398.87 28.71, 424.37 -0.34 M368.01 73.2 C390.42 47.3, 410.92 20.23, 427.28 0.79 M366.87 71.71 C381.01 56.68, 396.04 40.28, 426.52 2.03 M372.84 73.3 C387.07 56.12, 399.21 42, 425.32 8.63 M371.78 72.62 C388.57 54.63, 402.65 36.91, 428.09 8.39 M378.39 71.42 C396.89 52.46, 415.31 28.28, 426.55 13.74 M377.38 72.37 C393.96 51.4, 411.98 32.25, 426.96 13.93 M384.07 71.14 C391.07 58.88, 401.52 48.45, 428.39 22.21 M383.11 72.58 C398.88 53.46, 412.28 37.25, 427.34 19.69 M385.95 73.01 C395.55 61.08, 406.09 52.46, 427.06 27.59 M388.36 72.71 C397.23 59.81, 409.28 46.82, 427.4 27.17 M391.54 71.99 C401.26 60.09, 413.11 50.3, 426.92 32.86 M394.11 72.65 C400.61 63.03, 409.68 54.12, 427.5 33.48 M398.54 71.02 C406.65 60.17, 419.02 50.56, 427.26 39.96 M398.62 71.41 C408.79 59.57, 419.76 46.74, 427.86 37.92 M404.21 70.98 C409.94 64.71, 417.3 55.18, 425.1 43.28 M403.58 72.22 C411.04 63.61, 418.31 55.28, 426.19 44.65 M408.88 71.93 C415.94 63.58, 421.22 58.43, 428.49 51.62 M408.56 72.88 C416.76 63.77, 423.81 55.9, 427.95 51.78 M413.96 70.44 C420.21 67.35, 422.46 61.31, 428.02 57.52 M413.89 72.13 C419.33 65.71, 424.09 60.99, 426.68 57.75 M420.56 72.3 C421.15 70.31, 422.65 67.94, 426.58 63.44 M419.22 72.1 C421.7 70.11, 422.7 68.73, 426.5 64.18" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-0.38 -0.99 C129.93 1.12, 260.67 0.49, 424.57 0.6 M0.19 -0.52 C122.35 1.73, 244.37 2.19, 424.44 0.22 M426.25 1.17 C425.12 26.67, 423.52 50.29, 423.57 69.94 M425.17 0.86 C424.17 28.45, 425.56 54.21, 424.21 70.51 M424.49 70.85 C265.49 69.39, 108.23 69.4, -0.73 70.59 M424.8 70.31 C310.66 70.63, 196.23 69.69, 0.25 70.39 M0.65 71.59 C-1.35 54.35, 2.21 39.95, -1.61 -0.57 M0.98 70.15 C0.08 54.29, -0.18 39.72, -0.52 -0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(236.10886158517508 510.5000457763672) rotate(0 15.33331298828125 9.500045776367188)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.61 6.43 C1.18 3.41, 4.43 1.85, 5.73 0.49 M-0.62 6.36 C1.58 4.31, 3.14 2.27, 5.32 0.39 M-0.78 11.49 C3.85 7.54, 6.94 2.21, 9.88 -0.43 M0.25 12.52 C3.3 7.92, 6.26 3.57, 10 -0.38 M-1.79 20.03 C7.32 12.57, 10.6 5.33, 14.6 1.4 M-0.87 18.09 C6.1 10.81, 11.45 3.72, 15.74 -0.34 M1.49 20.55 C7.14 16.39, 11.5 11.06, 22.77 -0.47 M3.07 21.89 C7.77 15, 12.98 9.46, 20.97 -0.75 M6.73 22.65 C14.83 12.17, 20.98 4.84, 25.72 -1.15 M8.75 21.15 C13.81 14.75, 21.71 6.76, 27.16 0.98 M14.75 19.03 C20 14.07, 24.68 7.45, 30.62 2.3 M12.66 21.19 C20.55 13.7, 24.56 7.48, 30.42 0.82 M18.06 20.58 C23.21 18.18, 25.85 13.64, 29.81 6.31 M18.78 21.91 C21.67 18.14, 23.72 15.71, 31.68 6.79 M24.19 20.78 C27.35 18.83, 29.91 16.15, 31.35 12.41 M24.5 21.1 C25.71 19.27, 26.97 17.28, 31.79 13.07" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M-1.28 0.1 C7.3 0.89, 19.21 0.99, 29.41 -0.36 M-0.91 0.04 C8.64 0.05, 17.98 -0.77, 30.38 0.69 M30.07 -1.6 C30.28 5.37, 29.38 8.92, 31.42 18.58 M30.44 -0.85 C30.92 6.09, 30.99 11.51, 29.88 18.64 M31.74 17.56 C20.87 17.92, 12.46 20.57, 1.76 20.54 M30.96 19.22 C21.39 19.68, 11.28 18.24, 0.43 19.23 M1.13 18.67 C0.78 11.84, 1.02 7.88, 0.15 0.14 M-0.31 18.59 C0.32 13.14, 0.64 9.88, -0.23 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(255.44234242013601 474.00006103515625) rotate(0 18.999984741210938 9.8333740234375)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.15 5.81 C1.15 4.64, 2.4 4.48, 4.91 -0.19 M-0.51 6.08 C0.7 5.09, 1.86 3.46, 5.2 0.38 M0.59 11.75 C2.95 10.48, 4.67 6.26, 10.19 1.21 M0.22 11.68 C3.85 8.02, 6.16 4.9, 10.19 0.43 M-1.66 18.17 C2.35 13.5, 5.96 10.69, 14.22 0.21 M0.64 19.17 C6.24 12.45, 12.79 4.69, 14.85 0.51 M1.75 21.62 C8.66 13.23, 17.85 6.61, 19.53 -0.6 M1.67 20.84 C6.3 16.14, 10.52 11.63, 20.29 0.47 M8.3 22.42 C12.52 13.6, 18.17 7.63, 26.92 1.35 M7.78 21.34 C14.31 14.46, 20.28 7.91, 25.33 -0.59 M13.97 23.16 C20.07 14.99, 23.94 6.52, 32.37 0.99 M12.92 21.52 C19.3 14.56, 27.35 5.94, 30.96 0.79 M18.41 22.11 C22.08 17.9, 26.21 12.59, 36.95 0.71 M18.75 20.7 C23.29 16.49, 27.67 11.09, 37.42 0.2 M24.38 22.95 C27.92 18.02, 30.63 12.89, 41.29 3.32 M23.15 21.28 C28.88 15.48, 34.03 10.18, 39.79 1.16 M30.02 21.51 C31.39 17.86, 34.96 14.87, 38.59 7.93 M29.74 20.54 C31.69 18.69, 34.93 15.14, 39.87 7.95 M34.91 21.2 C35.14 20.45, 37.58 18.12, 41.09 14.88 M33.82 21.62 C35.63 20.19, 37.42 17.72, 41 14.12" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M-1.37 -1.66 C14.71 2.05, 28.4 0.44, 38 1.45 M0.46 -0.54 C11.54 0.38, 25.27 0.35, 38.33 0.77 M37.3 1.12 C39.87 7.23, 38.11 13.35, 37.32 20.48 M37.05 0.6 C38.7 5.03, 37.91 10.12, 38.05 19.3 M37.88 18.22 C26.35 19.52, 15.6 19.57, 1.15 19.79 M37.73 20.38 C30.23 19.89, 22.51 20.54, 0.17 19.84 M-1.75 21.52 C0.01 16.45, 0.31 9.9, 1.29 1.76 M-0.33 19.97 C-0.63 16.34, 0.09 12.03, 0.01 -0.79" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(308.77565540841726 475.33331298828125) rotate(0 17.999984741210938 7.8333892822265625)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.77 5.76 C0.46 5.14, 1.59 3.25, 5.42 0.41 M-0.15 6.32 C1.05 5.31, 2.09 3.57, 4.88 0.67 M0.31 11.32 C4.32 7.78, 5.61 5.39, 9.75 0.89 M-0.48 11.93 C2.11 8.89, 4.57 6.59, 10.07 -0.08 M2.72 18.4 C7.28 12.44, 13.77 4.5, 14.08 0.7 M0.94 16.83 C6.23 10.57, 12.61 5.22, 14.75 0.06 M5.69 14.59 C9.94 11.22, 13.33 8.01, 19.32 1 M7.04 17.03 C10.63 10.91, 14.91 6.25, 21.59 0.46 M11.61 16.72 C17.52 11.49, 22.15 6.78, 24.41 -1.48 M12.37 17.59 C16.92 11.75, 20.35 5.8, 26.49 0.84 M17.56 15.97 C21.79 11.98, 29.31 4.63, 30.04 1.68 M17.41 16.86 C20.38 13.53, 23.56 9.61, 31.92 0.12 M22.92 15.47 C26.75 12.95, 30.3 8.14, 37.96 0.14 M22.89 17.46 C26.23 13.22, 29.16 8.84, 37.25 0.85 M27.64 15.86 C31.23 12.66, 34.07 10.2, 35.63 5.4 M28.43 16.53 C30.15 13.82, 32.69 11.33, 35.97 6.43 M33.43 16.35 C33.71 16.19, 34.79 15.05, 36.11 12.71 M33.27 16.7 C33.68 16.11, 34.62 15.14, 36.45 13.23" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M0.92 -1.07 C9.9 0.82, 24.18 0.77, 36.66 1.55 M-0.36 0.57 C13.91 -0.08, 25.96 -0.56, 35.65 0.41 M34.49 0.95 C37.19 3.81, 35.93 7.74, 36.08 15.08 M35.95 -0.57 C35.55 4.21, 35.47 8.57, 36.45 15.72 M35.45 17.08 C28.49 16.01, 21.08 17.29, 0.34 16.01 M35.11 16.61 C26.78 16.36, 17.69 15.6, 0.65 16.56 M-0.53 16.14 C-1.02 13.67, 0.13 10.1, 0.01 -1.26 M-0.08 15.24 C-0.47 11.49, -0.14 8.29, 0.21 -0.22" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(362.77565540841726 475.0001220703125) rotate(0 17.999984741210938 8.166717529296875)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.13 5.78 C1.53 4.9, 2.28 2.75, 4.8 0.28 M-0.12 6.05 C1.05 4.4, 2.62 3.51, 4.76 -0.03 M-0.89 10.49 C4.26 8.01, 5.93 5.89, 10.97 0.76 M-0.64 12.31 C3.53 8.96, 6.39 5.89, 10.55 -0.1 M2.01 15.09 C4.51 11.05, 11 6.31, 16.72 1.71 M0.25 17.17 C7.07 11.47, 12.05 4.87, 15.67 0.06 M6.4 15.44 C11.69 10.95, 12.56 6.48, 21.17 0.65 M6.14 17.32 C10.53 11.8, 14.38 7.09, 21.5 -0.76 M10.79 17.98 C16.69 10.41, 22.01 4.13, 27.13 1.49 M12.57 17.26 C16.55 11.96, 20.19 6.52, 25.91 -0.18 M15.6 15.73 C20.4 10.42, 26.21 3.09, 32.93 0.08 M17.07 16.25 C20.19 12.51, 23.29 8.05, 32.6 -1.06 M22.84 15.86 C24.69 10.72, 28.53 10.22, 38.45 -0.77 M22.02 17.26 C26.88 11.84, 29.94 7.89, 36.27 0.07 M26.48 18.11 C29.83 13.43, 32.48 11.77, 35.99 6.32 M27.66 16.8 C31.06 13.66, 33.94 9.68, 36.38 7.22 M33.54 16.47 C34.1 14.97, 36 14.35, 36.6 13.37 M32.86 17.02 C33.64 15.82, 34.69 15.2, 36.31 12.95" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M1.52 0.34 C10.63 -0.79, 20.67 -1.22, 34.22 1.89 M0.16 0.65 C11.73 -0.95, 21.58 0.49, 35.66 0.3 M37.08 0.01 C34.83 2.9, 35.57 7.52, 35.83 15.44 M36.25 0.22 C35.7 3.92, 36.42 7.32, 35.85 15.53 M37.76 16.52 C25.89 14.52, 20.53 17.54, 1.03 14.87 M36.93 16.23 C23.05 15.78, 11.13 16.56, -0.63 15.53 M-0.86 17.22 C0.08 11.27, -0.44 8.35, 0.46 -0.3 M-0.12 16.11 C0.51 11.2, 0.56 5.43, 0.09 -0.37" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(400.7754875617376 234.5000762939453) rotate(0 6.666656494140625 7.833343505859375)"><path d="M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M2.06 10.26 C5.31 6.78, 8.64 5.19, 10.59 2.93 M2.71 11.38 C5.48 8.4, 7.43 4.41, 10.28 2.18 M6.17 13.96 C7.68 9.91, 10.82 8.55, 13.32 5.89 M5.16 14.4 C8.07 11.42, 9.47 9.22, 12.13 5.34" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M6.31 -0.48 C8.59 2.69, 10.97 4.43, 13.48 8.61 M6.68 -0.4 C8.45 2.64, 10.4 3.91, 12.91 8.41 M13.74 7.49 C11.58 11.7, 8.61 12.91, 6.26 15.32 M13.03 8.06 C11.03 10.01, 9.71 12.63, 6.65 15.54 M7.24 16.45 C4.73 13.27, 2.62 12, 0.18 8.86 M7.31 15.51 C4.83 13.97, 3.09 11.98, -0.3 8.32 M-0.65 7.72 C1.47 6.08, 3.67 2.98, 7.92 -0.29 M0.12 8.49 C1.92 6.19, 2.76 4.35, 7.33 -0.53" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(415.0751291701623 242.07610870814403) rotate(0 48.48086898253473 1.1317352233634779)"><path d="M-1.49 -0.69 C38.42 0.65, 75.12 1.95, 97.95 1.82 M-0.7 -0.26 C24.1 1, 48.17 1.73, 98.45 2.95" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(415.0751291701623 242.07610870814403) rotate(0 48.48086898253473 1.1317352233634779)"><path d="M68.52 11.8 C81.25 7.68, 90.75 4, 98.71 1.62 M69.31 12.24 C76.9 10.4, 83.85 7.99, 99.21 2.75" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(415.0751291701623 242.07610870814403) rotate(0 48.48086898253473 1.1317352233634779)"><path d="M69.04 -8.71 C81.55 -4.78, 90.85 -0.41, 98.71 1.62 M69.84 -8.28 C77.41 -5.04, 84.22 -2.38, 99.21 2.75" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(517.4421745734563 225.16676330566406) rotate(0 109 18.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.17 6.35 C0.99 4.73, 2.31 3.22, 5.47 0.32 M-0.11 6.64 C1.67 4.12, 3.39 1.75, 4.8 0.59 M-1.08 10.5 C1.87 8.3, 3.23 7.73, 10.78 -0.88 M-0.67 11.76 C2.88 7.66, 5.85 5.43, 9.86 -0.39 M-1.12 17.09 C3.6 10.73, 12.98 7.02, 14.59 -0.43 M0.27 19.15 C4.45 12.42, 10.14 5.75, 15.44 0.15 M1.54 23.89 C6.65 15.42, 16.1 5.94, 20.79 0.44 M-0.34 24.91 C5.36 18.65, 9.85 11.58, 22.07 0.78 M-1.43 29.46 C4.94 24.29, 14.77 16.28, 27.52 -0.78 M0.78 29.63 C9.83 19.11, 21.27 7.05, 25.82 -0.13 M-0.66 36.89 C11.29 22.19, 24.26 8.55, 33.67 -1.75 M0.68 36.13 C10.75 26.06, 21.21 14.16, 31.76 0.68 M4.04 39.96 C13.15 30.52, 22.04 18.2, 38.44 1.85 M2.26 39.11 C12.85 28.55, 20.83 19.15, 36.21 -0.26 M9.84 37.92 C17.7 31.2, 23.8 18.53, 43.35 1.53 M9.32 38.95 C21.4 24.18, 32.34 10.04, 41.56 -0.88 M12.95 41.23 C25.46 27.16, 33.47 14.63, 47.69 1.23 M13.52 38.69 C21.68 28.99, 30.42 19.33, 46.69 0.87 M20.63 38.54 C26.49 31.16, 35.11 19.98, 54.6 -1.41 M19.22 40.01 C32.96 22.96, 46.3 9.05, 53.84 -0.6 M24.69 40.17 C34.93 23.92, 50.16 11.84, 58.48 -1.78 M23.84 40 C35.99 24.57, 50.53 9.87, 58.95 -0.19 M30.82 40.15 C42.7 23.91, 53.26 9.28, 63.07 0.9 M28.15 40.14 C41.71 26.86, 52.25 12.39, 64.55 0.29 M33.4 37.71 C44.07 32.57, 48.38 21.99, 68.89 0.85 M33.89 39.05 C42.49 32.06, 50.02 23.07, 68.18 0.52 M38.28 38.76 C50.54 29.92, 59.86 16.6, 75.28 -0.99 M39.41 39.05 C49.59 27.37, 60.67 16.11, 75.2 0 M44.11 37.92 C51.93 29.69, 59.91 24.19, 79.87 0.25 M45.93 39.29 C53.47 29.47, 63.55 17.43, 79.19 0.44 M49.84 39.76 C62.08 26.35, 75.02 10.14, 84.62 -1.37 M49.88 40.15 C60.73 25.79, 73.01 13.49, 84.85 0.15 M56.72 40.01 C63.06 31.81, 70.9 18.95, 91.27 -1.32 M55.78 39.6 C68.12 24.21, 82.28 8.63, 90.32 0.4 M59.81 38.9 C72.19 28.92, 79.17 18.53, 95.37 0.59 M60.65 39.57 C73.85 24.96, 87.11 7.84, 96.13 -0.18 M65.99 38.3 C80.09 25.34, 90.9 10.48, 101.79 1.52 M66.83 38.31 C79.46 24.2, 93.29 9.04, 101.49 0.72 M73.41 39.07 C81.39 24.98, 93.73 11.78, 106.68 0.82 M72.39 38.83 C79.3 31.5, 85.53 22.51, 107.23 -0.49 M77.57 38.24 C89.22 25.48, 100.73 13.41, 113.02 1.28 M78 39.19 C84.34 31.95, 92.4 22, 112.16 -0.9 M82.73 38.29 C96.03 27.17, 106.27 11.21, 115.91 -0.85 M81.31 38.93 C91.25 28.8, 98.36 20.08, 117.26 -0.05 M87.98 40.39 C100.66 24.08, 113.37 12.98, 121.4 1.6 M87.82 39.42 C100.34 24.95, 112.7 10.5, 121.37 0.73 M94.72 37.67 C104.54 28.32, 116.61 15.27, 125.26 0.28 M93.22 40.26 C102.84 27.62, 114.25 14.23, 126.83 0.99 M96.63 40.45 C109.86 25.82, 122.72 12.85, 134.29 1.24 M98.33 39.64 C105.9 29.16, 114.09 21.39, 131.72 0.2 M103.21 41.5 C112.23 30.39, 119.23 22.05, 137.86 2.27 M103.44 38.7 C115.97 25.67, 129.27 10.27, 138.19 0.22 M109.78 37.25 C120.68 23.82, 132.42 11, 141.89 -1.92 M109.18 39.93 C116.21 30.37, 125.45 20.4, 143.37 -0.43 M112.92 41.14 C123.87 29.04, 132.49 17.12, 148.35 1.59 M114.91 39.53 C126.07 27.04, 137.18 13.96, 147.76 -0.1 M120.57 40.74 C128.55 29.43, 133.36 21.18, 153.27 1.13 M119.56 39.79 C128.22 27.97, 137.84 18.7, 154.05 0.3 M123.43 39.11 C131.83 31.81, 140.34 23.15, 158.25 1.79 M124.08 39.48 C138.88 23.93, 151.84 7.67, 159.55 -0.28 M129.03 39.98 C140.63 25.38, 151.14 14.72, 164.41 -1.47 M130.22 38.18 C137.14 30.45, 144.64 22.8, 165.04 -0.69 M137.2 41.04 C143.29 31.66, 148.56 22.45, 167.96 1.57 M134.99 38.72 C147.46 23.42, 160.81 8.55, 169.14 0.82 M141.41 39.93 C147.42 32.76, 154.07 22.22, 174.13 1.54 M140.83 40.24 C149.9 29.75, 158.9 18.96, 175.19 -1.04 M147.56 39.7 C155.48 30.42, 160.61 19.72, 180.75 -1.23 M145.25 38.85 C153.93 30.56, 161.65 22.1, 179.64 -0.22 M152.78 38.4 C164.81 23.8, 180.16 8.3, 184.15 0.54 M150.57 40.27 C164 24.97, 176.99 11.16, 184.91 -0.95 M154.72 38.97 C164.74 30.2, 173.63 21.71, 190.76 -1.68 M156.02 38.92 C169.12 24.71, 181.17 10.75, 189.76 0.61 M163.13 38.59 C172.67 28.54, 183.78 16.27, 195.04 1.03 M162.23 40.3 C169.35 31, 177.22 21, 196.18 -1.21 M165.77 37.85 C177.54 26.95, 188.19 14.84, 203.02 0.3 M168.01 39.4 C175.15 29.6, 183.43 20.8, 201.75 0.75 M171.98 38.08 C183.64 25.51, 197.14 11.97, 206.27 -0.33 M172.81 39.03 C181.99 29.26, 191.7 17.01, 206.53 -1.14 M178.66 38.49 C187.1 32.77, 191.27 23.25, 213.43 -0.1 M177.52 40.21 C184.05 31.57, 190.61 24.1, 211.42 -0.91 M181.74 41.55 C192.67 27.65, 204.38 13.4, 216.17 0.2 M182.89 40.58 C192.87 27.11, 204.67 13.93, 217.06 -0.64 M190.23 38.14 C193.49 32.89, 200.48 22.72, 218.78 1.72 M188.39 38.71 C199.36 26.16, 212.9 12.58, 220.19 2.22 M193.67 40.85 C200.46 29.79, 209.19 21.12, 222.08 10.56 M192.6 40.53 C199.64 30.8, 207.99 23.98, 220.55 8.9 M200.18 41.19 C203.75 32.3, 210.67 27.96, 222.16 14.74 M200.04 39.69 C208.18 29.96, 214.73 19.23, 220.44 13.44 M203.93 38.9 C206.68 33.2, 211.68 29.1, 221.32 18.74 M203.61 39.9 C210.12 33.02, 217.04 24.47, 220.49 20.4 M210.9 39.15 C212.7 37.64, 215.73 35.35, 220.67 25.82 M209.48 39.34 C213.02 36.01, 215.04 33.21, 221.15 26.18 M215.07 38.77 C215.64 37.12, 217.89 34.81, 220.11 31.9 M214.93 39.37 C216.41 37.9, 217.96 36.08, 220.91 33" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M-0.96 1.01 C58.02 -0.09, 118.22 -2.48, 217.77 -1.07 M-0.61 -0.05 C60.42 -1.23, 118.73 -0.33, 218.64 0.2 M216.46 0.38 C219.48 12.49, 218.98 28.49, 217.8 36.33 M217.13 -0.27 C217.45 10.12, 219.24 19.36, 217.03 37.02 M216.32 37.93 C169.97 35.08, 123.99 36.16, 0.86 36.53 M218.29 37.46 C172.71 35.63, 127.42 35.08, -0.07 37.47 M-1.84 35.23 C-0.11 25.32, 1.02 15.52, 1.38 1.39 M0.24 37.55 C0.73 26.16, 0.26 14.98, -0.26 -0.44" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(535.4421745734563 233.66676330566406) rotate(0 91 10)"><text x="91" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">(current func instance)</text></g><g stroke-linecap="round" transform="translate(401.4421745734563 267.50010681152344) rotate(0 6.33331298828125 8.833328247070312)"><path d="M7.27 -0.31 C7.27 -0.31, 7.27 -0.31, 7.27 -0.31 M7.27 -0.31 C7.27 -0.31, 7.27 -0.31, 7.27 -0.31 M1.9 10.99 C4.27 10.22, 5.06 8.1, 9.68 3.26 M2.32 11.29 C4.68 9.27, 6 7.22, 8.93 3.55 M4.54 15.01 C6.18 12.44, 8.93 9.73, 12.17 7.01 M5.18 15.18 C7 11.86, 10.14 8.86, 11.08 6.8" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M7.53 -0.29 C7.57 2.33, 8.98 5.01, 13.23 9.29 M6.95 0.29 C9.07 3.44, 11.27 5.87, 12.2 9.02 M13.38 9.72 C11.11 11.2, 8.57 14.15, 7.57 18.33 M12.53 8.77 C11.27 12.13, 9.12 14.06, 7.46 17.2 M7.4 17.43 C5.84 15.5, 3.68 13.54, 0.25 8.26 M6.61 17.92 C5.01 15.5, 2.74 13.01, -0.03 8.81 M0.68 8.94 C3.03 5.07, 5.26 3.8, 7.68 -0.2 M-0.27 9.32 C1.67 6.85, 3.89 3.23, 6.45 -0.15" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(532.1088005500188 276.16676330566406) rotate(0 112 26)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.62 6.21 C1.23 4.51, 2.21 3.69, 4.5 1.03 M-0.4 6.72 C1.51 4.54, 2.53 3.43, 4.7 0.16 M0.91 13.06 C1.47 10.74, 5.26 5.29, 11.87 -1.4 M-0.01 11.7 C2.65 9.36, 5.5 4.95, 10.47 -0.03 M0.33 20.22 C2.04 14.54, 7.72 9.7, 17.49 -1.16 M0.76 18.31 C6.43 11.17, 11.23 4.21, 16.26 0.55 M0.31 25.65 C8.92 15.08, 13.07 8.27, 20.25 -0.86 M1.23 23.41 C7.35 15.01, 14.64 6.11, 21.98 -0.66 M-1.36 31.31 C10 22.13, 16.79 11.84, 28.08 -0.02 M-0.38 29.52 C8.76 19.98, 18.18 8.97, 26.03 1.17 M-1.4 37.06 C12.85 22.39, 23.81 9.49, 32.15 -1.67 M0.01 36.06 C8.26 27.41, 16.36 18.54, 32.69 -0.37 M-1.61 43.97 C10.16 30.94, 23.48 16.94, 37.24 2.14 M0.66 43.21 C14.18 26.46, 28.53 10.08, 37.21 0.62 M0.48 49.26 C8.12 38.9, 21.71 25.49, 42.15 0.99 M0.48 49.73 C8.66 38.73, 18.35 27.37, 43.42 0.04 M0.67 52.34 C18.68 36.09, 33.07 17.47, 45.79 0.92 M1.28 53.82 C19.63 31.78, 36.44 12.36, 46.88 -0.62 M6.18 53.53 C25.08 30.99, 42.25 9.9, 51.62 -0.88 M6.89 52.83 C22.31 34.88, 36.82 15.98, 52.47 -0.67 M12.22 53.88 C25.6 36.56, 42.36 17.72, 57.68 -1.24 M12.91 53.81 C24.21 38.91, 35.63 26.01, 57.55 -0.53 M18.52 53.85 C30.43 38.05, 43.29 25.62, 65.08 -0.36 M16.36 53.17 C27.32 42.08, 37.27 30.29, 63.56 -0.19 M21.88 52.56 C34.05 39.18, 48.77 24.49, 67.98 1.01 M23.33 52.79 C33.16 41.41, 41.45 30.8, 69.17 0.5 M26.15 54.59 C36.77 43.1, 50.82 30.64, 74.15 0.3 M28.15 53.64 C38.21 41.18, 48.8 30.39, 73.87 -0.64 M34.77 52.65 C52.32 34.12, 70.66 11.66, 78.9 -0.12 M32.97 53.4 C44.88 40.17, 55.71 26.76, 79.12 -0.38 M36.75 54.44 C57.56 34.86, 74.84 11.4, 85.61 -2.24 M38.91 54.14 C51.66 39.09, 63.14 25.18, 85.98 -0.57 M43.16 53.29 C54.97 40.46, 62.5 32.66, 91.74 -1.56 M43.67 53.84 C59.62 35.22, 76.04 17.38, 90.23 -0.43 M49.15 55 C66.98 32.43, 80.83 13.16, 97.33 -0.46 M48.7 54.14 C59 40.78, 70.59 27.99, 95.96 -0.98 M54.43 52.51 C70.32 31.99, 89.08 15.18, 98.97 -1.34 M54.74 53.86 C72.18 33.58, 90.61 13.45, 100.75 0.63 M61.3 52.73 C78.09 35.03, 94.45 16.2, 106.33 0.04 M59.03 52.69 C78 33.01, 94.56 12.83, 107.27 -1.3 M66.44 51.96 C79.08 36.5, 94.06 19.09, 112.14 1.37 M64.24 53.53 C75.53 42.02, 85.89 29.66, 110.39 0.65 M70.26 54.95 C86.04 35, 99.34 19.87, 116.07 1.27 M70.86 52.38 C82.84 38.82, 94.63 26.7, 116.17 1.35 M74.13 53.89 C95.97 33.48, 113.9 10.72, 121.97 -1.72 M75.65 54.22 C88.64 37.87, 103.53 22.3, 122.27 -0.97 M80.24 51.88 C93.76 35.41, 110.21 21.81, 127.15 1.88 M80.57 53.36 C91.17 40.2, 101.66 28.41, 126.34 1.15 M85.61 53.71 C101.2 37.99, 112.8 22.18, 134.26 -0.03 M85.93 53.12 C102.95 32.1, 120.41 12.95, 132.99 0.75 M90.56 52.6 C110.11 33.28, 124.44 13.43, 137.27 1.65 M91.98 53.38 C102.37 41, 111 31.02, 136.91 0.12 M96.75 52.95 C111.3 39.84, 124.4 23.49, 141.97 -0.09 M96.1 54.25 C114.23 32.6, 132.79 12, 142.53 0.36 M103.66 53.08 C112.84 38.07, 124.75 27.83, 147.97 -1.54 M102.36 53.7 C113.65 38.59, 125.29 26.61, 149.11 1.07 M106.58 51.99 C124.08 37.43, 139.66 18.95, 153.18 -1.58 M106.66 53.17 C119.04 40.46, 129.65 29.38, 154.36 -0.06 M113.12 52.13 C126.98 37.64, 138.1 23.77, 159.85 1.1 M112.4 53.19 C129.16 32.28, 148.04 13.45, 159.61 0.38 M117.23 54.12 C134.08 31.57, 151.65 14.33, 163.07 -1.28 M117.53 53.02 C133.43 35.79, 149.39 16.21, 165.36 -0.85 M123.64 51.48 C138.05 38.17, 151.02 22.43, 168.7 1.21 M124.23 52.25 C138.49 34.01, 155.08 17.37, 168.5 0 M129.94 53.47 C140.61 38.18, 155.6 21.49, 173.97 -1.11 M128.04 52.47 C144.04 36.44, 157.7 18.65, 175.85 -0.77 M135.03 51.71 C149.33 35.19, 162.37 18.79, 181.39 1.3 M133.44 52.85 C146.31 37.74, 159.62 23.36, 179.34 -0.58 M137.12 55.06 C154.32 34.8, 170.08 19.52, 187.32 -0.12 M139 53.79 C154.99 36.55, 169.67 19.24, 185.6 -1.04 M146.25 52.28 C156.02 39.61, 168.37 26.14, 191.93 -1.22 M145.03 52.53 C157 36.59, 170.59 21.92, 191.1 -0.28 M150.27 54.8 C167.14 30.94, 187.03 13.17, 195.71 1.54 M150.64 52.8 C160.83 39.84, 173.43 25.21, 195.79 0.68 M155.36 51.51 C165.18 42.78, 175.68 30.63, 201.46 1.92 M155.44 52.4 C164.52 41.23, 175.33 31.96, 202.2 -0.47 M160.02 51.46 C169.67 43.07, 181.08 27.93, 206.82 -1.43 M160.62 52.87 C170.16 41.7, 180.49 29.12, 207.07 0.31 M167.57 54.62 C177.69 41.26, 186.23 30.59, 210.24 1.86 M166.58 53.1 C176.83 40.38, 187.5 29.59, 212.49 1.04 M172.14 54.68 C184.34 39.92, 197.37 25.66, 219.49 0.56 M170.05 52.95 C188.47 31.61, 208.47 11.16, 217.51 -0.68 M175.19 53.7 C186.16 41.68, 199.04 29.39, 221.65 0.63 M175.75 52.87 C189.37 36.29, 203.08 21.38, 223.27 0 M183.51 52.98 C195.58 34.21, 211.81 20.13, 225.68 2.22 M181.47 53.54 C199.29 32.58, 216.31 12.53, 226.66 1.01 M185.02 52.46 C192.87 43.98, 202.96 36.2, 226.98 7.43 M187.07 54.24 C199.73 39.59, 212.03 25.01, 226.05 8.03 M194.13 53.76 C204.35 38.18, 217.84 26.89, 227.9 14.45 M192.86 52.71 C204.53 39.57, 215.97 25.96, 226.89 13.53 M196.95 55.21 C205.73 41.93, 219.34 28.89, 227.81 21.48 M198.04 53.06 C208.98 41.11, 218.89 27.94, 226.93 19.49 M203.15 51.29 C213.16 42.97, 221.56 31.59, 226.9 25.63 M203.63 54.09 C210.47 44.13, 218.5 33.69, 227.13 25.23 M208 55.43 C211.93 48.63, 218.53 38.26, 228.18 33.68 M207.64 52.99 C212.88 47.27, 218.95 40.01, 226.79 33.04 M212.86 54.64 C217.53 48.07, 220.75 43.07, 225.36 37.67 M212.69 52.89 C216.88 49.05, 219.68 45.52, 226.51 38.59 M218.81 53.01 C220.39 52.26, 221.22 48.44, 227.33 45.1 M218.78 52.89 C221.19 50.66, 222.89 48.55, 226.57 44.58" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M0.95 1.19 C69.16 -1.19, 135.49 -2.77, 224.41 0.94 M0.04 -0.23 C81.09 0.34, 163.54 -0.23, 223.2 0.77 M223.9 0.72 C223.26 11.75, 223.53 21.83, 224.07 52.45 M224.24 -0.69 C224.39 12.11, 224.47 23.82, 224.54 51.94 M224.76 53.03 C164.15 52.03, 102.81 52.12, 0.64 53.03 M223.71 51.6 C161.19 49.89, 98.17 50.1, -0.65 51.17 M1.04 52.18 C-0.67 37.67, -0.07 24.03, -2 -0.7 M0.71 51.04 C0.06 39.49, 0.57 26.02, -0.5 -0.68" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(550.1088005500188 281.16676330566406) rotate(0 94 20)"><text x="94" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr"> (next bytecode in code</text><text x="94" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">for return)</text></g><g stroke-linecap="round"><g transform="translate(412.1088005500188 275.8334197998047) rotate(0 59.62893088121098 9.604696595875765)"><path d="M0.7 1.43 C43.96 8.29, 91.15 13.39, 118.66 18.28 M0.6 0.21 C27.67 5.29, 56.63 8.54, 118.63 18.99" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(412.1088005500188 275.8334197998047) rotate(0 59.62893088121098 9.604696595875765)"><path d="M89.87 26.06 C99.49 23.41, 112.92 19.34, 118.6 18.67 M89.76 24.85 C95.54 23.97, 103.17 21.43, 118.57 19.38" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(412.1088005500188 275.8334197998047) rotate(0 59.62893088121098 9.604696595875765)"><path d="M93.14 5.8 C101.42 10.8, 113.61 14.4, 118.6 18.67 M93.04 4.59 C97.99 8.55, 104.84 10.85, 118.57 19.38" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(684.1088615851751 506.00001525878906) rotate(0 0.1666259765625 0.1666717529296875)"><path d="M0.08 0 M0.08 0 C0.12 -0.01, 0.17 0, 0.25 0 M0.08 0 C0.13 0, 0.18 0.01, 0.25 0 M0.25 0 C-0.69 0.18, 2.05 0.73, 0.33 0.08 M0.25 0 C-0.64 -0.49, -0.48 -0.87, 0.33 0.08 M0.33 0.08 C0.33 0.12, 0.33 0.19, 0.33 0.25 M0.33 0.08 C0.34 0.14, 0.34 0.2, 0.33 0.25 M0.33 0.25 C-0.54 -1.61, 1.28 -0.68, 0.25 0.33 M0.33 0.25 C1.51 0.69, 0.47 -0.62, 0.25 0.33 M0.25 0.33 C0.22 0.32, 0.17 0.32, 0.08 0.33 M0.25 0.33 C0.19 0.33, 0.14 0.34, 0.08 0.33 M0.08 0.33 C-0.07 1.61, 0.64 1.66, 0 0.25 M0.08 0.33 C-1.57 0.65, 1.66 1.26, 0 0.25 M0 0.25 C0.01 0.21, 0.02 0.18, 0 0.08 M0 0.25 C0.01 0.2, 0 0.13, 0 0.08 M0 0.08 C-2 1.75, -1.64 0.12, 0.08 0 M0 0.08 C0.5 1.29, -1.69 -1.84, 0.08 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(111.10884632638601 546.6667938232422) rotate(0 178.66665649414062 15.166763305664062)"><path d="M0.28 -1.04 C113.29 -3.14, 228.85 -2.77, 357.45 1.1 M-0.23 -0.25 C119.69 0.19, 239.49 0.55, 356.97 0.02 M358.97 1.96 C357.68 13.1, 355.99 22.62, 355.42 31.3 M357.4 -0.42 C356.62 7.08, 357.82 15.48, 356.49 29.8 M356.99 30.42 C282.13 30.34, 208.71 29.69, 0.81 30.74 M357.79 30.6 C225.77 30.62, 95 31.03, 0.25 30.91 M-0.76 31.86 C1.77 19.12, -1.02 4.24, 1.72 -1.66 M-0.74 29.53 C-0.71 21.76, 0.65 12.73, 0.79 -0.68" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(485.6038355580406 321.63158298054134) rotate(0 29.15222727310197 115.55551553333692)"><path d="M-1.01 -0.64 C9.44 21.5, 63.91 94.75, 63.07 133.29 C62.24 171.83, 5.45 214.44, -6 230.6 M0.66 1.64 C11.43 23.39, 66.48 93.12, 65.21 131.48 C63.95 169.83, 4.83 215.15, -6.93 231.75" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(485.6038355580406 321.63158298054134) rotate(0 29.15222727310197 115.55551553333692)"><path d="M3.9 202.38 C2.09 212.78, -3.4 222.61, -7.98 232.68 M5.29 204.89 C0.28 213.64, -2.28 223.12, -7.29 231.71" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(485.6038355580406 321.63158298054134) rotate(0 29.15222727310197 115.55551553333692)"><path d="M18.82 216.47 C11.98 222.05, 1.52 227.18, -7.98 232.68 M20.21 218.98 C10.22 223.11, 2.67 227.89, -7.29 231.71" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(121.1973232608965 314.8304810956254) rotate(0 -43.58656128135101 121.37813472895851)"><path d="M-1.18 -0.11 C-15.73 21.29, -85.2 86.82, -86.87 127.34 C-88.54 167.86, -23.86 223.6, -11.18 243.01 M0.4 -1.22 C-14.3 20.47, -85.43 87.93, -87.53 128.8 C-89.62 169.66, -24.97 224.62, -12.15 243.98" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(121.1973232608965 314.8304810956254) rotate(0 -43.58656128135101 121.37813472895851)"><path d="M-38.58 230.35 C-29.9 233.99, -21.87 239.49, -11.97 242.12 M-37.46 229.32 C-28.08 234.58, -20.19 240.08, -12.27 244.39" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(121.1973232608965 314.8304810956254) rotate(0 -43.58656128135101 121.37813472895851)"><path d="M-23.09 216.89 C-19.78 224.93, -16.98 234.98, -11.97 242.12 M-21.97 215.86 C-18.07 225.97, -15.72 236.28, -12.27 244.39" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(111.77553333810476 549.0000152587891) rotate(0 103.6666259765625 12.666671752929688)"><path d="M1.69 1.47 C1.69 1.47, 1.69 1.47, 1.69 1.47 M1.69 1.47 C1.69 1.47, 1.69 1.47, 1.69 1.47 M3.39 5.6 C4.22 3.95, 6.2 2.9, 7.33 1.07 M3.39 5.6 C4.35 4.59, 5.6 3.28, 7.33 1.07 M3.13 12 C7.43 8.58, 10.46 4.14, 12.97 0.68 M3.13 12 C5.57 9.53, 8.85 5.42, 12.97 0.68 M1.56 19.9 C6.13 16.39, 10.89 8.05, 17.96 1.04 M1.56 19.9 C6.52 14.24, 10.88 8.65, 17.96 1.04 M2.61 24.79 C8.84 16.06, 15.32 9.7, 23.6 0.64 M2.61 24.79 C10.27 15.29, 18.59 6.14, 23.6 0.64 M6.94 25.91 C10.05 18.63, 16.22 12.82, 28.59 1 M6.94 25.91 C15.35 16.79, 22.89 8.33, 28.59 1 M12.58 25.51 C20.07 16.67, 25.17 12.21, 34.23 0.61 M12.58 25.51 C18.78 17.69, 25.27 10.34, 34.23 0.61 M17.57 25.87 C24.14 18.5, 31.44 12.81, 39.22 0.97 M17.57 25.87 C25.89 15.73, 35.51 5.98, 39.22 0.97 M22.56 26.23 C29.31 20.54, 34.75 13.02, 44.21 1.33 M22.56 26.23 C29.01 20.48, 33.16 12.82, 44.21 1.33 M28.2 25.84 C38.87 15.46, 45.85 7.47, 49.85 0.93 M28.2 25.84 C34.37 20.57, 38.83 14.23, 49.85 0.93 M33.19 26.2 C41.94 17.44, 47.47 6.39, 54.84 1.29 M33.19 26.2 C38.12 21.07, 43.97 13.14, 54.84 1.29 M38.83 25.8 C47.09 18.35, 55.46 9.7, 60.48 0.9 M38.83 25.8 C46.42 18.49, 51.85 10.12, 60.48 0.9 M43.82 26.16 C49.32 18.07, 56.84 12.49, 65.47 1.26 M43.82 26.16 C48.06 19.89, 53.19 14.86, 65.47 1.26 M49.46 25.77 C56.47 17.9, 63.36 9.26, 71.11 0.86 M49.46 25.77 C54.94 18.42, 61.87 11.83, 71.11 0.86 M54.45 26.13 C60.74 17.55, 70.12 10.13, 76.1 1.22 M54.45 26.13 C60.78 17.9, 67.67 10.25, 76.1 1.22 M60.09 25.73 C66.25 21.01, 69.95 14.5, 81.74 0.83 M60.09 25.73 C66.71 19.43, 70.8 11.67, 81.74 0.83 M65.08 26.09 C74.2 17.04, 79.29 9.82, 86.73 1.19 M65.08 26.09 C71.96 17.44, 78.56 9.61, 86.73 1.19 M70.72 25.7 C75.65 19.18, 83.53 10.33, 92.37 0.79 M70.72 25.7 C78.57 16.75, 86.96 5.49, 92.37 0.79 M75.71 26.06 C82.81 16.37, 90.61 8.96, 97.36 1.15 M75.71 26.06 C81.96 19.82, 87.35 13.43, 97.36 1.15 M81.35 25.67 C85.65 20.17, 91.56 13.33, 103 0.76 M81.35 25.67 C86.13 19.48, 90.52 15.94, 103 0.76 M86.34 26.03 C93.55 17.17, 100.83 10.43, 107.99 1.12 M86.34 26.03 C92.49 17.36, 100.16 9.88, 107.99 1.12 M91.98 25.63 C96.54 19.39, 101.07 14.72, 113.63 0.73 M91.98 25.63 C99.2 15.97, 107.84 7.41, 113.63 0.73 M96.97 25.99 C101.5 18.47, 110.01 14.7, 118.62 1.09 M96.97 25.99 C104.95 18.74, 111.45 9.64, 118.62 1.09 M102.61 25.6 C110.01 15.4, 118.57 10.31, 124.26 0.69 M102.61 25.6 C106.83 19.86, 112.65 13.41, 124.26 0.69 M107.6 25.96 C114.43 16.54, 123.9 6.23, 129.25 1.05 M107.6 25.96 C115.47 17.92, 121.99 8.41, 129.25 1.05 M113.24 25.56 C119.25 16.57, 128.98 8.63, 134.89 0.66 M113.24 25.56 C121.35 17.12, 127.88 8.33, 134.89 0.66 M118.23 25.92 C123.43 17.4, 129.35 11.32, 139.88 1.02 M118.23 25.92 C122.82 19.1, 127.89 14.23, 139.88 1.02 M123.87 25.53 C131 18.24, 137.53 8.64, 145.52 0.62 M123.87 25.53 C130.42 17.51, 138.65 10.15, 145.52 0.62 M128.86 25.89 C133.73 20.51, 141.41 13.51, 150.51 0.98 M128.86 25.89 C133.36 20.07, 138.72 15.49, 150.51 0.98 M133.84 26.25 C139.37 20.27, 144.21 11.58, 156.15 0.59 M133.84 26.25 C142.59 16.11, 150.12 7.43, 156.15 0.59 M139.49 25.85 C146.06 17.12, 153.07 6.28, 161.14 0.95 M139.49 25.85 C146.57 18.85, 153.9 8.94, 161.14 0.95 M144.47 26.21 C147.95 21.38, 152.26 14.79, 166.12 1.31 M144.47 26.21 C149.93 20.66, 153.49 14.36, 166.12 1.31 M150.12 25.82 C158.13 18.12, 166.7 7.43, 171.77 0.91 M150.12 25.82 C157.04 16.68, 164.82 10.23, 171.77 0.91 M155.1 26.18 C161.09 19.95, 166.24 15.03, 176.75 1.27 M155.1 26.18 C161.59 19.11, 167.76 12.15, 176.75 1.27 M160.75 25.78 C168.15 17.93, 176.58 9.51, 182.4 0.88 M160.75 25.78 C165.64 21.25, 170.54 15.65, 182.4 0.88 M165.73 26.14 C170.64 20.7, 179.32 10.61, 187.38 1.24 M165.73 26.14 C174.13 16.36, 181.53 6.99, 187.38 1.24 M171.38 25.75 C177.82 18.2, 184.88 12.99, 193.03 0.84 M171.38 25.75 C178.84 17.25, 185.58 9.2, 193.03 0.84 M176.36 26.11 C185.15 18.18, 193.41 9.44, 198.01 1.2 M176.36 26.11 C184.94 18.06, 192.75 8.94, 198.01 1.2 M182.01 25.72 C186.6 18.07, 194.82 11.25, 203 1.56 M182.01 25.72 C186.1 20.85, 191.03 15.64, 203 1.56 M186.99 26.08 C193.57 22.13, 195.97 14.39, 207.33 2.68 M186.99 26.08 C194 17.91, 199.97 9.59, 207.33 2.68 M192.64 25.68 C200.63 20.49, 203.69 11.22, 209.7 6.06 M192.64 25.68 C196.59 21.03, 199.75 15.84, 209.7 6.06 M197.62 26.04 C200.55 23.21, 205.72 19.65, 210.09 11.7 M197.62 26.04 C200.87 21.83, 204.65 17.88, 210.09 11.7 M202.61 26.4 C204.11 25.23, 204.55 24.02, 208.52 19.61 M202.61 26.4 C203.74 25.06, 205.9 23.06, 208.52 19.61" stroke="#868e96" stroke-width="0.5" fill="none"></path><path d="M6.33 0 M6.33 0 C47.95 -3.03, 87.49 -2.28, 201 0 M6.33 0 C56.65 -0.1, 105.86 0.22, 201 0 M201 0 C204.35 1.66, 208.71 0.8, 207.33 6.33 M201 0 C206.31 0.69, 207.43 3.94, 207.33 6.33 M207.33 6.33 C207.14 10.89, 208.12 12.88, 207.33 19 M207.33 6.33 C207.29 8.37, 207.42 11.89, 207.33 19 M207.33 19 C205.53 21.35, 206.1 24.05, 201 25.33 M207.33 19 C207.57 23.77, 205.02 23.89, 201 25.33 M201 25.33 C125.8 24.12, 50.17 25.28, 6.33 25.33 M201 25.33 C141.34 27.24, 80.09 25.84, 6.33 25.33 M6.33 25.33 C2.95 26.5, 0.26 22.15, 0 19 M6.33 25.33 C-0.17 26.05, -1.18 23.1, 0 19 M0 19 C0.95 14.31, 0.56 11.24, 0 6.33 M0 19 C0.46 15.15, -0.24 12.45, 0 6.33 M0 6.33 C-1.68 2.04, 2.76 -1.11, 6.33 0 M0 6.33 C1.55 -0.13, 2.42 0.68, 6.33 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(376.33720829260255 563.0806543384268) rotate(0 23.380680531078212 -0.8521640938315045)"><path d="M0.33 0.67 C8.35 0.43, 40.15 -0.27, 47.72 -0.42 M-0.96 -0.03 C7.02 -0.12, 39.09 -1.98, 47.27 -2.37" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(376.33720829260255 563.0806543384268) rotate(0 23.380680531078212 -0.8521640938315045)"><path d="M47.06 -3.14 L34.56 5.07 L34.94 -8.42 L48.54 -3.13" stroke="none" stroke-width="0" fill="#000000" fill-rule="evenodd"></path><path d="M48.11 -1.19 C44.22 -1.73, 40.89 2.2, 33.93 5.32 M47.08 -1.77 C44 -0.89, 39.71 0.96, 33.32 4.71 M34.02 4.92 C33.74 0.14, 33.48 -5.2, 33.4 -7.39 M33.86 4.15 C34.36 0.13, 33.55 -5.79, 33.26 -8.42 M33.52 -9.48 C36.55 -7.3, 42.06 -5.44, 48.17 -3.62 M33.49 -7.85 C36.5 -7.02, 40.29 -5.09, 46.82 -2.55 M47.27 -2.37 C47.27 -2.37, 47.27 -2.37, 47.27 -2.37 M47.27 -2.37 C47.27 -2.37, 47.27 -2.37, 47.27 -2.37" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(305.7754417853704 300.83335876464844) rotate(0 87 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">opnd_stack_boundary</text></g><g stroke-linecap="round" transform="translate(305.44212879708914 296.0000305175781) rotate(0 92.16668701171875 15.166664123535156)"><path d="M-0.55 0.06 C57.18 -1.04, 115.16 0.36, 183.02 1.48 M-0.3 0.16 C70.18 1.82, 138.85 1.2, 185.15 -0.93 M183.44 -1.42 C184.41 11.56, 185.92 20.6, 183.21 31.1 M184.86 -0.69 C184.32 6.55, 183.98 14.7, 184.14 31.24 M183.85 31 C135.29 29.09, 90.57 32.47, -1.06 31.59 M184.94 30.76 C141.45 30.35, 97.05 29.95, -0.7 30.56 M1.93 31.12 C-1.69 19.74, -0.47 12.94, -1.07 0.32 M0.09 31.03 C0.9 23.18, -0.3 15.12, 0.4 0.17" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(463.7754417853704 346.6667022705078) rotate(0 -62.78338652698665 105.96028334652118)"><path d="M-1 0.86 C-0.86 25.23, 24.19 110.37, 1.32 145.35 C-21.55 180.33, -115.02 199.82, -138.22 210.74 M0.68 0.26 C1.14 24.33, 26.75 108.18, 3.5 143.42 C-19.74 178.65, -115.35 200.29, -138.81 211.66" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(463.7754417853704 346.6667022705078) rotate(0 -62.78338652698665 105.96028334652118)"><path d="M-114.28 190.84 C-123.09 199.38, -132.77 206.44, -139.87 212.33 M-114.83 192.65 C-125.2 199.92, -131.83 207.38, -139.47 212.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(463.7754417853704 346.6667022705078) rotate(0 -62.78338652698665 105.96028334652118)"><path d="M-107.39 210.17 C-118.39 212.1, -130.41 212.61, -139.87 212.33 M-107.93 211.97 C-120.69 212.25, -129.84 212.65, -139.47 212.01" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(451.10875477365164 338.33335876464844) rotate(0 7.5 7.5)"><path d="M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M3.33 10.84 C4.88 9.18, 6.99 5.86, 10.54 2.54 M3.33 10.84 C5.14 8.72, 6.41 7.05, 10.54 2.54 M6.35 13.47 C7.77 10.41, 10.93 8.21, 12.91 5.92 M6.35 13.47 C8.17 11.04, 10.56 8.42, 12.91 5.92" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M10 2 M10 2 C10.6 3.11, 11.08 4.02, 13 6 M10 2 C11.02 3, 11.92 4.2, 13 6 M13 6 C15.14 6.79, 16.42 9.21, 13 10 M13 6 C13.61 8.85, 14.19 5.8, 13 10 M13 10 C12.44 11.02, 11.25 11.48, 10 13 M13 10 C11.87 10.8, 11.26 11.8, 10 13 M10 13 C6.3 16.29, 6.67 15.7, 6 13 M10 13 C9.55 15.12, 8.33 14.2, 6 13 M6 13 C5.46 11.78, 3.78 11.82, 2 10 M6 13 C5.1 12.54, 4.4 11.79, 2 10 M2 10 C1.47 8.31, 0.17 7.11, 2 6 M2 10 C1.32 7.7, -1.84 6.73, 2 6 M2 6 C3.47 4.49, 4.59 2.95, 6 2 M2 6 C3.71 4.8, 4.79 3.35, 6 2 M6 2 C7.68 -0.77, 6.14 1.9, 10 2 M6 2 C7.54 1.27, 9.52 -2, 10 2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(314.10875477365164 373.00001525878906) rotate(0 88 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">label_stack_boundary</text></g><g stroke-linecap="round" transform="translate(311.7754417853704 367.0000457763672) rotate(0 90.5 14.833328247070312)"><path d="M-2 -1.9 C60.92 -0.37, 125.49 2.23, 182.49 0.76 M0.05 0.5 C70.78 1.3, 143.94 1, 180.5 0.62 M181.95 1.2 C180.09 9.27, 181.8 20.47, 181.81 28.15 M181.64 0.98 C179.92 7.05, 180.83 12.31, 180.39 28.97 M181.9 28.81 C120.84 31.45, 61.66 30.91, -1.64 28.53 M181.18 29.61 C117.42 31.09, 53.54 31.66, -0.91 28.76 M0.12 29.52 C0.52 20.67, 0.94 11.25, 1.32 -1.28 M0.7 28.85 C-0.68 18.15, -0.65 6.84, -0.97 0.7" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(114.10880055001883 591.3334503173828) rotate(0 178.33331298828125 15.666702270507812)"><path d="M0.65 -0.08 C112.13 1.13, 223.36 0.7, 355.46 0.95 M-0.2 0.38 C106.39 -0.94, 213.14 -1.07, 356.28 -0.14 M358.52 0.39 C356.12 14.38, 356.58 24.44, 358.52 31.21 M357.32 0.84 C357.47 8.1, 356.09 15.45, 356.61 30.36 M356.64 32.35 C241.29 31.58, 127.39 32.99, -0.36 30.74 M356.92 31.67 C228.56 30.96, 100.86 30.65, 0.12 31.91 M0.49 32.03 C-1.86 21.26, 1.24 14.08, 0.88 -0.69 M0.03 32.1 C0.57 24.14, 0.13 15.29, 0.74 -0.61" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(117.44208302072195 591.0001373291016) rotate(0 125.16664123535156 13.333282470703125)"><path d="M1.77 1.54 C1.77 1.54, 1.77 1.54, 1.77 1.54 M1.77 1.54 C1.77 1.54, 1.77 1.54, 1.77 1.54 M2.83 6.43 C4.44 4.61, 5.73 2.46, 7.42 1.15 M2.83 6.43 C4.94 4.41, 6.31 2.59, 7.42 1.15 M3.22 12.07 C5.96 8.04, 8.44 5.32, 13.06 0.75 M3.22 12.07 C6.86 7.48, 10.04 3.66, 13.06 0.75 M0.99 20.74 C5.16 16.78, 9.46 11.72, 18.05 1.11 M0.99 20.74 C5.01 15.21, 10.19 10.12, 18.05 1.11 M2.04 25.62 C8.62 17.29, 16.6 8.94, 23.69 0.72 M2.04 25.62 C9.66 17.97, 15.86 10.14, 23.69 0.72 M6.37 26.74 C11.52 21.76, 15.77 14.37, 28.68 1.08 M6.37 26.74 C15.84 17.69, 24.6 7.38, 28.68 1.08 M9.39 29.36 C15.38 22, 23.64 9.18, 34.32 0.68 M9.39 29.36 C16.99 22, 22.81 13.2, 34.32 0.68 M15.03 28.97 C23.42 20.56, 32.71 8.59, 39.31 1.04 M15.03 28.97 C21.96 20.41, 30.83 11.45, 39.31 1.04 M20.02 29.33 C30.3 17.97, 39.88 6.04, 44.95 0.65 M20.02 29.33 C27.6 19.55, 35.57 10.75, 44.95 0.65 M25.66 28.93 C33.19 20.26, 41.96 7.49, 49.94 1.01 M25.66 28.93 C31.16 22.13, 39.03 14.79, 49.94 1.01 M30.65 29.29 C40.77 19.63, 49.74 8.06, 55.58 0.62 M30.65 29.29 C36 23.04, 42.04 17.15, 55.58 0.62 M36.29 28.9 C44.82 19.09, 48.82 14.66, 60.57 0.98 M36.29 28.9 C42.95 21.46, 49.17 13.71, 60.57 0.98 M41.28 29.26 C48.81 19.59, 57.83 11.94, 66.21 0.58 M41.28 29.26 C49.31 20.55, 56.66 10.45, 66.21 0.58 M46.92 28.87 C53.32 21.45, 58.43 18.82, 71.2 0.94 M46.92 28.87 C54.8 20.18, 62.89 12.68, 71.2 0.94 M51.91 29.23 C63.16 17.59, 72.5 7.61, 76.84 0.55 M51.91 29.23 C59.84 20.5, 67.73 13.06, 76.84 0.55 M57.55 28.83 C61.94 21.26, 70.95 15.36, 81.83 0.91 M57.55 28.83 C62.79 23.08, 67.24 16.61, 81.83 0.91 M62.54 29.19 C67.14 21.64, 75.32 13.09, 87.47 0.51 M62.54 29.19 C72.24 19.09, 78.89 9.98, 87.47 0.51 M67.53 29.55 C74.14 21.36, 83.36 8.41, 92.46 0.87 M67.53 29.55 C75.56 19.73, 83.13 10.32, 92.46 0.87 M73.17 29.16 C81 18.93, 88.53 10.75, 97.45 1.23 M73.17 29.16 C82.97 19.63, 91.94 8.21, 97.45 1.23 M78.16 29.52 C85.46 22.21, 90 15.29, 103.09 0.84 M78.16 29.52 C85.06 22.48, 90.33 14.37, 103.09 0.84 M83.8 29.12 C89.62 24.77, 93.38 15.73, 108.08 1.2 M83.8 29.12 C89.49 22.51, 96.56 14.88, 108.08 1.2 M88.79 29.48 C96.95 18.85, 106.44 10.25, 113.72 0.8 M88.79 29.48 C94.56 21.23, 102.6 13.75, 113.72 0.8 M94.43 29.09 C100.88 22.06, 109.15 12.8, 118.71 1.16 M94.43 29.09 C103.39 18.71, 114.07 6.55, 118.71 1.16 M99.42 29.45 C109.53 20.17, 116.82 10.25, 124.35 0.77 M99.42 29.45 C107.91 19.08, 118.01 8.01, 124.35 0.77 M105.06 29.05 C108.46 22.81, 115.23 16.56, 129.34 1.13 M105.06 29.05 C112.42 19.23, 120.83 11.86, 129.34 1.13 M110.05 29.41 C115.99 19.92, 122.45 15.46, 134.98 0.73 M110.05 29.41 C120.24 18.81, 128.21 6.64, 134.98 0.73 M115.69 29.02 C121.46 22.6, 129.92 14.69, 139.97 1.09 M115.69 29.02 C122.58 20.78, 128.54 13.6, 139.97 1.09 M120.68 29.38 C127.48 20.55, 130.78 14.25, 145.61 0.7 M120.68 29.38 C128.42 20.97, 134.41 14.63, 145.61 0.7 M126.32 28.98 C131.41 19.3, 140.95 12.5, 150.6 1.06 M126.32 28.98 C132.7 22.12, 138.95 14.16, 150.6 1.06 M131.31 29.34 C138.02 19.1, 144.45 13.69, 156.24 0.67 M131.31 29.34 C137.46 22.86, 144.26 14.49, 156.24 0.67 M136.95 28.95 C143.29 24.06, 146.41 14.84, 161.23 1.03 M136.95 28.95 C145.52 18.93, 156.23 6.06, 161.23 1.03 M141.94 29.31 C150.58 20.33, 156.85 11.48, 166.87 0.63 M141.94 29.31 C148.12 22.01, 153 16.2, 166.87 0.63 M147.58 28.91 C154.28 23.5, 158.99 15.04, 171.86 0.99 M147.58 28.91 C156.63 18.6, 165.78 8.63, 171.86 0.99 M152.57 29.28 C159.83 21.08, 167.39 14.07, 177.5 0.6 M152.57 29.28 C161.57 18.18, 170.58 6.72, 177.5 0.6 M158.21 28.88 C166.37 20.21, 171.42 11.83, 182.49 0.96 M158.21 28.88 C166.15 18.68, 173.72 9.45, 182.49 0.96 M163.2 29.24 C167.12 24.9, 175.96 17.56, 188.13 0.56 M163.2 29.24 C171.76 17.14, 182.6 5.95, 188.13 0.56 M168.84 28.85 C177.46 19.76, 181.89 13.51, 193.12 0.92 M168.84 28.85 C175 22.36, 180.25 15.24, 193.12 0.92 M173.83 29.21 C180.93 19.46, 187.85 10.77, 198.76 0.53 M173.83 29.21 C179.33 23.84, 183.64 17.8, 198.76 0.53 M179.47 28.81 C186.6 20.67, 189.78 17.17, 203.75 0.89 M179.47 28.81 C186.33 19.14, 195.13 10.68, 203.75 0.89 M184.46 29.17 C193.13 18.83, 200.59 9.66, 209.39 0.49 M184.46 29.17 C191.52 20.6, 198.66 13.76, 209.39 0.49 M189.45 29.53 C196.87 17.74, 206.07 7.34, 214.38 0.85 M189.45 29.53 C193.88 24.39, 200.35 18.88, 214.38 0.85 M195.09 29.14 C201.92 18.98, 212.1 8.95, 219.36 1.21 M195.09 29.14 C202.8 21.81, 209.05 13.09, 219.36 1.21 M200.08 29.5 C207.99 23.17, 214.16 13.02, 225.01 0.82 M200.08 29.5 C210.16 18.1, 218.35 8.75, 225.01 0.82 M205.72 29.1 C212.91 20.25, 218.24 13.82, 229.99 1.18 M205.72 29.1 C212.7 20.79, 220.6 13.32, 229.99 1.18 M210.71 29.46 C216.16 24.58, 223.85 17.87, 235.64 0.78 M210.71 29.46 C218.28 20.42, 225.97 11.22, 235.64 0.78 M216.35 29.07 C224.87 22.5, 229.53 14.59, 240.62 1.14 M216.35 29.07 C222.98 19.45, 232.1 11.8, 240.62 1.14 M221.34 29.43 C231.16 18.41, 241.19 8.4, 245.61 1.5 M221.34 29.43 C229.77 19.19, 240.55 7.66, 245.61 1.5 M226.98 29.03 C232.7 23.08, 242.13 14.3, 249.29 3.37 M226.98 29.03 C234.78 19.88, 243.96 10.06, 249.29 3.37 M231.97 29.39 C239.33 22, 247.59 10.96, 252.3 6 M231.97 29.39 C238.34 22.14, 246.11 13.15, 252.3 6 M237.61 29 C239.08 23.91, 244.75 20.14, 252.7 11.64 M237.61 29 C242.12 23.32, 246.22 18.67, 252.7 11.64 M244.56 27.1 C246.63 24.8, 248.86 22.07, 250.47 20.3 M244.56 27.1 C245.34 25.83, 246.62 24.28, 250.47 20.3" stroke="#868e96" stroke-width="0.5" fill="none"></path><path d="M6.67 0 M6.67 0 C72.37 0.56, 134.79 1.19, 243.67 0 M6.67 0 C59.92 1.29, 112.25 1.55, 243.67 0 M243.67 0 C248.74 -0.33, 249.18 1.85, 250.33 6.67 M243.67 0 C248.48 -1.84, 251.77 0.04, 250.33 6.67 M250.33 6.67 C250.82 10.8, 250.21 13.93, 250.33 20 M250.33 6.67 C250.01 10.95, 250.01 14.45, 250.33 20 M250.33 20 C250.94 23.15, 246.6 26.74, 243.67 26.67 M250.33 20 C248.06 25.32, 246.65 27.92, 243.67 26.67 M243.67 26.67 C192.46 25.25, 140.44 24.27, 6.67 26.67 M243.67 26.67 C162.22 28.75, 82.18 28.68, 6.67 26.67 M6.67 26.67 C2.2 26.55, 0.11 23.54, 0 20 M6.67 26.67 C4.49 24.7, -2.06 23.49, 0 20 M0 20 C-1.15 16.59, 1.04 14.13, 0 6.67 M0 20 C0.56 16.13, 0.1 12.4, 0 6.67 M0 6.67 C-0.79 0.44, 2.69 -1.32, 6.67 0 M0 6.67 C-0.97 3.37, 3.25 1.66, 6.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(171.10870899728445 596.0003204345703) rotate(0 54 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">&lt;lable stack&gt;</text></g><g stroke-linecap="round" transform="translate(113.10875477365164 307.0000305175781) rotate(0 6.833343505859375 4.5)"><path d="M-0.15 5.17 C-0.15 5.17, -0.15 5.17, -0.15 5.17 M-0.15 5.17 C-0.15 5.17, -0.15 5.17, -0.15 5.17 M4.29 6.35 C4.57 5.89, 5.99 5.22, 8.5 0.82 M3.92 6.85 C5.6 5.06, 6.77 3.09, 8.92 0.85 M6.94 9.19 C8.15 7.45, 9.59 5.65, 11.35 3.44 M7.47 9.07 C8.88 7.31, 10.24 5.2, 11.66 3.49" stroke="#12b886" stroke-width="0.5" fill="none"></path><path d="M7.77 -0.39 C9.78 2.14, 11.26 3.68, 14.38 4.98 M6.82 -0.07 C9.26 1.13, 11.15 2.65, 13.77 4.93 M13.46 4.88 C11.59 6.59, 10.06 6.52, 7.24 8.51 M13.86 5.22 C11.9 5.69, 10.52 7.04, 7.05 8.92 M7.47 8.35 C6.1 7.58, 4.61 7.38, -0.14 5.45 M7.1 9.26 C5.16 7.86, 3.8 7.48, -0.38 5.03 M0.34 5.02 C3.1 3.67, 3.8 1.57, 6.35 -0.05 M-0.06 5.26 C2.35 3.04, 4.2 1.54, 6.97 0.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(472.60878529122976 318.16668701171875) rotate(0 6.833343505859375 4.5)"><path d="M-0.15 5.17 C-0.15 5.17, -0.15 5.17, -0.15 5.17 M-0.15 5.17 C-0.15 5.17, -0.15 5.17, -0.15 5.17 M4 6.75 C5.22 5, 6.41 3.52, 8.65 0.49 M3.75 7.34 C5.14 5.65, 6.5 3.89, 8.39 0.85 M7.3 9.31 C8.89 7.6, 9.87 5.54, 11.6 3.53 M7.26 9.04 C9.03 7.08, 10.33 5.16, 11.8 3.57" stroke="#12b886" stroke-width="0.5" fill="none"></path><path d="M7.75 -0.23 C8.73 0.92, 11.4 2.35, 13.26 5.26 M6.79 0.21 C8.78 0.79, 9.96 2.05, 14.02 5.05 M13.93 5.46 C11.16 6.81, 9.41 8.02, 7.17 8.86 M13.7 5.1 C11.52 6.36, 8.72 8.09, 7.38 8.63 M6.44 9.32 C4.86 8.49, 2.89 5.84, -0.3 4.39 M6.92 8.94 C5.17 8.03, 2.48 6.55, -0.35 4.98 M-0.27 5.79 C2.5 3.8, 5.44 0.84, 7.45 0.24 M0.37 5.31 C2.17 4.08, 3.91 2.34, 7.42 -0.14" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(117.77544178537039 384.3333282470703) rotate(0 -47.40232942563995 113.54590398524448)"><path d="M1.17 0.29 C-14.9 20.04, -94.36 80.87, -95.95 118.56 C-97.53 156.24, -23.12 208.35, -8.34 226.41 M0.32 -0.6 C-15.42 19.31, -92.69 81.81, -93.73 119.86 C-94.78 157.91, -20.38 209.63, -5.92 227.69" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(117.77544178537039 384.3333282470703) rotate(0 -47.40232942563995 113.54590398524448)"><path d="M-32.99 214.25 C-24.85 218.09, -14.85 223.83, -5.19 227.32 M-34.46 215.54 C-26.42 219.02, -17.05 223.08, -5.84 227.39" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(117.77544178537039 384.3333282470703) rotate(0 -47.40232942563995 113.54590398524448)"><path d="M-18.92 199.31 C-15.55 208.37, -10.34 219.18, -5.19 227.32 M-20.38 200.6 C-16.26 208.41, -10.91 216.72, -5.84 227.39" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(477.7754417853704 386.99998474121094) rotate(0 24.668359239004417 108.56823457765549)"><path d="M1.17 0.68 C9.98 26.35, 53.27 118.4, 52.58 154.23 C51.89 190.06, 6.33 205.67, -2.98 215.66 M0.32 -0.01 C9.08 25.29, 52.7 116.21, 52.11 152.4 C51.51 188.59, 5.89 206.77, -3.25 217.15" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(477.7754417853704 386.99998474121094) rotate(0 24.668359239004417 108.56823457765549)"><path d="M14.46 193.67 C9.77 200.73, 4.83 207.07, -5.19 216.39 M13.48 192.72 C9.47 198.92, 4.86 204.43, -3.52 217.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(477.7754417853704 386.99998474121094) rotate(0 24.668359239004417 108.56823457765549)"><path d="M26.65 210.18 C18.59 212.83, 10.32 214.65, -5.19 216.39 M25.67 209.23 C18.63 211.24, 10.85 212.46, -3.52 217.01" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(425.10875477365164 419.99998474121094) rotate(0 -16.972179325830325 89.23514720534712)"><path d="M-0.36 0.99 C2.84 22.96, 29.25 103.02, 19.99 132.36 C10.74 161.7, -43.49 169.55, -55.9 177.02 M1.66 0.46 C4.7 22.5, 28.78 103.8, 19.57 133.39 C10.36 162.98, -41.34 170.57, -53.61 178.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(425.10875477365164 419.99998474121094) rotate(0 -16.972179325830325 89.23514720534712)"><path d="M-29.19 160.14 C-40.79 163.71, -48.64 173.35, -54.39 179.32 M-30.28 158.87 C-36.95 163.26, -42.49 169.24, -52.7 177.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(425.10875477365164 419.99998474121094) rotate(0 -16.972179325830325 89.23514720534712)"><path d="M-21.96 179.35 C-36.33 175.79, -46.85 178.31, -54.39 179.32 M-23.05 178.08 C-31.47 177.45, -38.92 178.36, -52.7 177.01" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(114.60875477365164 377.49998474121094) rotate(0 7.5 7.5)"><path d="M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M3.33 10.84 C6.55 8.42, 7.66 4.91, 10.54 2.54 M3.33 10.84 C5.28 8.75, 6.92 7.69, 10.54 2.54 M6.35 13.47 C7.67 12.5, 9.67 10.21, 12.91 5.92 M6.35 13.47 C8.16 11.11, 9.36 9.06, 12.91 5.92" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M10 2 M10 2 C11.2 3.33, 11.78 3.83, 13 6 M10 2 C10.87 2.81, 11.26 3.75, 13 6 M13 6 C14.65 9.05, 13.11 6.55, 13 10 M13 6 C16.67 7.31, 16.57 5.9, 13 10 M13 10 C12.51 10.97, 11.28 11.18, 10 13 M13 10 C12.49 10.58, 11.66 11.56, 10 13 M10 13 C8.6 14.58, 9.94 16.27, 6 13 M10 13 C6.41 15.57, 5.94 17.18, 6 13 M6 13 C4.69 11.88, 3.72 10.61, 2 10 M6 13 C4.55 11.97, 2.95 10.57, 2 10 M2 10 C1.44 9.41, -1.66 6.8, 2 6 M2 10 C2 7.81, 0.34 9.21, 2 6 M2 6 C3.26 4.19, 4.37 3.68, 6 2 M2 6 C3.03 4.79, 4.44 3.75, 6 2 M6 2 C8.69 0.95, 8.96 -1.4, 10 2 M6 2 C6.48 -0.12, 6.58 1.23, 10 2" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(415.60875477365164 409.49998474121094) rotate(0 7.5 7.5)"><path d="M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M3.33 10.84 C5.96 7.8, 7.5 4.3, 10.54 2.54 M3.33 10.84 C5.78 8.11, 9.27 4.32, 10.54 2.54 M6.35 13.47 C8.84 11.74, 10.01 9.28, 12.91 5.92 M6.35 13.47 C7.75 10.96, 9.47 9.24, 12.91 5.92" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M10 2 M10 2 C11.26 3.52, 11.73 4.55, 13 6 M10 2 C11.05 3.4, 12.25 5.11, 13 6 M13 6 C16.05 6.11, 13.55 9.45, 13 10 M13 6 C14.31 9.57, 12.9 6.24, 13 10 M13 10 C12.64 10.32, 11.51 11.09, 10 13 M13 10 C11.74 11.23, 10.87 12.34, 10 13 M10 13 C7.58 16.94, 9.27 13.62, 6 13 M10 13 C8.57 12.94, 10.18 15.9, 6 13 M6 13 C4.61 12.47, 3.05 11.42, 2 10 M6 13 C4.66 11.88, 2.92 10.99, 2 10 M2 10 C1.41 6.34, -1.2 9.74, 2 6 M2 10 C-0.19 8.34, 1.21 8.81, 2 6 M2 6 C2.9 4.34, 5.1 3.32, 6 2 M2 6 C3.41 4.63, 4.99 3.37, 6 2 M6 2 C8.95 0.96, 6.6 -1.32, 10 2 M6 2 C7.88 -1.42, 9.23 -0.31, 10 2" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(471.60875477365164 389.49998474121094) rotate(0 7.5 7.5)"><path d="M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M0.31 8.22 C0.31 8.22, 0.31 8.22, 0.31 8.22 M3.33 10.84 C5.5 7.36, 7.23 6.09, 10.54 2.54 M3.33 10.84 C5.31 9.53, 6.24 6.82, 10.54 2.54 M6.35 13.47 C8.51 11.47, 9.95 8.58, 12.91 5.92 M6.35 13.47 C7.95 10.7, 10.35 9.1, 12.91 5.92" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M10 2 M10 2 C10.82 2.51, 11.1 4.36, 13 6 M10 2 C10.66 2.98, 11.61 4.32, 13 6 M13 6 C13.11 6.55, 16.45 7.4, 13 10 M13 6 C16.57 5.9, 13.24 6.17, 13 10 M13 10 C11.61 10.89, 10.68 12.43, 10 13 M13 10 C12.04 11.15, 10.94 12.08, 10 13 M10 13 C9.94 16.27, 6.62 15.5, 6 13 M10 13 C5.94 17.18, 8.9 15.6, 6 13 M6 13 C5.33 11.81, 4.14 11.66, 2 10 M6 13 C4.91 12.07, 4.08 11.62, 2 10 M2 10 C-1.66 6.8, 1.74 7.83, 2 6 M2 10 C0.34 9.21, 0.81 8.97, 2 6 M2 6 C2.59 5.48, 3.82 4.52, 6 2 M2 6 C3.31 4.93, 4.73 3.53, 6 2 M6 2 C8.96 -1.4, 6.68 -0.11, 10 2 M6 2 C6.58 1.23, 7.69 1.91, 10 2" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(421.4420677619329 608.6666412353516) rotate(0 15.645775490626704 0.18181313132862442)"><path d="M-0.83 -0.89 C4.58 -0.77, 26.91 0.97, 32.12 1.08 M0.94 1.26 C6.32 1, 27.03 -0.58, 31.76 -0.65" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(421.4420677619329 608.6666412353516) rotate(0 15.645775490626704 0.18181313132862442)"><path d="M32.95 1.06 L17.9 7.16 L17.5 -7.3 L32.5 -1.08" stroke="none" stroke-width="0" fill="#000000" fill-rule="evenodd"></path><path d="M30.65 0.75 C29.14 0.42, 23.96 2.7, 18.29 7.24 M31.14 -0.64 C29.36 1.18, 25.6 2.59, 17.9 6.85 M18.82 7.23 C17.92 2.47, 17.82 0.18, 17.38 -7.4 M19.11 5.76 C18.02 4.26, 18.68 0.39, 18.31 -6.61 M19.02 -6.41 C21.93 -4.18, 28.4 -2.77, 30.42 -1.22 M17.57 -6.06 C22.22 -5.06, 26.58 -2.59, 31.25 0.09 M31.76 -0.65 C31.76 -0.65, 31.76 -0.65, 31.76 -0.65 M31.76 -0.65 C31.76 -0.65, 31.76 -0.65, 31.76 -0.65" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(124.44220509103445 204.3333282470703) rotate(0 -56.62977379366271 -56.91430162810924)"><path d="M1.18 -0.74 C-17.74 -11.18, -103.75 -43.61, -113.35 -62.71 C-122.95 -81.8, -66.12 -106.85, -56.42 -115.32 M0.34 1.49 C-18.2 -8.81, -101.96 -42.22, -111 -61.54 C-120.05 -80.87, -63.33 -105.47, -53.93 -114.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(124.44220509103445 204.3333282470703) rotate(0 -56.62977379366271 -56.91430162810924)"><path d="M-73.27 -91.7 C-67.49 -99.58, -62.09 -104.99, -52.39 -113.54 M-71.55 -91.48 C-67.53 -96.33, -61.77 -103.04, -53.77 -113.58" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(124.44220509103445 204.3333282470703) rotate(0 -56.62977379366271 -56.91430162810924)"><path d="M-84.41 -108.93 C-75.12 -111.49, -66.2 -111.45, -52.39 -113.54 M-82.69 -108.72 C-75.6 -108.97, -66.91 -111.14, -53.77 -113.58" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(121.7755180793157 193.6666717529297) rotate(0 5.833343505859375 8.5)"><path d="M5.53 0.83 C5.53 0.83, 5.53 0.83, 5.53 0.83 M5.53 0.83 C5.53 0.83, 5.53 0.83, 5.53 0.83 M1.98 11 C2.86 8.08, 5.53 6.76, 8.54 3.45 M1.98 11 C4.41 8.73, 6.97 5.95, 8.54 3.45 M5 13.62 C6.93 11.11, 9.35 9.17, 10.91 6.83 M5 13.62 C6.28 12.1, 8.29 10.1, 10.91 6.83" stroke="#12b886" stroke-width="0.5" fill="none"></path><path d="M7.5 2.25 M7.5 2.25 C8.6 3.47, 8.85 4.48, 10.17 6.75 M7.5 2.25 C8.57 3.82, 9.38 5.67, 10.17 6.75 M10.17 6.75 C9.73 10.14, 11.51 8.91, 10.17 11.25 M10.17 6.75 C12.32 10.02, 12.54 6.89, 10.17 11.25 M10.17 11.25 C9.79 11.77, 8.89 12.83, 7.5 14.75 M10.17 11.25 C9.36 12.46, 8.71 13.54, 7.5 14.75 M7.5 14.75 C7.12 18.95, 6.27 18.92, 4.5 14.75 M7.5 14.75 C5.16 17.97, 7.07 15.95, 4.5 14.75 M4.5 14.75 C3.82 13.69, 2.72 12.65, 1.5 11.25 M4.5 14.75 C3.8 13.76, 3.22 12.98, 1.5 11.25 M1.5 11.25 C-1.81 7.5, 0.7 9.27, 1.5 6.75 M1.5 11.25 C-0.01 9.67, 1.08 8.15, 1.5 6.75 M1.5 6.75 C2.06 5.34, 2.71 4.17, 4.5 2.25 M1.5 6.75 C2.61 5.12, 3.78 3.33, 4.5 2.25 M4.5 2.25 C6.61 1.43, 6.24 0.13, 7.5 2.25 M4.5 2.25 C7.72 -1.3, 7.36 0.12, 7.5 2.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(69.94215931466726 16.999984741210938) rotate(0 212.1667022705078 35.333343505859375)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.46 6 C1.69 3.73, 3.38 1.52, 5.72 0.69 M-0.47 6.62 C1.02 5.02, 2.28 3.16, 4.73 0.68 M1.57 10.75 C4.08 6.98, 8.42 1.72, 12.02 -0.67 M-0.52 11.31 C2.34 8.48, 5.37 5.86, 10.69 -0.32 M-0.36 17.49 C1.97 12.59, 8.32 12.08, 14.74 0.57 M0.37 18.69 C4.35 12.54, 8.58 8.26, 16.04 -0.01 M-1.63 25.77 C5.81 20.11, 11.73 12.51, 19.33 0.72 M-0.52 24.76 C4.74 18.3, 9.48 13.89, 21.47 0.68 M-1.37 30.09 C7.96 22.4, 16.7 14.4, 26.3 -0.35 M0.65 30.1 C9.01 20.61, 15.8 11.41, 26.59 0.72 M-1.17 38.2 C14.63 20.79, 25.28 8.45, 30.25 0.63 M-0.31 36.11 C9.11 25.25, 18.99 14.11, 31.96 -1.05 M-0.34 41.62 C8.09 30.7, 19.11 22.65, 35.44 -1.21 M-0.52 42.29 C10.22 32.72, 18.8 21.39, 36.15 0.34 M-1.33 48.44 C17.59 29.82, 31.28 11.12, 43.46 -0.39 M0.33 48.74 C11.19 35.86, 22.95 23.67, 42.24 -0.88 M1.2 54.65 C10.31 41.4, 24.46 29.46, 48.43 -0.46 M-0.16 54.07 C17.68 34.06, 36.75 13.06, 46.92 1.05 M-0.36 60.67 C13.13 48.39, 24.83 31.76, 52.66 0.51 M-0.08 61.66 C17.96 39.32, 37.49 18.2, 52.95 0.59 M0.41 66.68 C14.35 50.14, 26.02 35.31, 57.88 -1.43 M0.67 67.63 C12.04 53.06, 25.05 38.37, 58.23 -0.81 M-0.22 71.93 C16.92 55.06, 33.13 37.45, 64.89 -1.65 M2.02 71.77 C18.82 51.29, 36.73 29.49, 64.31 0.43 M8.33 73.54 C23.4 50.34, 40.98 29.44, 68.76 1.73 M7 71.05 C25.39 49.2, 45.21 28.2, 69.45 0.3 M12.07 72.88 C30.85 51.91, 48.45 31.24, 74.53 -1.7 M12.8 71.6 C28.43 53.95, 42.24 36.91, 75.12 0.38 M16.18 70.06 C34.54 49.55, 56.01 29.06, 80.37 2.02 M17.27 71.9 C30.7 57.52, 42.25 42.4, 79.05 0.08 M22.73 72.97 C39.04 50.44, 58.83 31.37, 85.31 1.7 M22.5 71.48 C39.58 51.9, 57.64 29.88, 85.75 -0.16 M27.88 71.95 C43.55 50.88, 60.24 34.2, 88.36 1.6 M26.87 72.19 C46.28 51.45, 63.69 30.19, 89.56 -0.61 M31.55 72.24 C53.31 46.26, 72.73 26.35, 96.29 0.01 M32.58 72.35 C53.05 49.69, 71.48 27.09, 95.15 -1.1 M38.63 72.6 C59.11 45.73, 84.73 18.29, 98.73 1.79 M37.68 72.06 C57.4 48.74, 77.3 25.95, 100.6 -0.73 M43.99 70.61 C61.91 51.57, 83.39 26.21, 107.89 0.9 M42.95 72.07 C63.05 47.08, 82.71 24.33, 105.86 -0.69 M48.96 73.5 C65.75 51.58, 86.72 31.14, 109.79 1.04 M49.18 71.32 C69.32 47.21, 90.93 23.49, 111.86 -0.05 M55.81 70.93 C78.79 44.38, 99.73 19.44, 115.22 -1.1 M53.54 71.39 C76.9 46.85, 99.14 22.59, 116.33 0.25 M58.75 70.33 C81.08 46.52, 103.42 18.58, 122.25 0.99 M59.41 72.46 C79.38 48.32, 100 25.09, 122.13 -0.19 M63.16 73.45 C80.12 57.99, 93.84 39.91, 128.68 -1.53 M65.42 71.54 C85.75 47.12, 106.03 23.21, 126.56 0.31 M69.24 70.92 C82.08 55.55, 97.28 41.97, 133.11 0.42 M70 71.65 C92.76 45.17, 115.44 20.37, 132.25 0.41 M75.21 70.83 C87.69 57.34, 102.34 41.12, 136.06 0.46 M74.38 72.12 C89.97 54, 105.56 37.77, 137.16 1.01 M80.99 73.26 C98.16 53.91, 110.5 38.02, 141.74 1.26 M81.14 71.71 C97.66 52.86, 114.21 34.14, 144.15 -0.53 M87.42 70.89 C105.03 52.55, 119.48 33, 147.16 1.15 M85.27 72.93 C106.5 48.26, 127.96 22, 148.98 0.8 M91.91 71.49 C116.84 44.46, 137.73 13.32, 151.86 -1.38 M90.63 71.15 C113.32 46.93, 134.9 20.64, 153.84 -0.1 M95.65 70.58 C119.74 46.72, 141.98 20.53, 159.1 -1.05 M97.05 72.93 C118.54 47.69, 138.92 22.95, 159.42 0.79 M103.27 69.9 C114.44 56.54, 126.97 40.1, 165.52 -1.27 M102.82 71.15 C118.82 52.61, 136.03 31.68, 164.41 0.78 M106.07 70.04 C122.88 55.27, 138.1 38.18, 170.36 0.45 M107.74 71.27 C120.51 54.71, 136.61 38.07, 169.51 -0.25 M113.66 72.95 C135.65 47.17, 156.66 21.79, 173.12 1.01 M113.65 70.54 C136.73 44.25, 158.67 18.85, 175.02 0.34 M117.2 70.55 C134.14 53.11, 152.53 34.92, 178.77 -1.63 M117.45 72.25 C135.84 52.96, 151.23 32.91, 180.81 1.16 M125.03 71.25 C140.97 54.73, 155.71 35.69, 187.4 0.02 M123.64 70.86 C143.18 47.59, 165.52 23.02, 185.91 -0.99 M129.91 72.54 C143.1 57.63, 155.08 40.06, 191.47 1.62 M129.35 72.34 C152.03 43.93, 174.95 17.72, 190.48 0.13 M132.66 71.56 C153.96 52.81, 169.69 28.22, 197.44 -0.51 M134.87 71.29 C154.74 47.36, 176.32 21.04, 195.4 0.38 M137.41 73.62 C152.98 54.28, 168.44 36.36, 202.99 1.23 M138.69 71.21 C160.96 46.51, 180.39 23.69, 202.26 0.48 M143.2 70.8 C159.38 56.14, 173.45 36.39, 206.68 -1.73 M144.02 71.69 C166.77 47.02, 186.63 23.67, 206.9 0.21 M151.25 70.53 C171.55 43.85, 196.05 15.05, 213.17 0.42 M149.82 72.67 C164 55.96, 176.96 40.17, 211.45 -0.34 M156.61 70.06 C179.82 43.09, 204.34 15.43, 218.88 0.42 M155.35 71.6 C173.54 50.17, 190.57 29.51, 217.87 -0.58 M159.34 73.17 C172.6 56.77, 188.77 39.76, 221.21 0.54 M161.16 71.73 C179.5 50.45, 200.09 26.38, 221.96 -0.17 M163.55 73.33 C178.37 56.32, 191.96 40.54, 228.17 1.1 M165.02 71.99 C178.67 57.66, 191.21 43.11, 228.88 -0.86 M171.91 70.61 C193.28 47.03, 211.77 20.81, 231.64 -0.9 M170.19 71.54 C186.72 52.79, 203.03 35.55, 233.24 0.8 M174.02 70.48 C193.4 51.99, 214.68 28.57, 236.34 1.44 M176.75 71.21 C193.71 50.24, 211.17 30.85, 237.9 0.38 M179.54 73.08 C202.23 46.78, 225.76 20.4, 244.35 -0.22 M182.48 72.45 C198.54 52.47, 214.64 33.93, 243.35 -0.94 M187.35 71.82 C202.3 52.4, 217.89 35.74, 249.52 -0.6 M186.87 72.58 C209.11 46.08, 231.3 19.18, 247.96 0.09 M191.18 69.94 C210.06 48.24, 230.91 27, 252.56 -1.58 M192.68 70.97 C211.09 52.44, 228.92 29.95, 253.91 0.76 M196.89 71.05 C210.23 55.33, 226.84 36.96, 260.2 0.42 M197.94 72.32 C215.78 49.85, 234.05 29.32, 260.18 0.64 M204.09 71.72 C218.32 55.36, 228.76 38.82, 264.85 0.98 M203.52 70.79 C220.76 50.88, 240.65 28.56, 265.12 0.75 M207.35 72.04 C226.15 48.54, 244.2 27.41, 271.86 0.29 M207.11 71.32 C228.4 48.8, 248.17 25.11, 269.44 -0.17 M213.89 72.13 C232.93 47.75, 254.24 22.22, 275.13 1.62 M212.81 71.76 C236.95 43.74, 260.49 16.56, 274.77 -0.47 M216.76 70.79 C239.34 51.51, 255.76 25.93, 280.35 -0.01 M219.1 72.15 C241.35 45.96, 262.88 20.51, 280.68 0.62 M224.54 69.99 C238.48 54.24, 257.96 33.87, 284.65 0.63 M224.42 70.9 C238.67 54.36, 252.28 36.13, 287.21 0.26 M230.5 73.48 C245.79 51.77, 263.98 31.5, 291.83 -0.36 M229.19 72.04 C244.85 52.07, 260.65 34.06, 291.92 0.15 M234.33 71.31 C251.75 52.42, 272.7 30.99, 296.02 -1.53 M235.32 71.41 C252.23 52.09, 269.41 32.48, 296.39 -0.2 M239.3 70.44 C263.05 43.63, 288.57 17.17, 300.85 0.53 M240.27 71.91 C262.68 46.02, 286.18 19.44, 301.27 0.73 M245.93 71.24 C259.23 54.5, 274.39 36.18, 307.18 1.74 M244.55 71.68 C265.89 46.29, 288.4 21.16, 306.81 -0.33 M249.23 70.15 C271.41 47.23, 292.57 20.92, 312.25 -0.9 M249.79 71.34 C274.49 43.41, 300.06 14.91, 311.9 0.83 M256.33 72.11 C272.05 54.11, 284.68 37.92, 317.41 1.22 M256.23 72.23 C281.56 43.06, 306.18 14.53, 318.58 -0.95 M259.7 73.26 C276.58 53.89, 288.6 36.88, 323.26 0.93 M260.78 71.58 C280.47 48.12, 301.62 26.38, 323.08 0.1 M266.85 73.38 C285.15 49.63, 303.4 27.49, 329.36 -2.19 M266.54 70.78 C290.51 42.74, 315.64 14.49, 328.36 -0.18 M273.47 70.55 C291.59 50.73, 310.55 27.02, 333.43 -1.22 M270.85 72.56 C288.24 52.85, 305.48 33.06, 333.14 0.38 M276.52 70.42 C298.19 49.72, 319.43 23.39, 339 0.61 M276.12 71.98 C290.08 55.1, 304.23 40.62, 340.41 -0.5 M282.64 73 C303.57 45.95, 324.77 20.74, 342.65 -1.44 M281.19 71.88 C298.46 54.01, 314.56 33.92, 344.49 0.66 M286.68 73.52 C304.02 55.06, 316.36 39.19, 348.99 1.6 M287.61 71.37 C310.62 45.08, 335.77 16.56, 348.89 1.06 M294.66 69.7 C314.98 48.51, 334.86 24.25, 353.16 1.32 M293.56 71.8 C309.62 50.95, 327.06 31.69, 354.63 0.1 M299.03 70.36 C315.33 50.87, 332.47 29.63, 361.3 -1.33 M296.81 72.94 C318.78 50.34, 337.31 27.87, 359.53 0.87 M302.31 69.92 C326.37 46.7, 346.22 22.38, 367.56 1.29 M303.31 72.26 C324.86 45.86, 347.51 21.66, 365.13 -0.95 M308.29 73.04 C319.91 57.39, 333.24 42.53, 371.3 2.11 M308.2 71.09 C323.97 54.92, 340.44 37, 370.66 0.23 M313.73 73.09 C332.66 48, 351.67 27.94, 374.77 -0.16 M314.36 71.88 C332.1 50.96, 350.22 30.31, 376.63 0.02 M319.52 72.8 C338.75 48.3, 359.54 22.77, 380.32 1.63 M319.39 72.4 C339.44 48.22, 359.14 24.08, 380.83 -0.64 M326.39 70.78 C339.14 56.2, 350.12 41.3, 388.06 -0.49 M324.2 70.95 C347.41 45.65, 370.25 18.32, 387.87 0.68 M330.1 70.07 C348.97 48.06, 369.37 23, 393.07 1.09 M330.03 72.6 C350.62 47.62, 371.18 23.12, 391.19 1.16 M337.11 72.72 C351.27 53.62, 366.57 33.49, 399.06 -2.02 M334.93 72.41 C350.15 55.02, 366.04 37.94, 398.64 -1.1 M339.78 72.39 C361.93 45.16, 384.51 18.13, 403.58 0.5 M340.87 71.63 C362.71 46.1, 385.38 19.55, 402.46 0.2 M344.06 72.82 C369.69 43.57, 396.02 16.44, 407.71 -1.9 M346.2 70.9 C360.86 56.52, 374.26 40.42, 408.84 -0.3 M352.65 72.49 C375.5 46.2, 395.14 17.48, 413.24 2.04 M350.72 72.56 C370.14 48.77, 389.88 26.49, 413.93 -0.3 M356.74 71.11 C376.83 48.8, 396.27 26.34, 420.33 -2.13 M356.23 71.73 C378.3 45.85, 402.81 18.47, 419.41 0.29 M363.14 70.24 C382 50.23, 398.48 29.73, 424.76 0.04 M361.5 72.66 C375.5 54.72, 389.81 39.14, 424.48 0.6 M366 71.8 C385.92 51.09, 403.8 29.84, 424.94 3.45 M366.84 71.85 C381.29 53.86, 397.28 37.41, 426.79 2.04 M374.01 70.67 C388.24 55.15, 403.04 36.47, 429.02 7.28 M373.16 72.36 C389.77 51.46, 407.37 30.73, 426.35 8.75 M378.05 73.25 C396.04 50.72, 412.47 30.62, 425.28 15.22 M378.43 70.92 C397.01 51.99, 415.21 30.8, 427.83 15.55 M382.39 69.98 C397.97 55.73, 409.13 38.18, 429.34 19.87 M382.77 72.27 C398.17 53.1, 415.18 33.05, 426.5 20.9 M387.75 70.73 C397.86 62.4, 406.67 49.38, 426.57 27.56 M388.31 73.01 C399.61 58.07, 410.85 44.36, 426.6 27.46 M393.74 73.51 C403.7 60.34, 416.59 46.49, 427.13 33.6 M393.47 72.16 C405.4 58.47, 416.7 44.89, 427.17 33.95 M399.32 71.4 C406.84 59.63, 417.14 52.3, 428.47 39.12 M398.33 72.59 C405.22 65, 409.99 58.78, 426.39 39.67 M403.85 69.75 C409.62 62.21, 417.32 53.07, 427.78 45.91 M403.46 71.99 C411.16 62.18, 419.55 53.03, 426.86 45.99 M408.3 72.85 C416.47 67.12, 418.56 58.99, 427.01 49.68 M409.96 72.08 C414.33 65.44, 420.15 59.78, 426.53 51.24 M412.98 72.34 C416.5 66.14, 419.56 65.35, 426.14 58.6 M415.01 70.91 C417.33 68.22, 422.04 64.15, 426.7 57.99 M418.93 70.94 C422.62 68.51, 424.18 65.69, 427.46 63.27 M419.82 71.91 C422.31 69.73, 424.48 66.51, 426.86 63.95" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-0.26 -0.41 C91.81 -0.91, 185.24 -0.82, 424.87 -0.05 M0.3 -0.04 C125.41 2.31, 251.1 2.36, 423.85 -0.39 M423.1 -0.49 C424.27 27.92, 423.24 55.48, 424.55 72.01 M425.31 0.14 C425.82 26.81, 425.28 54.82, 423.88 71.19 M424.7 71.46 C284.82 72.02, 142.74 72.24, 0.1 70.18 M423.94 70.85 C261.47 68.65, 98.61 68.9, -0.19 70.37 M-1.05 69.85 C-1.97 46.01, 0.54 20.83, 0.62 -0.12 M0.72 70.78 C0.64 45.26, 0.01 18.94, 0.05 0.97" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(131.1087700324407 105.50001525878906) rotate(0 45.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">prev_frame</text></g><g stroke-linecap="round" transform="translate(116.77557911447195 102.49995422363281) rotate(0 5.833343505859375 8.5)"><path d="M5.53 0.83 C5.53 0.83, 5.53 0.83, 5.53 0.83 M5.53 0.83 C5.53 0.83, 5.53 0.83, 5.53 0.83 M1.98 11 C4.67 8.7, 4.95 6.58, 8.54 3.45 M1.98 11 C3.88 9.35, 4.99 7.78, 8.54 3.45 M5 13.62 C6.38 12.16, 8.24 10.11, 10.91 6.83 M5 13.62 C6.9 11.26, 9.28 8.34, 10.91 6.83" stroke="#12b886" stroke-width="0.5" fill="none"></path><path d="M7.5 2.25 M7.5 2.25 C8.21 3.36, 9.3 4.92, 10.17 6.75 M7.5 2.25 C8.08 3.24, 8.86 4.34, 10.17 6.75 M10.17 6.75 C9.79 8.85, 10.04 10.32, 10.17 11.25 M10.17 6.75 C13.92 9.99, 9.86 11.07, 10.17 11.25 M10.17 11.25 C9.22 12.05, 9.23 13.17, 7.5 14.75 M10.17 11.25 C9.34 12.26, 8.71 13.13, 7.5 14.75 M7.5 14.75 C4.94 16.31, 4.7 18.59, 4.5 14.75 M7.5 14.75 C8.14 16.26, 3.83 19.06, 4.5 14.75 M4.5 14.75 C3.85 13.71, 3.59 13.02, 1.5 11.25 M4.5 14.75 C3.62 13.71, 3.02 12.88, 1.5 11.25 M1.5 11.25 C0.69 7.62, 0.16 8.28, 1.5 6.75 M1.5 11.25 C-1.65 6.77, -1.23 8.73, 1.5 6.75 M1.5 6.75 C2.59 6.14, 2.82 4.57, 4.5 2.25 M1.5 6.75 C2.44 5.56, 3.2 4.01, 4.5 2.25 M4.5 2.25 C6.05 -0.11, 6.84 -0.67, 7.5 2.25 M4.5 2.25 C4.44 -1.56, 7.11 -2.18, 7.5 2.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(123.10886158517508 110.33332824707031) rotate(0 -40.438134377168524 -47.67213378051295)"><path d="M0.63 0.71 C-12.52 -8.04, -70.32 -37.49, -79.39 -53.3 C-88.45 -69.11, -57.86 -87.27, -53.74 -94.16 M-0.49 0.04 C-13.68 -9.01, -70.83 -39.21, -79.84 -55.23 C-88.85 -71.24, -58.7 -89.71, -54.54 -96.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(123.10886158517508 110.33332824707031) rotate(0 -40.438134377168524 -47.67213378051295)"><path d="M-64.26 -72.44 C-61.86 -79.91, -58.24 -87.14, -53.93 -94.62 M-66.01 -73.42 C-62.01 -80, -59.16 -87.55, -54.46 -96.84" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(123.10886158517508 110.33332824707031) rotate(0 -40.438134377168524 -47.67213378051295)"><path d="M-75.88 -84.6 C-70.54 -88.98, -63.91 -93.05, -53.93 -94.62 M-77.63 -85.59 C-70 -88.46, -63.52 -92.22, -54.46 -96.84" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(510.44220509103445 10) rotate(0 54.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Stack bottom</text></g><g transform="translate(514.7754570441595 153.00005340576172) rotate(0 55 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">current frame</text></g><g stroke-linecap="round" transform="translate(66.4420219855657 631.0000305175781) rotate(0 214.8333740234375 24.166671752929688)"><path d="M0.57 -0.75 C154.98 -1.14, 309.95 -0.85, 429.95 -0.5 M0.28 0.33 C147.49 1.83, 295.24 1.8, 430.1 -0.17 M429.66 1.58 C429.58 13.17, 428.19 29.14, 428.06 46.71 M430.35 0.15 C429.38 11.96, 428.73 22.96, 430.38 48.74 M429.73 47.58 C277.58 49.48, 125.96 50.66, 0.15 49.17 M430.03 48.65 C317.46 48.6, 204.82 48.3, -0.46 47.83 M0.98 50.24 C-1.92 32.75, 0.23 20.72, 0.17 0.62 M-0.35 48.29 C0.36 31.74, -0.5 14.94, 0.78 -0.89" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(268.44208302072195 662.0001220703125) rotate(0 28.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Unused</text></g><g transform="translate(502.7755180793157 665.0001220703125) rotate(0 61 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">stack boundary</text></g><g transform="translate(509.77533497384695 619.000244140625) rotate(0 40 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">stack top</text></g><g stroke-linecap="round" transform="translate(109.67070050512564 507.66123261353005) rotate(0 179.3333511352539 12.999984741210938)"><path d="M0.34 0.17 C83.01 0.94, 164.47 -0.75, 358.75 -1.14 M-0.42 -0.1 C96.49 1.08, 193.49 0.95, 359.25 -0.33 M359.83 1.76 C359.93 11.2, 357.9 19.33, 356.68 25.41 M359.09 0.7 C359.45 6.47, 357.84 11.7, 357.76 25.27 M359.24 26.21 C245.11 25.02, 131.3 24.24, 0.81 27.12 M358.15 25.62 C264.58 23.82, 171.21 25.02, -0.38 26.24 M-0.78 24.25 C2.11 21.67, 0.39 15.26, 1.69 -0.9 M-0.63 25.03 C-0.06 19.7, 0.85 14.64, 0.18 -0.91" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(109.44208302072195 440.3334197998047) rotate(0 118 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">Wasm LOCALs (local.set/get):</text></g><g stroke-linecap="round" transform="translate(272.0040096787096 511.82783570190895) rotate(0 15.33331298828125 9.500045776367188)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.2 7.11 C0.58 4.97, 1.91 2.62, 5.4 0.45 M-0.35 6.64 C1.61 4.1, 3.68 2.36, 5.13 0.74 M-0.61 11.51 C3.13 8.02, 5.17 6.49, 11.42 0.12 M0.76 11.73 C2.72 8.53, 6.5 5.39, 10.24 -0.14 M1.39 17.6 C3.84 12.26, 8.92 8.68, 14.74 -0.17 M-0.14 18.13 C4.76 12.29, 10.46 7.91, 15.26 0.74 M4.74 21.31 C7.29 15.58, 11.45 11.47, 19.63 -0.78 M2.52 20.08 C8.31 14.8, 15.04 6.28, 22.24 -0.12 M6.89 21.58 C14.1 12.9, 18.18 10.14, 26.37 -0.37 M8.55 21.38 C14.56 14.9, 20.31 7.82, 26.79 1.2 M12.94 19.2 C21.29 15.03, 24 5.7, 30.37 1.94 M13.89 21.51 C20.11 13.54, 28.42 4.99, 30.92 0.97 M18.37 19.77 C22.55 18.1, 26.16 16.72, 30.01 6.03 M18.32 21.02 C21.82 18.35, 25.16 14.29, 31.34 5.48 M23.25 21.47 C26.89 18.34, 27.56 16.68, 31.34 13.44 M23.9 21.5 C26.13 18.71, 27.81 16.77, 31.02 12.65" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M0.78 -1.37 C10.36 -1.24, 21.05 1.5, 30.2 0.25 M-0.21 0.62 C8.47 0.58, 16.55 0.72, 30.37 0.67 M31.81 1.87 C32.38 3.15, 32.36 6.98, 29.42 18.86 M29.85 -0.57 C31.05 7.53, 31.23 14.84, 29.8 18.24 M32.57 17.01 C19.18 18.94, 6.31 18.98, -1.97 19.56 M30.44 19.7 C20.05 18.71, 10.58 18.36, -0.51 18.05 M1.27 18.72 C-1.28 11.12, -1.28 4.75, -0.75 0.78 M-0.27 18.4 C-0.27 14.57, -0.58 7.87, 0.58 -0.42" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(311.6706966904284 510.1611486901902) rotate(0 15.33331298828125 9.500045776367188)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.44 6.89 C1.54 4, 3.81 2.67, 5.26 1.11 M-0.45 6.26 C1.02 4.77, 2.08 3.75, 5.18 0.4 M1.38 11.43 C2.34 8.48, 6.83 5.75, 9.84 -0.25 M0.74 11.71 C2.72 8.41, 5.79 5.79, 10.28 -0.23 M-0.15 17.82 C4.65 11.66, 11.17 8.49, 14.91 1.16 M0.8 18.56 C3.38 14.18, 6.77 10.61, 14.8 -0.03 M2.16 19.09 C7.4 15.78, 14.42 6.16, 23.23 -0.18 M2.4 21.14 C8.81 13.53, 13.68 8.89, 21.32 -0.4 M9.23 21.33 C15.28 15.14, 21 7.63, 27.33 2.11 M7.59 20.51 C14.99 14.52, 19.68 6.02, 25.81 0.93 M14.26 22 C19.45 14.06, 28.98 5.11, 30.61 1.29 M13.45 20.22 C17.98 16.63, 22.18 13.18, 30.43 0.52 M18.14 20.66 C21.87 18.92, 25.34 14.49, 31.04 4.66 M17.69 21.82 C22.62 17.12, 24.87 13.73, 31.61 6.97 M23.64 22.01 C26.16 18.69, 27.53 17.1, 30.68 12.61 M24.43 21.2 C25.48 18.99, 26.86 17.39, 31.35 12.7" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M-0.41 1.23 C8.38 0.99, 15.97 1.28, 30.07 1.33 M0.6 0.98 C8.08 -0.59, 15.2 -0.9, 30.01 -0.07 M29.04 -1.14 C31.57 7.97, 31.94 15.5, 28.93 17.47 M31.57 -0.95 C30.7 6.95, 29.94 13.95, 29.73 19.27 M30.21 20.4 C19.64 18.66, 10.9 17.97, -1.03 17.1 M31.33 18.85 C17.87 18.97, 5.78 19.56, -0.39 19.41 M-0.54 17.79 C-0.71 15.47, -1.33 7.41, 1.17 -0.84 M0.08 18.51 C-0.57 11.99, 0.59 5.63, -0.01 -0.89" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(349.6707577255846 511.4944921960496) rotate(0 15.33331298828125 9.500045776367188)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.01 7.15 C0.44 5.32, 2.16 2.68, 4.72 0.8 M-0.07 6.44 C0.76 5.57, 1.57 4.26, 4.83 0.17 M-0.65 11.82 C2.32 9.61, 4.99 6.11, 9.96 0.14 M-0.22 11.84 C2.31 8.99, 3.96 7.05, 10.38 -0.12 M-0.84 19.27 C1.49 14.49, 7.11 11.62, 15.87 1.08 M-0.94 18.08 C4.01 14.75, 6.36 9.54, 14.63 -0.58 M4.86 20.95 C10.5 12.99, 18.12 3.27, 21.42 0.53 M2.95 20.73 C6.85 15.8, 10.96 13.05, 21.22 0.65 M8.96 23.24 C14.69 16.47, 21.13 7.19, 24.42 2.04 M7.44 22.07 C15.74 12.98, 20.67 6.51, 26.73 -0.37 M12.89 21.67 C17.94 13.34, 25.74 6.53, 29.62 1.84 M12.71 20.89 C18.04 14.49, 23.3 8.56, 30.87 0.7 M17.92 19.75 C22.17 16.3, 26.87 8.92, 32.49 8.02 M18.49 22.07 C21.49 18.38, 24.48 13.59, 32.55 6.36 M23.46 20.91 C25.43 17.9, 28.5 16.59, 31.78 12.11 M24.13 21 C25.87 18.91, 27.85 16.05, 31.25 12.83" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M-0.59 1.33 C9.11 -1.04, 20.4 1.03, 32.63 1.89 M-0.66 -0.07 C7.88 -0.47, 15.04 -0.56, 30.07 0.55 M28.93 -1.53 C32.09 7.94, 30.97 14.98, 28.78 18.8 M29.73 0.27 C30.8 5.61, 29.75 11.03, 31.33 18.61 M29.64 17.1 C23.5 18.44, 13.66 20.21, -0.29 17.61 M30.27 19.41 C21.89 18.18, 12.96 18.83, -0.64 18.53 M1.17 18.16 C1.15 11.74, 0.69 4.14, -0.98 -1.08 M-0.01 18.11 C0.6 14.19, 0.55 8.76, -0.72 0.49" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(388.6707577255846 512.827835701909) rotate(0 15.33331298828125 9.500045776367188)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.51 6.31 C0.46 5.6, 2.62 3.37, 5.32 -0.43 M-0.21 6.55 C1.18 4.65, 2.9 2.14, 4.84 0.56 M-1.44 10.59 C5.52 6.82, 7.46 5.12, 10.54 0.09 M0.2 12.28 C2.64 7.89, 7.45 4.51, 10.36 0.08 M-0.22 19.88 C3.65 15.79, 6.19 11.59, 17.43 1.33 M-1.04 19.31 C6.55 10.5, 11.64 3.83, 16.26 1.32 M3.86 19.74 C8.04 17.58, 11.19 11.27, 21.9 -1.77 M2.08 21.65 C7.93 16.25, 13.92 8.64, 21.13 -0.62 M7.15 21.52 C14.08 16.16, 18.26 9.54, 24.61 -0.71 M8.31 22.29 C13.24 14.71, 19.44 8.16, 26.92 0.06 M15.36 21.15 C19.99 12.67, 27.73 5, 31.08 -0.99 M13.89 20.5 C17.52 15.05, 22.25 10.89, 31.25 0.17 M18.09 21.88 C23.73 18.25, 27.8 12.73, 31.32 5.42 M18.21 21.38 C21.51 17.09, 26.26 11.67, 31.62 5.31 M23.11 21.77 C26.12 18.45, 29.78 14.59, 31.96 11.93 M24.01 20.58 C25.33 19.65, 26.79 17.09, 31.06 13.1" stroke="#40c057" stroke-width="0.5" fill="none"></path><path d="M1.4 -0.83 C9.06 0.7, 17.52 -0.96, 28.77 1.89 M-0.15 -0.69 C8.32 -0.9, 17.44 -0.6, 31.07 -0.19 M29.46 -0.89 C32.37 2.41, 29.64 9.01, 29.83 20 M30.18 -0.54 C30.41 6.56, 30.75 11.87, 29.78 19.73 M29.16 20.04 C22.26 20.56, 11.05 17.29, -0.04 17.97 M31.56 18.37 C23.57 18.43, 15.26 19.54, 0.12 19.59 M1.17 18.7 C-0.57 15.29, 1.43 11.04, 1.79 -1.7 M-0.32 19.52 C-0.81 12.27, -0.21 5.16, 0.09 -0.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(290.57010854999623 634.9946447839402) rotate(0 0.8891058973021586 10.258329023839963)"><path d="M-0.43 -0.33 C-0.18 2.94, 1.8 16.94, 2.21 20.46 M1.54 -1.55 C1.58 1.87, 1.34 18.68, 1.29 22.07" stroke="#000000" stroke-width="4" fill="none"></path></g><g transform="translate(290.57010854999623 634.9946447839402) rotate(0 0.8891058973021586 10.258329023839963)"><path d="M-2.35 12.46 C-0.7 15.76, 0.82 19.29, 0.98 21.11 M-1.7 12.27 C-1.24 14.01, -0.82 16.71, 0.92 22.48" stroke="#000000" stroke-width="4" fill="none"></path></g><g transform="translate(290.57010854999623 634.9946447839402) rotate(0 0.8891058973021586 10.258329023839963)"><path d="M4.64 12.56 C3.81 15.8, 2.84 19.3, 0.98 21.11 M5.29 12.37 C4.29 14.07, 3.24 16.74, 0.92 22.48" stroke="#000000" stroke-width="4" fill="none"></path></g></g><mask></mask><g transform="translate(115.55437738682588 510.8333435058594) rotate(0 45.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func locals:</text></g><g stroke-linecap="round" transform="translate(97.38772089268525 462.16668701171875) rotate(0 192.00001525878906 38.333343505859375)"><path d="M19.17 0 M19.17 0 C88.63 -2.16, 159.84 -1.51, 364.83 0 M19.17 0 C140.64 -0.33, 262.53 0.34, 364.83 0 M364.83 0 C377.17 -0.64, 383.35 7.41, 384 19.17 M364.83 0 C376.8 1.86, 382.07 8.04, 384 19.17 M384 19.17 C383.58 32.77, 384.4 45.01, 384 57.5 M384 19.17 C384.76 31.08, 384.2 43.94, 384 57.5 M384 57.5 C382.46 70.03, 377.13 75.43, 364.83 76.67 M384 57.5 C382.49 68.16, 379.3 75.4, 364.83 76.67 M364.83 76.67 C251.17 78.48, 138.06 76.07, 19.17 76.67 M364.83 76.67 C263.65 76.42, 162.62 76.78, 19.17 76.67 M19.17 76.67 C5.43 75.19, 0.13 70.54, 0 57.5 M19.17 76.67 C6.56 77.51, -0.4 71.49, 0 57.5 M0 57.5 C-1.56 44.95, 0.72 34.9, 0 19.17 M0 57.5 C0.61 45.17, -1.07 33.48, 0 19.17 M0 19.17 C-0.61 7.71, 4.6 1.47, 19.17 0 M0 19.17 C1.3 4.18, 6.73 -0.07, 19.17 0" stroke="#000000" stroke-width="1" fill="none"></path></g></svg> \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_exports.svg b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_exports.svg
new file mode 100644
index 000000000..573f11c35
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_exports.svg
@@ -0,0 +1,16 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1881.1670328776042 868.4740259407099" width="1881.1670328776042" height="868.4740259407099">
+ <!-- svg-source:excalidraw -->
+
+ <defs>
+ <style class="style-fonts">
+ @font-face {
+ font-family: "Virgil";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Virgil.woff2");
+ }
+ @font-face {
+ font-family: "Cascadia";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Cascadia.woff2");
+ }
+ </style>
+ </defs>
+ <rect x="0" y="0" width="1881.1670328776042" height="868.4740259407099" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(1043.166748046875 206.64086779229868) rotate(0 110.66668701171875 47.3148244222005)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.89 5.81 C1.21 5.6, 2.4 3.75, 5.22 0.61 M-0.03 6.68 C1.93 4.34, 4.12 1.45, 5.05 0.65 M-1.33 13.62 C4.51 7.38, 9.15 4, 10.99 1.52 M0.83 11.73 C3.61 9.28, 5.98 5.09, 10.38 -0.64 M-1.98 17.51 C3.18 11.5, 8.44 8.05, 16.07 0.65 M-0.79 17.98 C5.92 12.67, 12.32 5.35, 16.16 0.54 M0.1 23.16 C7.08 17.12, 10.76 12.48, 23.25 -2.05 M0.7 23.94 C8.26 14.33, 17.06 4.83, 21.86 -0.69 M-1.11 30.7 C8.64 19.87, 18.26 8.46, 26.77 1.57 M-0.73 30.39 C9.34 19.32, 17.47 10.03, 27.19 0.72 M-0.73 35.12 C10.45 24.67, 21.18 12.35, 29.92 -1.19 M0.68 37.18 C8.15 26.62, 17.38 16.62, 32.09 -0.83 M-0.86 43.45 C9.64 32.86, 19.8 21.53, 38.33 -0.87 M0.93 41.58 C14.37 28.56, 26.79 12.9, 36.63 -0.51 M-2.09 49.66 C16.1 29.71, 32.62 11.32, 41.65 -1.32 M-0.4 49.81 C16.8 30.67, 32.24 12.05, 42.58 -0.87 M1.49 55.86 C11.72 39.81, 25.32 26.76, 46.75 -1.13 M0.7 53.94 C9.61 41.57, 21.37 30.55, 47.45 -0.6 M-0.49 62.95 C19.13 38.74, 40.11 14.93, 51.38 -1.06 M0.73 61.19 C16.42 41.97, 32.47 22.88, 53.99 -0.3 M-1.66 67.92 C23.32 42.8, 43.3 16.26, 57.39 -1.49 M-0.49 66.81 C17.11 46.76, 34.52 28.57, 58.23 0.69 M1.54 74.59 C16.73 53.07, 36.07 31.76, 64.39 -1.87 M-0.44 73.61 C23.56 47.6, 44.61 23.31, 63.03 0.56 M0.38 78.53 C16.2 56.68, 38.66 36.77, 66.94 1.9 M0.34 78.41 C25.91 52.2, 50.71 21.84, 68.1 0.23 M0.82 86.29 C26.94 55.67, 50.44 25.1, 76.28 -2.06 M0.18 86.02 C23.24 56.49, 48.63 29.36, 73.52 -0.43 M-1.28 92.01 C22.49 61.19, 49.67 36.91, 77.45 1.06 M-0.73 91.43 C24.8 63.35, 47.74 35.05, 79.79 0.61 M0.82 94.44 C26.8 68.12, 48.09 41.87, 87.02 1.21 M1.55 95.54 C33.42 59.77, 64.59 23.88, 85.34 -0.24 M7.98 97.54 C38.95 57.58, 68.79 21.42, 90.28 -1.85 M7.69 95.4 C25.88 74.56, 45.49 52.97, 90.59 1.05 M10.93 94.04 C29.34 76.28, 45.01 54.22, 94.91 -2.06 M11.78 96.42 C40.09 62.45, 70.36 28.71, 95.44 0.32 M15.99 94 C40.4 68.73, 62.85 46.2, 100.17 -0.48 M16.87 96.6 C48.27 60.56, 78.41 24.85, 101.37 0.47 M24.16 96.6 C51.99 60.66, 83.1 24.94, 106.6 -0.72 M22.85 96.95 C40.44 75.28, 59.49 53.35, 106.88 -0.37 M29.58 94.96 C53.64 67.84, 78.97 38.13, 113.2 1.64 M28.84 96 C57.77 61.95, 86.14 28.61, 111.59 0.45 M32.01 94.98 C65.3 59.07, 96.86 22.73, 114.43 0.31 M32.45 95.27 C57.23 70.21, 79.61 43.86, 117.1 0.98 M37.85 96.61 C59.39 66.39, 84.77 42.69, 120.76 1.15 M38.67 96.2 C68.68 60.56, 98.22 27.73, 122.28 0.23 M45.36 96.45 C65.01 72.81, 86.02 47.6, 125.05 -1.02 M43.9 95.44 C70.71 64.69, 97.83 34.43, 127.62 0.59 M50.29 96.28 C77.96 64.82, 102.34 35.02, 133.63 0.86 M49.49 94.98 C79.33 63.48, 106.48 30.98, 133.06 -0.24 M55.1 97.68 C79.76 67.56, 101.27 40.97, 137.47 -1.32 M53.74 95.46 C78.03 68.77, 102.99 40.96, 137.05 1.08 M58.67 94.49 C80.04 71.13, 100.58 49.61, 143.89 -0.29 M59.5 96.29 C76.15 75.73, 93.45 57.47, 143.1 0.62 M65.45 95.49 C97.52 59.28, 128.86 20.43, 147.72 -0.82 M64.11 96.98 C97.82 57.93, 129.34 21.5, 148.75 -0.48 M71.17 96.88 C85.55 75.27, 104.46 55.64, 155 -1.19 M71 95.25 C93.08 71.43, 113.45 45.95, 154.17 -0.91 M75.99 96.88 C93.48 73.51, 115.2 50.6, 158.17 -0.57 M75.7 96.33 C92.87 73.98, 112.05 53.61, 159.15 1.13 M82.26 96.28 C101.24 73.26, 118.94 52.94, 163.75 -0.56 M81.36 95.14 C109.08 63.27, 137.07 32.5, 163.62 -0.9 M87.63 96.99 C116.62 61.12, 149.2 25.37, 167.53 -0.49 M86.8 95.53 C103.39 76.48, 121.47 55.95, 168.74 0.33 M90.78 94.64 C114.26 72.41, 134.85 43.72, 174.26 1.01 M92.02 96.44 C113.56 71.37, 136.29 45.51, 175.38 -0.73 M96.62 97.11 C117.75 75.1, 135.2 50.06, 180.84 -1.32 M96.26 95.24 C130.34 58.5, 162.12 20.7, 179.13 -0.32 M101.92 97.1 C130.95 58.24, 164.03 25.82, 184.01 -0.89 M101.5 95.79 C123.03 73.45, 142.1 51.02, 184.93 -0.12 M108.56 94.69 C132.23 67.25, 155.44 37.59, 191.52 1.35 M106.52 95.81 C127.52 74.05, 148.49 50.54, 189.98 0.93 M113.19 93.93 C139.3 64.43, 168.78 35.47, 197.83 -0.54 M112.41 94.98 C144.91 58.98, 177.37 19.71, 196.36 -0.11 M116.4 97.35 C142.39 69.48, 162.11 43.95, 203.3 -0.92 M118.61 96.26 C134.2 76.46, 152.61 55.27, 202.02 0 M124.46 94.58 C156.13 59.51, 187.41 22.89, 205.87 -0.04 M124.43 96.01 C146.25 71.5, 167.19 46.27, 207.32 -0.07 M130.44 96.86 C161.31 57.7, 189.44 23.43, 212.26 0.58 M129.1 95.29 C146.09 74.65, 166.07 53.83, 212.08 -0.02 M135.94 93.63 C163.08 61, 191.18 28.64, 217.64 0.66 M133.31 96.02 C162.29 62.85, 191.07 30.69, 218.06 -0.7 M140.29 95.12 C155.63 72.28, 176.76 50.72, 220.18 2.5 M139.18 96.25 C167.9 62.49, 196.67 28.87, 221.4 0.88 M145.54 97.6 C167.69 71.96, 186.24 46.82, 222.1 4.55 M145.23 97.08 C165.28 71.46, 186.12 48.26, 222.47 5.76 M148.94 94.23 C174.16 66.58, 202.76 33.44, 220.65 12.41 M149.6 96.18 C174.35 68.28, 201 39.26, 222.77 13.7 M153.45 95.88 C168.05 78.33, 185.24 62.65, 222.08 17.23 M154.43 96.2 C173.22 74.06, 193.01 52.89, 221.61 20.21 M158.71 94.42 C181.03 72.12, 200.19 49.81, 220.63 23.21 M159.68 96.79 C180.97 72.72, 201.33 47.81, 223.09 25.74 M164.27 95.29 C179.53 80.97, 191.22 66.55, 223.04 30.44 M166.23 96.79 C187.1 72.81, 205.9 48.83, 221.35 31.17 M169.26 96.07 C187.75 75.02, 206.1 55.9, 221.57 36.21 M170.33 95.45 C185.96 77.84, 202.15 59.21, 221.49 36.75 M175.58 95.05 C190.04 79.96, 205.08 59.96, 223.2 41.59 M176.71 96.68 C188.75 81.82, 202.13 67.41, 221.58 43.37 M183.6 93.74 C192.15 83.21, 202.41 71.05, 222.63 48.69 M181.04 96.22 C189.57 84.94, 198.58 74.95, 221.53 49.46 M187.31 97.53 C193.55 84.99, 205.29 76.45, 222.79 55.52 M187.02 95.9 C198.95 82.46, 211.06 69.89, 222.42 54.49 M194.07 94.14 C201.76 84.26, 209.68 74.86, 221.26 60.79 M192.86 94.83 C199.33 87.28, 208.95 77.05, 222.8 61.46 M195.74 94.27 C202.66 90.88, 208.66 83.06, 221.37 67.22 M198.38 95.63 C203.85 88.76, 209.89 81.92, 222.58 66.84 M204.38 94.11 C210.78 89.46, 217 78.48, 223.3 74.08 M203.44 95.65 C208.49 90.16, 212.68 84.83, 222.03 72.81 M207.47 95.94 C211.54 90.23, 217.61 86.4, 223.2 80.56 M207.09 95.21 C211.4 92.69, 214.23 87.47, 221.68 79.2 M214.9 95.01 C217.48 90.96, 219.74 87.84, 223.1 86.28 M213.89 95.07 C215.53 92.71, 217.46 90.64, 222.49 85.92 M218.36 95.6 C220.01 94.47, 220.77 93.24, 221.91 92.01 M218.88 95.79 C219.24 95.03, 219.98 94.24, 221.93 92.35" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M1.45 0.67 C48.55 0.84, 100.74 3.3, 219.61 1.42 M0.05 -0.25 C45.98 -0.39, 92.98 -0.07, 221.85 -0.37 M219.62 1.34 C222.48 36.93, 219.42 75.87, 220.82 92.82 M220.61 0.6 C222.81 19.73, 221 38.3, 221.95 94.36 M220.06 94.37 C160.73 92.94, 100.23 94.11, -1.58 93.83 M221.4 94.02 C161.06 92.93, 101.41 93.95, -0.81 94.41 M-0.3 93.46 C-1.36 70.21, -1.76 49.84, 1.59 -1.06 M-0.34 94.99 C-1.42 66.62, -1.41 39.91, 0.92 -0.26" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1043.8334350585938 161.30749376886118) rotate(0 48 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#1864ab" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule</text></g><g stroke-linecap="round" transform="translate(1032.5001220703125 190.97421129815805) rotate(0 123.55554877387152 132.83335876464844)"><path d="M-1.38 -0.87 C52.11 0.67, 101.18 0.56, 245.6 -0.99 M-0.11 -0.61 C71.66 0.29, 142.3 0.24, 247.92 -0.34 M248.32 -0.63 C244.11 58.53, 244.91 114.99, 245.57 266.67 M247.8 0.46 C244.85 67.35, 246.07 134.5, 246.9 265.78 M246.97 265.11 C187.04 265.92, 125.86 264.61, -0.47 264.74 M246.88 265.18 C188.48 264.72, 128.84 264.02, -0.48 265.67 M-1.07 264.44 C-1.07 194.21, 1.57 120.4, -0.2 1.24 M-0.54 265.04 C0.19 184.03, 1.45 102.63, -0.51 -0.75" stroke="#1864ab" stroke-width="4" fill="none"></path></g><g transform="translate(1043.6112738715278 233.4556633923421) rotate(0 105.5 27.999999999999986)"><text x="0" y="14.666666666666668" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMTable *tables;</text><text x="0" y="33.333333333333336" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMMemory *memories;</text><text x="0" y="52" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMGlobal *globals;</text></g><g transform="translate(1093.5001831054688 373.64086779229865) rotate(0 82.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMExport *exports;</text></g><g stroke-linecap="round" transform="translate(1047.8335571289062 358.97424181573615) rotate(0 108 21.33331298828125)"><path d="M-1.6 -1.05 C83.78 -1.45, 167.51 -1.78, 214.7 1.6 M0.86 -0.36 C56.08 0.07, 114.17 1.48, 215.65 -0.67 M214.05 1.27 C214.96 12.2, 217.1 29.05, 217.16 40.8 M215.73 0.14 C215.69 12.04, 216.11 25.47, 215.66 42.55 M215.5 41.68 C142.78 41.93, 70.49 41.3, -1.02 42.92 M215.49 42.67 C138.14 42.06, 60.27 41.6, -0.68 41.9 M-0.25 44.23 C-0.21 27.13, 0.37 11.61, -1.57 -1.34 M-0.65 41.72 C-1.15 30.61, 0.53 19.81, -0.24 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1062.5003051757812 369.6409288274549) rotate(0 7.666656494140625 11.333343505859375)"><path d="M7.15 -0.18 C9.64 2.06, 10.85 3.82, 16.62 11.48 M7.71 -0.57 C9.98 4.71, 13.76 8.28, 14.8 12.14 M16.16 11.4 C12.28 15.63, 12.34 18.53, 6.79 22.66 M15.43 11.63 C12.17 15.74, 9.94 19.48, 7.92 22.89 M7.25 21.84 C6.48 19.48, 4.33 17.41, 0.19 12.79 M8 22.48 C6.27 20.03, 4.27 17.7, -0.59 12.32 M1.13 12.09 C2.6 7.97, 5.15 1.77, 7.03 -0.4 M-0.68 11.45 C2.85 8.01, 6.57 2.47, 8 0.4" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1389.8704460991748 278.41847772339696) rotate(0 78 64.16667175292969)"><path d="M-1.87 -0.51 C36.48 -0.93, 74.73 -1.22, 154.83 -1.36 M0.79 -0.53 C34.59 0.03, 69.5 -1.09, 156.36 -0.68 M157.84 -0.53 C153.85 26.51, 153.62 55.92, 157.84 129.06 M155.57 0.8 C156.86 34.56, 155.53 71.4, 155.28 129.07 M155.97 127.72 C123.75 131.22, 94.81 128.17, -1.47 128.83 M156.29 128.65 C95.28 128.67, 33.13 129.73, 0.71 128.77 M0.3 129.77 C0.39 82.62, -2.3 34.06, 1.98 0.54 M0.22 129.3 C-0.96 91.23, -1.77 54.51, -0.39 0.55" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1392.1296827528208 255.78885261489003) rotate(0 48.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMExport</text></g><g transform="translate(1421.537102593316 288.75182122925634) rotate(0 44 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">char *name;</text></g><g transform="translate(1418.8704155815972 321.08519525269384) rotate(0 37.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">uint8 kind;</text></g><g transform="translate(1414.2037590874565 354.41847772339696) rotate(0 46.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">uint32 index;</text></g><g stroke-linecap="round" transform="translate(1405.2037896050342 284.418492982186) rotate(0 60.333343505859375 14.833335876464844)"><path d="M0.58 0.12 C22.94 -0.06, 50.75 -0.69, 120.27 -1.81 M-0.45 -0.88 C40.48 -0.37, 82.35 -0.29, 119.99 -0.01 M119.12 1.98 C120.55 11.77, 121.3 24.46, 121.9 29.44 M121.27 0.22 C121.31 10.59, 121.36 18.59, 120.53 28.69 M121.86 28.38 C84.91 27.76, 46.23 29.27, 1.76 31.2 M121.22 30.06 C77.02 27.8, 34.9 29.04, -0.7 29.07 M1.77 28.06 C-0.87 23.66, -1.05 13.89, 0.73 -0.42 M-0.98 29.16 C-0.86 20.49, -0.39 12.37, -0.23 0.85" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1405.8704460991748 320.08519525269384) rotate(0 59 13.166656494140625)"><path d="M0.44 1.28 C37.42 0.65, 69.66 -0.97, 116.05 0.25 M-0.64 0.98 C23.47 -0.2, 48.23 0.17, 118.77 0.56 M118.79 -1.42 C116.26 10.67, 118.73 19.49, 116.82 25.57 M117.2 -0.57 C119.02 4.94, 118.02 11.55, 117.79 26.11 M116.99 24.99 C73.23 24.79, 30.57 24.72, 1.7 25.85 M117.96 25.86 C86.44 25.25, 53.35 24.75, -0.59 27.04 M0.45 28.17 C0.18 16.86, -0.58 8.54, -1.13 0.3 M0.71 26.86 C0.91 19.13, 0.84 12.51, -0.31 0.58" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1403.2037896050342 351.0851647351157) rotate(0 63 14.833328247070312)"><path d="M-0.38 -1.44 C48.21 -0.97, 98.37 0.36, 126.26 -1.79 M-0.21 0.96 C47.91 -1.14, 94.57 -1.55, 125.01 0.27 M127.09 -0.5 C127.66 10.67, 126.58 21.67, 124.93 30.3 M125.5 0.02 C126.99 11.6, 126.24 21.73, 126.66 30.06 M126.45 28.45 C89.43 29.44, 47.93 28.16, 0.24 29.51 M126.25 29.16 C78.14 30.5, 31.23 30.54, -0.04 28.86 M0.79 27.84 C0.64 19.32, -1.78 9.87, 1.1 -0.34 M-0.04 30.12 C-0.33 19.51, 0.61 9.14, -0.2 -0.9" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1458.537133110894 385.25185174683446) rotate(0 10 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(1390.5371025933155 407.4185082409751) rotate(0 79 21)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.85 6.73 C1.68 4.1, 3.34 2.06, 4.91 0.88 M-0.01 6.51 C0.74 4.64, 2.36 3.58, 4.79 0.21 M1.57 13.25 C3.91 10.01, 7.2 4.17, 9.67 1 M-0.31 12.65 C2.37 9.47, 4.16 6.46, 11.1 0.33 M-0.15 19.72 C5.17 13.49, 9.88 9.53, 15.77 1.8 M-0.55 18.84 C2.92 13.78, 5.77 11.14, 15.59 -0.5 M1.1 22.18 C3.61 20.75, 10.86 11.98, 20.8 1.62 M-0.16 24.81 C4.67 18.69, 9.97 12.98, 20.39 -0.33 M-0.21 28.78 C8.21 17.91, 19.17 8.51, 24.51 -0.46 M-0.61 30.56 C5.05 24.04, 10.41 18.3, 26.7 0.12 M0.16 36.04 C6.49 27.38, 13.61 21.46, 33.63 1.34 M0.42 36.64 C7.97 27.47, 16.6 16.6, 32.48 0.02 M1.03 44 C14.51 26.39, 26.3 11.73, 36.76 0.42 M0.2 41.86 C15.21 26.53, 28.79 8.71, 37.55 0.75 M4.18 42.25 C11.93 32.18, 21.71 22.01, 44.1 0.3 M5.21 42.95 C17.62 28.86, 29.63 15.08, 42.15 -0.9 M10.36 43.08 C24.7 29.16, 33.02 14.84, 46.61 -0.82 M9.96 42.36 C24.67 25.86, 38.79 9.68, 47.96 -0.51 M17.42 43.69 C28.32 29.55, 41.61 11.58, 51.71 0.54 M17.01 42.16 C24.6 32.5, 32.67 23.32, 52.63 -0.79 M20.93 42.03 C36.51 26.12, 49.75 10.08, 58.47 1.69 M22.36 42.51 C34.69 27.4, 48.86 10.92, 58.83 0.61 M27.83 41.37 C41.38 27.38, 50.14 14.35, 65.3 0.28 M27.05 41.88 C38.06 31.5, 47.27 18.87, 64.75 0.33 M33.69 40.9 C39.38 33.44, 45.62 26.22, 69.13 -1.03 M31.14 42.32 C46.2 26.22, 61.59 8.43, 69.15 -0.47 M36.31 40.22 C50.41 28.99, 62.86 14.98, 73.09 -0.12 M37.25 41.61 C46.62 31.65, 55.3 20.57, 73.89 -0.9 M40.98 41.95 C55.64 26, 72.65 11.12, 77.7 1.22 M42.63 42.52 C54.06 31.09, 64.43 18.25, 78.96 -0.13 M50.11 40.29 C58.02 30.89, 70.38 16.31, 84.59 -0.16 M48.61 41.01 C63.3 25.93, 77.49 9.06, 85.01 -0.17 M52.45 43.57 C62.38 31.5, 75.21 19.13, 91.65 -0.22 M52.73 41.48 C65.31 29.28, 77.69 15.7, 90.4 0.39 M60.8 42.8 C70.94 24.89, 86.26 8.84, 96.71 -1.16 M58.2 42.93 C74.38 25.13, 87.96 7.95, 95.68 -0.48 M65.12 42.29 C75.28 30.56, 82.23 17.87, 100.77 1.16 M63.94 42.24 C76.76 26.43, 91.01 11.23, 100.68 0.05 M70.31 40.13 C84.93 27.38, 97.49 9.08, 107.65 -0.28 M70.15 42.37 C79.2 30.2, 89.03 20.08, 107 -1.18 M73.34 42.82 C88.72 24.9, 103.62 11.46, 111.21 1 M74.31 41.54 C86.68 28.85, 99.52 13.65, 111.08 0.96 M80.28 42.56 C89.29 32.62, 95.43 23.76, 114.35 0.2 M80.05 42.27 C86.28 34.52, 95.66 24.06, 116.03 -0.18 M86.79 44.03 C97.65 30.11, 108.47 17.42, 123.47 -1.88 M84.49 42.77 C96.82 29.11, 107.43 17.45, 121.98 -0.57 M88.61 41.27 C104.24 26.61, 116.16 10.99, 125.01 -0.07 M90.52 43.48 C103.83 26.07, 116.99 11.08, 127.37 0.01 M96.53 40.93 C105.34 33.48, 109.82 26.54, 134.38 0.49 M96.69 42.98 C104.27 31.68, 114.91 21.11, 131.83 0.91 M99.62 42.87 C112.06 26.47, 127.88 10.62, 137.25 -1.05 M100.27 42.28 C111.46 29.12, 121.63 17.78, 138.21 -0.17 M104.92 42.69 C115.82 29.07, 126.77 19.03, 143.13 -0.76 M105.71 41.93 C117.84 30.51, 127.53 18.07, 144.14 -0.96 M112.61 44.35 C120.39 35.34, 125.96 24.12, 146.66 0.71 M111.76 42.37 C121.11 31.14, 130.36 22.16, 148 0.62 M115.7 42.64 C124.68 31.42, 132.91 23.39, 153.22 -1.36 M117.93 43.02 C132.54 26.19, 145.63 8.48, 154.51 0.63 M123.23 43.86 C134.64 28.98, 145.73 17.5, 160.18 -1.16 M121.55 42.61 C132.46 29.3, 144.5 16.16, 158.74 0.4 M127.94 40.27 C139.04 29.5, 146.91 21.88, 156.64 4.94 M128.3 42.33 C138.12 30.03, 149.3 17.84, 157.73 7.45 M133.47 42.73 C138.4 33.22, 147.04 25.05, 158.97 11.91 M133.25 42.07 C141.13 34.73, 147.07 25.98, 158.89 13.69 M138.05 43.21 C145.99 34.5, 151.45 25.49, 156.89 17.2 M137.36 41.62 C145.54 34.35, 150.9 26.66, 157.86 18.15 M141.67 43.42 C148.48 35.26, 153.33 28.25, 158.45 26.28 M142.54 42.94 C147.33 39.3, 149.63 34.13, 158.41 25.27 M149.58 41.46 C151.5 40.54, 153.02 38.26, 159.04 30.11 M148.39 41.49 C152.69 37.78, 156.42 32.61, 159.2 30 M153.44 42.8 C155.53 41.48, 156.83 39.61, 158.68 37.69 M154.04 42.12 C154.85 41.42, 155.7 40.2, 158.5 37.4" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M0.4 -0.47 C56.07 2.7, 113.88 2.96, 157.92 -0.36 M0.27 -0.07 C54.21 -0.95, 107.89 -0.81, 157.65 0.02 M159.68 -0.05 C159.16 16.64, 158.64 33.3, 157.16 43.23 M157.08 -0.96 C158.07 16.56, 158.46 32, 157.99 42.04 M157.58 43.78 C103.06 40.96, 47.97 41.65, 1.79 43.77 M157.78 41.91 C97.64 42.58, 37.24 42.94, 0.57 42.05 M-0.14 43.49 C0.44 34.39, -0.95 23.44, 1.82 0.3 M-0.93 42.39 C-0.74 26.36, 1.01 12.91, 0.37 0.44" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1459.537102593316 418.9185082409751) rotate(0 10 9.5)"><text x="10" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[1]</text></g><g stroke-linecap="round" transform="translate(1391.5371025933155 450.4185082409751) rotate(0 79 21)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.33 5.68 C1.26 4.43, 3.58 1.9, 4.68 -0.26 M-0.59 6.06 C1.25 4.91, 2.16 3.4, 4.79 0.72 M1.49 11.05 C3.6 8.85, 7.68 3.89, 9.5 0.86 M-0.08 12.62 C3.27 9.56, 5.4 5.2, 10.08 -0.49 M-0.88 16.55 C4.67 12.26, 7.72 8.22, 15 -0.42 M-0.3 17.63 C3.71 12.8, 8.42 8.34, 15.42 -0.5 M1.71 23.53 C5.09 16.45, 13.49 9.68, 19.79 1.07 M0.39 24.66 C5.37 18.93, 9.77 14.35, 22 -0.55 M0.17 32.3 C6.13 20.62, 16.29 10.67, 26.81 1.13 M0.5 29.74 C7.3 22.34, 12.57 15.3, 25.27 0.02 M0.18 37.43 C10.23 24.95, 16.51 17.91, 32.11 0.49 M-1.02 37.13 C9.34 25.68, 19.26 14.45, 32.84 0.12 M-0.9 44.19 C6.45 34.17, 14.27 24.36, 35.85 -0.41 M-0.59 42.98 C8.66 30.81, 19.33 21.81, 36.3 1.13 M6.5 40.47 C14.3 30.52, 27.27 19.57, 42.17 -1.1 M5.17 43.11 C16.25 30.03, 27.16 17.47, 42.67 0.12 M12.27 43.83 C17.95 32.88, 30.45 21.79, 46.44 1.46 M11.19 42.89 C22.46 29.46, 34.44 15.27, 48.41 0.18 M16.9 41.54 C23.49 31.86, 31.04 24.34, 55.12 1.23 M16.95 41.16 C27.49 28.22, 40.86 14.01, 52.85 -0.29 M20.22 44.35 C27.57 34.98, 34.16 25.16, 57.06 1.58 M20.78 42.79 C33.01 27.67, 45.51 13.09, 58.19 0.64 M27.16 40.88 C36.81 29.74, 49.13 14.87, 63.29 -0.28 M26.38 42.96 C36.05 30.95, 45.46 20.33, 62.93 -0.24 M33.13 42.12 C43.97 26.46, 57.35 13.43, 70.36 1.12 M31.78 42.46 C45.02 26.82, 60.19 10.51, 67.89 1 M37.79 43.8 C48.37 29.19, 58.27 17.18, 76.14 -0.03 M37.78 41.95 C51.94 27.06, 65.1 10.77, 73.63 0.7 M42.36 42.87 C53.07 28.89, 65.02 12.88, 79.13 1.61 M42.96 43.28 C55.39 28.63, 67.6 14.62, 78.44 -0.11 M47.46 43.94 C56.6 29.06, 65.54 22.23, 86.29 -1.06 M48.13 41.69 C58.52 30.98, 68.38 19.95, 85.82 -0.44 M54.39 43.68 C60.95 31.67, 70.48 22.85, 88.33 -1.09 M53.28 43.2 C63.27 30.04, 75.42 16.57, 90.43 0.98 M58.99 41.29 C68.99 31.01, 79.33 20.55, 95.53 -1.09 M58.09 42.79 C68.83 28.23, 79.72 16.98, 95.57 -1.07 M64.9 42.94 C76.99 28.46, 87.47 12.91, 101.06 1.24 M64.86 41.76 C78.82 25.1, 92.95 9.66, 101.14 0.03 M69.39 40.19 C78.48 33.68, 85.44 24.1, 104.79 1.52 M69 41.94 C84.29 26, 98.37 10.94, 107.11 -0.02 M72.69 42.43 C89.34 24.85, 99.94 12.06, 112.6 -0.85 M73.99 43.06 C85.61 28.99, 95.16 16.54, 111.5 -0.13 M79.12 44.08 C85.92 32.9, 96.59 25.91, 115.52 -1.51 M79.21 41.68 C86.91 32.85, 95.58 23.89, 117.18 0.21 M85.72 41.24 C93.47 30.37, 104.31 23.16, 120.36 -0.47 M86.14 42.79 C99.28 26.87, 111.78 11.49, 121.13 -0.58 M88.81 42.46 C102.74 28.67, 115.99 11.63, 126.28 -1.37 M89.69 42.34 C98.29 32.76, 104.73 24.9, 126.67 -0.56 M95.14 41.82 C105.8 26.7, 118.09 14.5, 133.93 -0.37 M94.94 41.22 C107.31 29.24, 119.26 16.82, 133.31 0.67 M101.24 41.46 C111.24 31.26, 122.7 18.4, 138.81 -1.63 M101.14 41.61 C115.36 26.54, 128.58 9.94, 137.67 -0.67 M105.21 43.96 C118.39 27.85, 134.2 14.43, 145.03 1.04 M107.19 42.2 C117.11 31.27, 127.3 19.62, 144 -0.31 M110.03 42.79 C126.92 27.17, 138.3 10.22, 146.68 0.71 M111.58 42.5 C120.7 31.66, 132 17.96, 149.1 -0.62 M115.37 42.78 C127.22 29.87, 142.28 15.06, 153.57 -0.32 M117.89 42.13 C131.31 26.08, 145.77 10.25, 152.83 -0.37 M120.94 42.51 C132.26 29.97, 141.62 20.32, 160.61 1.99 M122.71 43.1 C130.26 32.94, 137.36 24.61, 159.05 0.63 M126.23 42.77 C135.93 33.32, 140.08 24.95, 159.68 6.61 M127.18 43.04 C134.77 35.47, 140.1 27.6, 158.19 6.52 M133.89 41 C137.36 36.92, 142.05 30.99, 159.32 14.76 M132.88 41.56 C139.29 34.72, 145.48 27.96, 158.62 13.57 M137.52 43.74 C146.26 35.62, 148.82 26.59, 158.87 18.96 M137.38 41.48 C145.06 34.07, 150.2 28.31, 159.38 19.13 M144.97 41.02 C150.17 35.96, 155.96 26.97, 157.65 26.45 M144.13 43.13 C145.83 39.45, 149.66 34.6, 159.06 25.83 M149.86 42.65 C152.19 36.98, 155.47 33.64, 159.78 30.46 M148.24 41.73 C150.98 39.31, 153.02 36.47, 159.41 30.62 M153.41 42.14 C155.01 40.66, 156.81 39.13, 158.05 37.5 M153.68 42.66 C155.43 40.96, 156.28 39.36, 158.81 37.41" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M1.77 1.67 C44.17 -0.72, 91.67 -1.6, 158.53 0.05 M0.05 -0.96 C55.7 -0.63, 110.34 -0.15, 158.32 0.47 M158.3 1.04 C156.94 9.49, 155.84 22.86, 156.21 40.26 M158.44 -0.07 C158.56 16.59, 158.08 32.94, 157.17 41.48 M158.51 43.29 C110.45 44.2, 61.56 40.62, 1.69 41.78 M158.32 42.99 C126.31 42.12, 92.2 42.27, -0.13 42.16 M1.3 41.06 C-1.87 30.27, 0.98 22.96, -1.86 -1.4 M-0.37 41.72 C0.14 29.35, 0.7 19.29, 0.61 0.72" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1458.537102593316 461.9185082409751) rotate(0 12 9.5)"><text x="12" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g transform="translate(732.5855178833008 145.59075335138093) rotate(0 85.5 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#e67700" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance</text></g><g stroke-linecap="round" transform="translate(730.1668548583984 180.4407457219863) rotate(0 105.33334350585938 157.16667175292972)"><path d="M1.49 -0.19 C78.81 1.19, 160.77 2.37, 212.41 1.49 M-0.11 0.14 C68.23 -0.23, 137.55 -0.2, 210.25 -0.71 M209.35 -0.99 C211.76 64.74, 211.35 127.64, 210.26 314.81 M211.1 0.51 C213.29 64.85, 212.24 131.41, 210.16 314.22 M210.26 314.59 C161.36 315.45, 116.62 316.54, -0.79 314.33 M211.23 314.18 C151.91 315.67, 91.49 316.18, -0.8 313.72 M-0.54 313.23 C-0.24 203.28, 0.91 89.96, -1.18 1.39 M-0.34 314.97 C-0.31 233.14, -1.09 153.77, -0.44 -0.31" stroke="#d9480f" stroke-width="4" fill="none"></path></g><g stroke-linecap="round" transform="translate(753.16650390625 424.940913568666) rotate(0 87.33334350585938 15.83331298828125)"><path d="M0.64 1.97 C37.66 0.7, 70.48 1, 174.41 0.32 M0.65 -0.47 C39.98 -0.79, 82.18 0.46, 173.74 -0.7 M173.93 -0.57 C175.48 7.01, 176.6 19.21, 175.88 33.1 M175.31 -0.71 C174.23 11.54, 173.83 25.32, 174.43 31.81 M175.57 30.77 C139.65 32.36, 104.63 33.99, 1.28 31.31 M175.41 30.76 C104.34 32.35, 34.98 32.2, -0.38 30.89 M-1.65 30 C1.83 23.92, 0.71 16.03, -0.96 1.81 M0.85 31.05 C-0.17 20.33, -0.15 7.9, -0.71 0.56" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(758.4998168945312 432.60757006280664) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.11 10.59 C2.95 8.97, 5.09 6.5, 7 3.95 M1.72 10.63 C3.58 8.93, 5.52 6.08, 8.01 3.7 M4.72 14.75 C5.94 12.76, 8.12 11.13, 9.68 7.52 M4.62 13.81 C5.69 12.42, 7.15 10.66, 10.3 7.24" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M7 0.86 C7.5 1.63, 8.89 4.62, 10.83 8.33 M5.76 -0.41 C7.19 3.54, 9.51 6.01, 10.31 8.9 M10.39 9.33 C8.11 12.86, 8.14 15.58, 6.71 18.53 M10.32 8.92 C9.26 10.6, 9.01 12.59, 6.07 17.18 M5.53 17.66 C4.07 15.23, 3.22 13.45, -0.19 10.04 M5.52 17.3 C4.39 14.75, 2.42 12.04, -0.41 8.56 M-0.9 10.06 C1.56 6.45, 3.04 2.44, 6.98 0.94 M-0.33 8.76 C1.8 6.8, 2.98 4.72, 6.3 -0.22" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(778.4998474121094 429.440913568666) rotate(0 57.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_tables</text></g><g stroke-linecap="round" transform="translate(745.5002593994141 359.30750902765044) rotate(0 87.33334350585938 15.83331298828125)"><path d="M1.24 1.37 C36.92 -2.97, 72.9 -2.41, 174.47 0.7 M0.15 -0.53 C36.64 1.72, 74.19 1.27, 174.32 0.1 M174.02 -1.53 C175.02 10.09, 174.21 20.2, 174.35 32.17 M174.12 -0.29 C175.57 12.02, 174.16 25.09, 173.81 31.45 M175.77 31.97 C112.93 34.15, 50.89 31.71, 0.13 31.15 M173.67 31.36 C123.33 32.6, 72.15 33.67, -0.5 30.8 M0.97 30.81 C-1.75 20.18, -2.11 7.89, -0.49 -1.14 M0.71 30.92 C-0.64 20.49, 0.04 7.96, 0.09 0.36" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(750.8335723876953 366.97416552179106) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.06 11.33 C3.87 8.86, 5.28 7.59, 7.02 3.44 M1.76 11.15 C3.91 8.57, 5.65 6.33, 7.53 3.85 M4.24 14.04 C5.36 12.8, 7.18 10.55, 10.7 7.61 M4.39 14.69 C6.4 11.52, 8.87 9.28, 9.96 7.78" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.7 -0.11 C6.48 1.73, 8.04 4.79, 11.02 8.12 M5.73 -0.31 C7.18 2.2, 8.17 4.54, 10.72 9.23 M9.91 9.2 C8.86 11.24, 7.14 13.73, 6.25 18.52 M10.52 9.33 C8.79 11.84, 7.45 15, 5.89 17.95 M6.16 18.14 C4.86 15.77, 1.7 12.36, -0.27 8.94 M5.84 17.7 C3.72 15.08, 2.44 12, -0.46 9.35 M-0.46 8.14 C2.23 4.77, 3.97 2.42, 5.38 0.85 M-0.4 8.69 C2.35 6.12, 4 3.21, 6.2 -0.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(764.8335418701172 365.1408220159317) rotate(0 65.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_memories</text></g><g stroke-linecap="round" transform="translate(752.1667938232422 189.3074785100723) rotate(0 87.33334350585938 15.83331298828125)"><path d="M0.6 1.9 C49.4 -1.37, 97.77 -0.55, 173.63 1.67 M-0.12 -0.51 C38.36 0.93, 77.07 1.86, 173.94 0.46 M176.26 -1.16 C176.14 6.14, 172.77 11.98, 175.38 30.01 M174.74 -0.18 C174.13 6.56, 174.12 12.78, 174.05 32.65 M174.24 31.96 C130.47 30.16, 86.56 31.59, 1.5 33.01 M174.72 31.13 C136.55 33.49, 96.85 34.04, 0.42 32.07 M-0.68 33.47 C-0.25 20.29, 1.13 14.33, 0.49 -0.55 M-0.17 32.65 C0.92 22.5, -0.2 13.91, 0.54 -0.93" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(757.5001068115234 196.9741350042129) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.89 11.28 C3.51 9.66, 4.27 7.56, 7.22 3.37 M1.73 10.86 C3.67 8.19, 5.62 6.03, 8.15 3.72 M3.45 14.22 C6.22 13.23, 6.51 11.3, 9.98 7.2 M4.56 14.47 C5.86 12.58, 6.68 11.06, 10.13 7.15" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.96 0.23 C6.56 2.72, 8.43 5.05, 11.51 8.2 M5.74 -0.17 C7.21 2.78, 9.2 5.51, 10.9 8.55 M10.1 9.86 C9.44 10.08, 8.01 13.08, 5.19 16.78 M10.58 8.76 C9.37 11.2, 7.85 13.56, 6.48 17.45 M6.16 17.93 C3.63 15.71, 2.56 13.19, 0.71 8.18 M5.72 17.99 C3.95 14.53, 2.18 11.97, 0.22 8.99 M0.98 8.96 C1.04 6.53, 5.04 2.91, 5.7 -0.05 M0.53 9.38 C1.49 6.71, 3.29 5.15, 5.5 -0.45" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(777.5001373291016 193.8074785100723) rotate(0 59 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_globals</text></g><g stroke-linecap="round" transform="translate(752.8335418701172 271.30750902765044) rotate(0 87.33334350585938 15.83331298828125)"><path d="M0.01 -0.35 C49.56 2.61, 95.56 0.38, 176.61 1.07 M0.83 -0.76 C35.85 -0.07, 71.32 0.69, 174.85 -0.59 M172.88 -0.19 C173.44 13.9, 175.22 24.19, 175.43 30.43 M173.99 -0.9 C174.44 11.02, 174.54 21.63, 174.01 31.73 M173.83 30.84 C132.04 32.24, 89.53 30.46, -1.04 30.35 M173.83 31.45 C105.72 30.84, 38.96 31.64, -0.85 32.22 M-0.07 31.94 C1.68 23.61, 1.48 13.01, -0.88 -0.5 M0.9 30.82 C-0.65 22.89, -0.06 12.39, -0.22 0.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(758.1668548583984 278.97416552179106) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.06 10.76 C3.94 9.54, 5.5 7.93, 8.02 4.89 M2.03 10.45 C4.03 7.96, 6.43 5.74, 7.56 4.52 M5.08 14.82 C5.38 12.27, 6.49 10.95, 9.96 7.2 M4.2 14.61 C6.09 11.65, 7.77 9.74, 10.36 7.76" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.82 1 C8.03 2.85, 8.27 6.31, 11.21 8.06 M5.62 -0.15 C6.95 1.42, 8.35 3.97, 10.37 9.48 M10.58 8.47 C10.22 11.49, 7.96 13.7, 5.39 18 M10.22 9.03 C9.85 10.88, 8.88 12.33, 6.03 17.38 M5.57 17.41 C4.6 15.27, 2.34 13.27, -0.7 9.95 M5.89 17.22 C4.71 15.99, 3.83 13.39, 0.29 8.92 M0.15 9.86 C2.21 7.32, 2.99 3.66, 5.73 0.04 M-0.46 8.53 C1.85 6.72, 2.77 4.68, 6.03 0.48" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(778.1668853759766 275.80750902765044) rotate(0 68 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_functions</text></g><g transform="translate(438.8334197998047 192.6407609807754) rotate(0 96.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMExportFuncInstance</text></g><g stroke-linecap="round" transform="translate(449.8334197998047 223.3074785100723) rotate(0 88.66665649414061 60.500030517578125)"><path d="M-0.41 1.89 C62.67 1.94, 125.66 1.78, 177.25 0.96 M-0.96 -0.09 C51.96 -0.44, 105.71 -0.75, 176.96 -0.75 M176.85 -1.12 C178.33 48.82, 178.22 96.76, 179.12 122.62 M178.11 -0.93 C178.21 40.92, 177.31 79.67, 177.86 121.66 M177.46 119.89 C133.37 123.72, 84.81 121.05, -1.33 121.43 M176.39 120.79 C127.43 120.17, 75.76 121.41, 0.87 120.62 M0.93 120.34 C-0.86 95.09, -0.23 71.96, -1.28 1.81 M0.92 121.27 C0.22 86.63, 0.03 53.4, 0.77 -0.78" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(463.50010681152344 239.30741747491604) rotate(0 58.5 15.5)"><path d="M1.89 -1.11 C46.15 -1.66, 91.23 0.16, 117.96 -0.04 M-0.09 -0.86 C24.95 1.19, 48.76 0.76, 116.25 0.93 M115.88 0.05 C118.09 11.67, 118.46 25.23, 118.62 31.64 M116.07 0.08 C117.86 10.54, 116.42 23.25, 117.66 30.57 M115.89 32.56 C83.43 29.6, 46.09 29.75, 0.43 30.71 M116.79 31.72 C90.05 29.55, 65.23 30.76, -0.38 30.06 M-0.66 29.08 C-0.96 23.13, 0.78 16.56, 1.81 -0.34 M0.27 30.5 C-0.33 22.86, 0.67 16.88, -0.78 -0.22" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(469.50010681152344 244.30741747491604) rotate(0 52.5 10.5)"><text x="52.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">char* name </text></g><g stroke-linecap="round" transform="translate(481.16676330566406 283.64076098077544) rotate(0 7.3333282470703125 8.833328247070312)"><path d="M8.51 -1.06 C10.36 2.51, 12.35 5.04, 13.62 9.8 M8.46 0.03 C9.64 1.68, 10.28 4.24, 15.1 8.72 M15.35 8.97 C13.66 12.37, 11.82 14.14, 8.73 18.07 M15.07 8.55 C11.69 12.56, 9.91 15.32, 7.98 18.16 M8.65 16.79 C4.68 14.29, 3.39 12.24, -0.91 9.04 M7.47 17.47 C6.58 16.46, 4.51 13.61, -0.52 8.87 M-0.62 8.22 C3.23 5.19, 6.67 2.64, 7.28 0.8 M-0.08 8.58 C3.64 5.98, 5.78 1.85, 8.41 -0.14" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(465.8334197998047 275.9740739690567) rotate(0 64 19)"><path d="M-1.9 0.74 C50.43 0.39, 100.97 -2.45, 129.42 -1.93 M0.06 0.52 C36.92 -1.81, 75.52 -0.27, 127.5 -0.24 M127.94 1.61 C129.8 10.9, 128.65 19.89, 128.73 39.56 M127.17 -0.69 C128.55 8.52, 127.6 15.69, 128.91 38.07 M126.52 36.44 C95.36 39.14, 65.1 37.16, 0.07 36.1 M127.66 38.35 C93.12 36.48, 55.54 35.98, -0.21 38.46 M-1.3 38.72 C-0.91 29.67, 0.02 16.52, 1.34 1.84 M-0.69 38.88 C0.96 24.79, -0.03 13.82, -0.23 -0.72" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(498.3334197998047 284.9740739690567) rotate(0 31.5 10.5)"><text x="31.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">function</text></g><g stroke-linecap="round"><g transform="translate(483.8334197998047 292.9740739690567) rotate(0 -55.467186777966646 91.99187592595712)"><path d="M0.44 -0.05 C-18.05 5.67, -104.28 2.28, -110.42 33.14 C-116.56 64, -48.72 159.93, -36.39 185.1 M-0.78 -1.12 C-19.43 4.9, -105.52 3.94, -111.07 34.67 C-116.62 65.39, -46.46 158.12, -34.08 183.21" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(483.8334197998047 292.9740739690567) rotate(0 -55.467186777966646 91.99187592595712)"><path d="M-57.73 165.61 C-49.74 169.09, -40.14 175.44, -34.26 181.48 M-58.03 163.89 C-47.7 172.4, -40.12 178.48, -34.64 183.23" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(483.8334197998047 292.9740739690567) rotate(0 -55.467186777966646 91.99187592595712)"><path d="M-40.29 154.8 C-38.42 162.08, -34.84 172.16, -34.26 181.48 M-40.58 153.09 C-36.92 165.82, -36.01 176.03, -34.64 183.23" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1300.6854010687935 70.78894077678237) rotate(0 117.5 74.5)"><text x="0" y="14.625" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">name: shown to external</text><text x="0" y="33.25" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">index: refer to item idx for export </text><text x="0" y="51.875" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> in current kind</text><text x="0" y="70.5" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">kind: total 4 export kinds:</text><text x="0" y="89.125" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">- function</text><text x="0" y="107.75" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">- globals</text><text x="0" y="126.375" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">- memory</text><text x="0" y="145" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">- table</text></g><g stroke-linecap="round" transform="translate(450.8334045410156 343.4741197454239) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.64 6.96 C0.82 4.59, 1.44 3.77, 4.39 1.01 M0.11 6.5 C1.08 4.98, 1.89 3.79, 5.37 0.17 M1.04 11.49 C4.19 7.88, 4.79 5.6, 9.29 -0.28 M0.51 11.89 C3.54 7.22, 8.11 2.17, 11.35 0.09 M-2.12 19.77 C2.96 13.81, 7.38 8.86, 14.63 -1.52 M-0.18 18.95 C3.59 12.79, 9.11 8.92, 15.36 1.09 M-0.86 22.87 C4.46 18.87, 11.12 11.34, 19.76 1.42 M0.25 23.46 C5.13 17.63, 9.6 13.34, 21.9 -0.93 M-0.58 31.13 C8.83 16.98, 19.31 7.61, 25.35 1.18 M-0.77 30.08 C6.26 24.37, 12.27 16.14, 26.56 0.53 M0.58 33.95 C10.22 24.31, 21.8 12.71, 33.83 -1.32 M3.01 34.61 C8.18 26.23, 14.43 18.69, 32.25 -0.76 M6.52 33.25 C16.6 25.21, 24.88 13.93, 36.32 -0.3 M8.16 34.23 C16.76 23.29, 25.33 12.94, 36.34 0.59 M12.96 32.54 C21.48 21.92, 31.62 15.14, 44.25 1.38 M13.15 34.2 C22.32 23, 33.24 12.11, 43.26 0.72 M16.46 34.48 C28.28 23.18, 34.79 16.38, 48.58 0.83 M18.28 34.08 C29.41 20.95, 39.78 8.81, 47.52 0.82 M24.89 33.12 C35.91 22.42, 47.52 9.46, 51.47 1.64 M23.92 33.67 C32.61 24.78, 40.46 14.72, 52.21 0.27 M30.55 32.58 C35.82 28.16, 43.41 20.61, 57.48 -1.51 M28.52 34.25 C36.1 24.52, 44.52 15.41, 58.05 0.95 M35.22 36.25 C42.64 22.55, 52.72 13.6, 65.27 -0.29 M33.54 33.56 C44.34 21.42, 57.83 7.53, 63.94 0.35 M38.68 33.69 C45.25 24.21, 55.98 17.15, 70.75 -0.21 M38.67 33.23 C46.76 24.77, 55.05 15.51, 67.94 -0.11 M45.1 33.39 C55.52 19.47, 68.13 6.52, 74.8 -1.98 M44.26 35.32 C53.48 22.67, 63.25 10.66, 73.86 0.07 M50.12 34.11 C57.54 23.2, 68 13.84, 78.43 -1.02 M49.09 34.21 C56.88 24.9, 65.16 15.47, 80.26 0.72 M56.04 33.42 C62.6 26.99, 68.19 19.74, 86.52 -0.85 M55.46 34.86 C64.19 23.35, 74.47 13.25, 84.98 0.2 M59.47 34.29 C67.2 27.13, 74.79 18.77, 90.93 -0.54 M59.7 34.02 C71.61 21.66, 81.64 8.67, 90.18 -0.33 M66.56 33.63 C73.98 21.65, 87.09 9.49, 94.25 -0.16 M65.23 34.47 C76.37 20.95, 88.74 8.15, 94.88 0.21 M72.67 32.85 C79.43 25.4, 87.4 16.61, 100.98 -0.21 M71.03 34.19 C80.36 24.81, 88.31 14.66, 99.95 -0.84 M77.54 34.45 C85.21 23.42, 97.04 7.17, 105.17 0.97 M76.75 34.64 C84.69 24.78, 93.1 16.35, 106.71 -0.77 M81.02 32.54 C89.82 27.14, 93.77 19.46, 109.67 -0.3 M81.18 33.91 C88.71 26.66, 94.45 20.22, 111.89 0.79 M86.19 33.47 C93.19 26.64, 99.22 17.32, 117.11 2.35 M87.29 35.01 C97 22.6, 107.63 10.63, 115.56 -0.19 M91.13 34.3 C99.32 24.9, 104.2 15.99, 120.43 -1.94 M92.81 33.04 C98.31 25.16, 105.92 17.33, 121.39 0.32 M96.06 35.45 C106.18 20.69, 117.37 10.15, 127.25 1.67 M97.18 33.42 C106.6 23.67, 113.47 14.66, 126.04 -0.09 M103 35.19 C115.76 21.94, 126.15 7.7, 133.02 -1.1 M102.17 33.12 C113.97 21.79, 125.34 8.55, 131.94 0.67 M107.04 34.29 C118.93 24.8, 129.14 10.19, 138.12 1.04 M108.83 34.86 C119.32 21.66, 131.57 8.55, 137.39 0.43 M111.94 34.46 C124.68 19.53, 134.25 10.44, 141.58 1.41 M114.09 34.35 C120.76 26.07, 126.29 19.66, 144.08 -1.04 M117.38 35.05 C130.32 20.55, 140.95 8.71, 146.27 1.99 M117.74 34.5 C126.34 25.41, 135.75 15.12, 149.08 1.19 M122.61 35.5 C134.9 20.09, 146.33 6.95, 152.56 -2.06 M124.98 34.62 C135.64 21.45, 147.26 8.64, 154.44 -0.55 M129.67 35.97 C137.6 25.53, 141.56 19, 159.56 0.19 M129.47 34.67 C139.72 20.66, 152.32 8.79, 159.17 0.68 M135.03 31.85 C142.95 25.8, 149.45 16.06, 162.76 -0.02 M135.83 34.47 C142.23 25.22, 150.49 15.67, 164.75 0.61 M140.83 34.4 C151.96 21.14, 162.05 6.82, 171.23 -0.55 M140.68 33.9 C147.51 24.73, 155.03 16.07, 169.26 1.05 M145.87 33.97 C152.14 24.59, 161.53 15.89, 173.33 0.19 M144.53 34.88 C156.28 21.89, 165.63 10.13, 174.79 0.05 M152.13 32.88 C159.88 24.03, 167.04 15.57, 181.86 1.78 M150.09 33.85 C157.94 27.01, 165.42 18.27, 179.57 1.15 M157.17 36.21 C161.86 24.48, 171.72 15.63, 177.86 5.17 M155.55 35.23 C162.21 25.41, 169.4 18.49, 179.53 6.36 M159.2 33.11 C165.19 29.24, 171.65 21.72, 178.85 13.38 M161.51 34.39 C165.69 27.62, 170.06 23.4, 179.38 11.54 M166.28 35.35 C170.42 31.87, 173.67 25.2, 181.5 18.4 M166.95 34.85 C171.42 27.7, 176.44 23, 179.21 18.98 M170.62 33.97 C175.47 30.24, 175.95 29.01, 181.38 23.1 M171.16 34.37 C175.19 30.75, 178.11 26.07, 179.82 23.65 M177.24 34.2 C177.69 33.12, 179.33 31.55, 179.8 30.66 M176.59 34.56 C177.86 33.42, 178.29 32.2, 180.16 30.43" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M0.7 0.18 C44.18 0.19, 92.18 -0.84, 178.43 -1.98 M-0.23 0.03 C62.62 -0.73, 126.88 -1.86, 180.34 0.59 M179.72 1.77 C180.8 10.79, 180.2 20.9, 179.25 30.73 M179.3 0.65 C180.34 8.59, 180.4 18.98, 180.03 32.36 M181 33.95 C136.37 33.25, 89.68 32.21, 0.03 33.85 M180.37 32.49 C126.54 31.37, 70.7 32.4, -0.51 33.13 M-1.98 31.66 C2.02 22.41, -0.55 10.57, -0.75 0.8 M0.66 31.35 C0.09 23.8, 0.42 13.67, 0.25 0.29" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(529.8334045410156 349.64079149835356) rotate(0 11 10.5)"><text x="11" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[1]</text></g><g transform="translate(526.0000305175781 323.8075242864395) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(451.1666564941406 376.9741960393692) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.5 5.68 C1.47 4.06, 3.37 3.19, 4.66 1.14 M-0.63 6.66 C1.34 4.68, 2.2 3.07, 4.94 0.5 M0.37 11.37 C1.84 10.11, 5.39 7.4, 9.4 -0.48 M-0.12 12.68 C2.98 8.79, 5.47 5.01, 10.44 -0.47 M-0.14 18.4 C3.83 11.93, 8.6 7.22, 17.22 2.05 M-0.28 18.59 C6.12 11.25, 11.85 5.75, 15.97 1.07 M-0.17 22.56 C8.7 16.82, 14.88 5.82, 22.27 1 M-0.07 24.38 C6.9 16.23, 13.57 7.35, 21.72 -0.05 M-1.09 31.74 C8.54 20.82, 19.8 10.55, 27.12 -1.39 M-0.13 30.77 C10.16 19.18, 21.28 6.72, 26.74 -0.65 M1.56 35.79 C11.22 22.66, 24.58 11.84, 33.67 -0.76 M2.33 33.77 C8.92 26.07, 14.73 19.18, 31.54 -0.19 M6.84 35.84 C20.24 21.69, 27.7 10.19, 36.15 1.75 M6.89 34.15 C14.82 23.1, 24.89 14.71, 37 0.41 M12.32 33.26 C23.23 20.19, 32.89 11.25, 42.9 1.85 M13.42 33.25 C20.52 23.57, 29.92 14.1, 42.86 -0.97 M17.2 35.05 C24.73 24.75, 31.93 16.61, 45.74 0.61 M17.93 34.21 C25.01 26.2, 30.14 18.73, 46.7 -0.33 M22.9 34.04 C33.4 21.09, 42.62 11.21, 53.72 -1.14 M22.74 33 C31.04 24.66, 37.7 16.8, 52.38 0.69 M28.34 35.32 C38.5 23.08, 50.2 9.88, 58.48 1.67 M28.46 34.74 C36.98 24.7, 44.49 16.15, 59.02 0.13 M33.11 33.47 C44.59 22.32, 55.66 11.04, 64.05 0.69 M32.83 33.71 C41.43 25.32, 49.6 15.02, 63.46 -0.05 M40.06 35.19 C45.93 23.37, 53.79 17.2, 68.14 -1.26 M39.91 33.85 C48.1 23.04, 57.13 13.44, 69.26 -0.64 M43.89 36.01 C53.77 22.24, 66.42 9.72, 75.98 0.08 M44.39 34.37 C53.1 25.06, 62.45 14.33, 75.14 -0.94 M48.32 35.5 C55.95 24.86, 63.75 18.36, 77.61 -1.01 M49.38 34.71 C61.04 22.13, 71.18 9.99, 79.94 0.53 M55.37 33.69 C61.47 26.97, 71.48 15.41, 85.73 -1.9 M55.34 33.85 C63.72 25.56, 72.04 15.47, 85.12 0.33 M59.22 33.48 C71 20.68, 83.2 6.86, 88.97 0.92 M60.62 34.59 C72.8 20.61, 83.86 7.55, 89.71 -0.64 M67.49 33.14 C73.43 26.07, 79.51 15.68, 93.7 -1.8 M66.39 34.82 C71 26.55, 77.27 20.36, 94.78 -0.84 M71.04 32.68 C81.9 20.66, 89.44 9.69, 101.41 0.4 M71.1 33.81 C81.12 22.36, 91.87 8.35, 100.41 -0.82 M77.33 34.35 C84.86 26.84, 92.61 16.94, 106.44 0.13 M75.45 33.51 C82.56 25.69, 91.22 17.41, 106.17 -0.96 M80.19 33 C92.67 22.55, 105.13 10.4, 109.34 0.6 M80.91 34.8 C91.99 22.2, 101.85 11.39, 112.06 -0.13 M85.16 32.62 C96.32 23.69, 103.06 11.61, 118 -1.22 M86.6 34.77 C98.61 22.46, 108.52 9.01, 116.36 1.27 M91.26 32.68 C99.07 28.19, 102.45 21.43, 120.27 -1.92 M91.84 33.04 C104.12 20.18, 115.86 8.14, 121.84 0.9 M96.36 32.63 C110.3 20.04, 119.65 6.57, 126.53 -0.91 M97.08 35 C103.9 27.7, 109.36 21.36, 127.05 0.98 M102.97 34.3 C112.64 26.76, 117.57 15.21, 132.89 0.71 M102.36 34.11 C111.99 22.91, 119.64 14.04, 133.11 0.32 M107.52 34.38 C116.4 23.36, 128.8 10.91, 136.42 -1.37 M108.3 35.18 C117.84 23.27, 126.82 13.22, 137.66 0.62 M114.22 34.8 C124.68 21.33, 136.2 6.82, 143.05 1.72 M114.58 34.65 C121.3 25.21, 128.68 16.41, 142.38 -0.25 M120.35 35.22 C129.65 20.96, 140.41 9.86, 146.82 -1.47 M118.86 33.88 C128.2 23.91, 137.24 11.53, 148.92 0 M126.06 35.44 C132.72 24.25, 142.82 12.47, 153.74 1.68 M123.31 33.4 C135.42 21.06, 147.89 8.35, 154.37 -0.61 M127.72 35.85 C142.71 19.49, 151.2 8.3, 157.07 -1.7 M129.52 34.23 C136.84 25.94, 142.07 18.17, 159.24 -0.03 M135.69 31.84 C142.18 22.63, 153.12 13.96, 165.13 -1.5 M135.02 34.15 C145.94 21.28, 155.36 8.62, 164.94 -0.96 M139.67 34.3 C147.78 26.74, 155.41 18.38, 168.65 1.77 M140.21 34.96 C148.61 24.58, 155.89 14.68, 169.71 -0.51 M145.82 32.72 C154.92 24.35, 164.04 9.37, 176.53 1.44 M144.2 33.54 C151.47 27.4, 157.91 19.58, 174.13 -0.96 M149.38 35.96 C155.6 26.05, 162.66 20.92, 179.2 -0.88 M151.04 33.36 C160.16 24.66, 168.51 12.69, 179.08 0.57 M157.26 34.88 C159.81 29.41, 165.16 21.29, 178.5 7.89 M154.98 35.04 C163.95 23.83, 173.78 14.94, 179.26 6.13 M159.19 35.55 C163.83 28.19, 169.49 26.34, 182.03 12.94 M161.29 34.32 C167.63 27.61, 173.84 19.25, 180.27 11.4 M167.04 33.71 C171.23 27.12, 176.3 25.61, 179.98 18.3 M166.19 34.42 C170.55 29.95, 175.66 23.64, 179.02 19.31 M171.03 34.77 C175.23 30.08, 177.62 26.41, 179.84 24.1 M172.18 33.55 C174.08 31.83, 175.79 30.51, 180.68 24.78 M176.83 34.37 C178.39 33.19, 178.73 31.72, 179.63 30.65 M176.83 34.27 C177.64 33.38, 178.9 32.08, 180.19 30.84" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M0.36 -0.95 C54.66 0.85, 105.48 -0.58, 180.33 -1.49 M0.42 0.92 C68.78 0.12, 137.02 -0.87, 180.48 0.95 M178.67 1.14 C179.16 9.86, 178.4 15.43, 179.52 30.65 M180.99 0.46 C180.1 8.46, 180.26 18.27, 179.54 33.23 M181.96 30.34 C124.5 32.47, 65.75 33.52, -1.66 31.35 M180 32.28 C143.13 33.26, 104.41 34.59, 0.11 32.07 M1.96 31.2 C-1.12 18.71, 1.6 7.54, 0.48 -1.5 M0.81 32.32 C-0.39 20.36, -0.55 7.93, 0.42 0.64" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(525.6666564941406 383.1408677922989) rotate(0 15.5 10.5)"><text x="15.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round" transform="translate(451.8334655761719 407.97425707452544) rotate(0 90 15.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.33 5.61 C1.12 4.78, 3.1 2.56, 5.45 0.96 M-0.31 6.54 C1.54 4.39, 3.35 2.43, 5.29 0.32 M-1.03 12.75 C3.27 9.32, 6.33 4.06, 11.92 1.19 M-0.1 12.68 C4.22 7.36, 8.42 2.54, 10.27 0.11 M-0.29 19.43 C3.54 15.14, 9.97 9.13, 13.71 2.01 M0.8 19.07 C3.42 13.61, 7.08 8.01, 16.01 1.09 M-0.6 26.04 C6.09 15.87, 12.9 7.65, 19.98 1.83 M0.04 23.96 C7.15 15.84, 12.54 8, 21.45 -0.67 M1.58 30.93 C8.24 21.33, 16.71 10.31, 24.27 1.4 M0.32 30.77 C5.44 24.35, 11.89 17.28, 25.93 -0.61 M3.18 31.79 C8.81 25.97, 15.91 16.78, 31.37 -0.39 M2.69 32.71 C11.77 21.57, 22.27 10.46, 31.5 -0.7 M6.36 32.27 C13.89 27.06, 19.59 19.45, 36.93 0.26 M8.2 34.32 C16.77 23.6, 26.5 12.49, 36.8 0.94 M12.25 32.46 C24.38 19.01, 36.32 6.96, 43.34 0.46 M14.38 33.73 C21.78 21.94, 31.58 12.67, 42.55 -0.76 M19.6 35.26 C27.15 25.71, 33.3 14.04, 46.96 1.13 M19.46 33.88 C27.3 24.22, 34.45 15.06, 47.53 0.55 M23.88 31.81 C34.3 22.81, 43.57 9.48, 53.99 -0.64 M24.23 33.86 C35.32 20.41, 46.25 8.74, 54.01 -0.12 M30.66 34 C38.71 22.69, 51.1 6.94, 59.77 -1.09 M28.97 34.16 C35.04 26.84, 41.89 19.9, 57.75 1.16 M32.71 33.6 C45.08 21.11, 53.59 11.28, 64.58 -1.38 M33.27 33.71 C44.89 21.85, 54.22 12.05, 63.45 0.56 M38.65 34.95 C47.3 22.36, 56.6 12.39, 68.96 -1.15 M40.34 33.41 C47.01 25.42, 54.69 16.8, 68.74 0.75 M43.51 33.69 C55.04 23.53, 61.31 15.79, 73.51 -2.09 M44.16 34.69 C52 27.56, 56.15 19.83, 73.62 0.18 M51.87 33.89 C56.69 24.91, 64.01 17.3, 78.24 -1.47 M50.39 33.49 C60.19 21.71, 69.1 11.54, 78.46 -0.61 M57.22 34.55 C65.15 24.44, 73.36 16.62, 86.34 0.25 M56.26 34.58 C63.84 22.55, 72.78 13.17, 85.44 0.24 M61.74 33.96 C68.07 22.58, 77.94 15.34, 91.51 1.89 M62.1 32.81 C66.05 27.28, 73.35 19.26, 90.54 0.23 M67.62 32.23 C75.74 19.08, 89.07 7.74, 93.79 -2.03 M65.26 33.45 C77.66 20.75, 89.69 8.01, 94.99 -0.22 M72.87 31.63 C79.26 22.03, 90.12 14, 98.82 1.18 M71.62 33.38 C77.83 24.89, 84.92 17.96, 101.27 0.5 M78.63 35.12 C84.08 21.74, 95.39 12.76, 105.73 -1.23 M77.52 33.47 C84.99 25.04, 94.39 15.04, 106.54 0.47 M81 34.72 C91.24 23.29, 102.15 14.27, 110.38 -0.96 M83.27 33.77 C90.77 22.91, 101.07 11.45, 110.63 0.51 M86.33 33.98 C97.07 21.75, 105.87 10.66, 116.55 0.46 M87.08 33.88 C95.02 26.37, 102.45 16.86, 116.86 0.25 M95.04 32.4 C102.54 23.51, 111.22 12.35, 122.54 -1.59 M92.56 34.15 C102.14 24.33, 109.42 14.35, 121.27 0.63 M96.94 31.88 C106.17 26.97, 110.27 18.23, 125.75 1.89 M98.65 34.01 C105.26 25.41, 112.12 18.68, 126.88 -0.56 M103.05 33.17 C116.39 22.21, 124.21 9.56, 131.82 0.61 M103.14 33.23 C110.97 22.63, 120.23 13.39, 133.5 0.33 M108.87 34.26 C117.56 23.05, 131.12 8.49, 136 1.55 M108.6 34.25 C115.41 26.65, 122.07 19.3, 136.71 0.14 M114.25 34.88 C125.13 19.76, 133.32 8.84, 144.89 -0.71 M113.86 33.35 C124.3 22.18, 134.15 10.44, 142.31 -0.86 M118.66 34.89 C129.44 22.18, 140.67 11.11, 149.81 0.51 M119.99 33.07 C126.89 25.63, 134.52 16.29, 147.3 0.33 M125.02 34.73 C135.59 20.26, 144 12.95, 152.58 -1.58 M125.74 33.38 C134.76 19.97, 146.69 8.86, 154.35 -0.31 M131.01 33.88 C134.99 28.68, 141.24 19.03, 158.85 1.19 M129.53 34.04 C138.04 24.12, 145.52 17.32, 158.77 -0.47 M136.89 31.26 C143.01 26.98, 146.39 20.55, 163.88 -1.64 M134.94 33.81 C141.61 25.6, 148.42 16.86, 164.96 0.67 M140.79 31.7 C145.86 26.94, 153.71 15.74, 169.91 1.34 M140.63 32.79 C151.88 20.51, 163.2 7.98, 169.42 -0.16 M145.89 35.1 C155.81 22.46, 164.45 10.86, 175.92 1.78 M145.17 34.42 C154.58 23.33, 163.14 14.05, 175.15 -0.14 M151.01 35.14 C155.83 27.26, 163.32 18.98, 178.97 0.06 M150.34 34.02 C159.41 24.13, 167.1 15.93, 180.7 0.96 M155.18 31.97 C164.57 23.72, 174.43 14.64, 178.1 6.49 M155.28 34.33 C161.45 27.33, 165.88 22.31, 180.68 5.89 M162.83 31.37 C167.99 26.15, 174.84 16.76, 178.67 11.87 M162.41 32.53 C169.14 24.46, 174.99 16.92, 179.77 11.23 M165.1 33.2 C170.64 28.23, 173.61 23.11, 179.19 20.35 M166.3 33.51 C171.36 27.25, 177.29 23.43, 180.22 18.18 M173.14 33.64 C174.54 31.09, 178.81 27.86, 179.99 24.4 M172.32 33.83 C174.8 31.01, 176.54 28.84, 180.08 24.35 M177.51 33.87 C178.23 32.89, 179.53 31.75, 180.33 30.88 M177.37 33.48 C178.09 33.05, 178.51 32.5, 180.12 30.61" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M1.87 1.37 C60.01 0.96, 123.92 0.25, 178.16 -1.13 M-0.73 -0.38 C59.28 -1.57, 119.56 -0.63, 180.57 0.21 M180.01 0.61 C179.49 5.04, 180.19 12.75, 180.57 32.79 M179.25 0.74 C179.37 8.68, 181.05 15.48, 179.76 30 M179.51 31.07 C128.59 28.98, 75.61 30.95, 0.38 32.28 M180.11 30.17 C139.57 31.3, 99.78 30.44, -0.46 30.32 M-0.02 29.47 C0.15 22.39, -1.11 13.27, -1.76 0.72 M0.26 30.52 C-0.42 19.36, 0.11 6.97, 0.19 0.86" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(529.3334655761719 417.97425707452544) rotate(0 12.5 10.5)"><text x="12.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[n]</text></g><g stroke-linecap="round"><g transform="translate(973.1669311523438 20.863758858108355) rotate(0 1.1454355564646477 418.47457523718464)"><path d="M0.45 -0.66 C1.4 286.58, 2.58 571.88, 1.22 837.61" stroke="#000000" stroke-width="4.5" fill="none" stroke-dasharray="1.5 10"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(763.5001068115234 278.02590276007174) rotate(0 -65.8816224112011 -26.85459209832011)"><path d="M1.68 -0.68 C-50.77 -21.8, -101.06 -42.9, -133.45 -53.78 M0.28 0.81 C-26.88 -11.6, -53.21 -23.06, -133.44 -54.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(763.5001068115234 278.02590276007174) rotate(0 -65.8816224112011 -26.85459209832011)"><path d="M-101.77 -54.33 C-115.8 -55.04, -127.13 -55.82, -133.87 -53.71 M-103.17 -52.84 C-109.46 -54.35, -114.95 -54.95, -133.87 -54.44" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(763.5001068115234 278.02590276007174) rotate(0 -65.8816224112011 -26.85459209832011)"><path d="M-109.34 -35.26 C-120.32 -43.17, -128.79 -51.17, -133.87 -53.71 M-110.74 -33.77 C-115.51 -39.13, -119.47 -43.59, -133.87 -54.44" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(442.1667785644531 477.8076005803848) rotate(0 111.66673278808595 16.500076293945284)"><path d="M0.19 0.79 C65.62 -0.82, 132.42 -1.39, 222.22 1.26 M0.3 -0.33 C71.93 1.03, 142.16 1.53, 223.15 -0.54 M223.57 1.93 C223.04 9.41, 224.4 20.82, 222.23 34.8 M224.15 0.4 C224.03 10.25, 223.82 19.89, 223.95 33.84 M224.55 31.61 C135.77 35.58, 46 33.82, 0.09 32.7 M223.77 32.47 C166.8 31.73, 109.97 33.19, -0.75 32.95 M-1.5 31.18 C-1.57 21.01, 0.57 10.79, -0.05 -1.29 M0.04 32.55 C0.49 21.89, -0.67 12.91, 0.42 -0.33" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(448.8334045410156 485.4741960393692) rotate(0 104 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(refer to function diagam)</text></g><g transform="translate(763.5001525878906 316.47401293390044) rotate(0 77 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_func_count</text></g><g stroke-linecap="round"><g transform="translate(752.8126237255627 333.47404345147856) rotate(0 -95.43072714479244 45.03858509230764)"><path d="M-1.05 -0.83 C-14.62 8.49, -50.24 40.2, -81.93 55.48 C-113.62 70.77, -173.01 84.99, -191.18 90.9 M0.6 1.35 C-13.08 10.37, -50.84 39.17, -82.85 53.79 C-114.86 68.41, -172.97 83.21, -191.46 89.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(752.8126237255627 333.47404345147856) rotate(0 -95.43072714479244 45.03858509230764)"><path d="M-168.65 71.43 C-172.2 77.24, -178.14 82.14, -189.65 88.1 M-166.9 71.62 C-175.14 76.42, -183.59 83.9, -191.75 89.04" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(752.8126237255627 333.47404345147856) rotate(0 -95.43072714479244 45.03858509230764)"><path d="M-162.91 91.13 C-167.87 91.82, -175.29 91.65, -189.65 88.1 M-161.16 91.33 C-171.42 89.1, -181.9 89.61, -191.75 89.04" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(753.5000915527344 310.80738695733794) rotate(0 86.3333740234375 15.833343505859375)"><path d="M1.7 0.48 C59.04 1.96, 116.59 3.11, 173.81 1.69 M-0.12 -0.35 C65.42 -0.77, 131.51 -0.79, 173.32 -0.4 M172.98 -1.26 C174.27 12.36, 171.88 24.13, 170.98 30.65 M173.29 0.03 C171.95 5.96, 171.9 12.54, 172.22 30.89 M170.74 32.26 C114.88 30.58, 61.41 29.08, -0.7 31.64 M171.89 31.11 C107.53 32.12, 43.99 31.99, 0.36 31.51 M0.75 32.92 C1.71 25.77, 1.94 17.25, 1.8 0.58 M0.03 31.17 C0.3 19.11, -0.63 7.42, 0.33 -0.39" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1288.3149074978296 65.01118334405675) rotate(0 143.85188462999133 81.14818912082251)"><path d="M1.29 -1.34 C76.66 0.94, 152.17 0.46, 287.94 0.62 M286.56 -0.85 C287.49 56.32, 286.87 113.44, 289.42 162.71 M288.17 161.21 C179.72 162.5, 75.07 164.32, 0.14 163.4 M0.31 162.86 C2.92 107.51, 0.32 52.92, -1.83 1.96" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g stroke-linecap="round"><g transform="translate(1547.7461809951221 224.5152236258764) rotate(0 -0.49546062400435176 26.05596998477685)"><path d="M0.86 -0.37 C2.51 4.05, 13.12 17.91, 10.94 26.72 C8.76 35.53, -8.34 47.88, -12.22 52.48" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(1547.7461809951221 224.5152236258764) rotate(0 -0.49546062400435176 26.05596998477685)"><path d="M-4.99 38.26 C-6.89 41.84, -11.59 47.57, -10.74 53.11" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(1547.7461809951221 224.5152236258764) rotate(0 -0.49546062400435176 26.05596998477685)"><path d="M3.09 46.84 C-1.95 47.18, -9.76 49.59, -10.74 53.11" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g transform="translate(98.83338928222656 113.05734118097072) rotate(0 96 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMExportGlobInstance</text></g><g stroke-linecap="round" transform="translate(109.83338928222656 143.7240587102676) rotate(0 88.66665649414062 60.500030517578125)"><path d="M-0.75 -0.95 C39.17 -2.52, 82.68 -0.76, 175.94 -1.5 M0.99 -0.97 C38.27 -0.77, 78.75 -0.52, 178.33 -0.46 M178.27 0.25 C178.37 29.4, 176.39 60.32, 176.09 119.25 M177.33 -0.94 C178.22 39.7, 176.6 79.54, 177.12 120.09 M177.98 122.7 C135.35 121.19, 88.77 118.81, -0.94 119.44 M177.99 121.58 C125.09 120.44, 71.17 120.17, 0.35 121.32 M1.55 120.23 C-0.27 93.21, 0.56 64.42, 1.75 -0.3 M-0.46 120.94 C0.8 96.67, -0.02 72.3, -0.42 -0.41" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(123.50007629394531 159.72399767511135) rotate(0 58.5 15.5)"><path d="M-0.95 -1.72 C31.08 1.35, 65.43 -0.96, 115.5 -1.6 M-0.97 -0.75 C43.8 -0.45, 87.57 -0.17, 116.54 -0.54 M117.25 0.14 C116.53 9.77, 117.72 21.96, 115.25 31.65 M116.06 0.98 C116.77 8.42, 116.38 17.92, 116.09 30.45 M118.7 32.46 C82.05 29.7, 43.45 30.44, -1.56 30.95 M117.58 31.48 C87.52 31.05, 58.3 32.11, 0.32 30.27 M-0.77 30.14 C-0.43 23.18, -1.78 17.17, -0.3 -1.92 M-0.06 31.24 C0.54 22.56, 0.82 14.87, -0.41 0.34" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(129.5000762939453 164.72399767511135) rotate(0 52.5 10.5)"><text x="52.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">char* name </text></g><g stroke-linecap="round" transform="translate(141.16673278808594 204.05734118097072) rotate(0 7.3333282470703125 8.833328247070312)"><path d="M7.15 0.51 C9.85 1.64, 10.62 3.89, 15.47 9.67 M8.16 0.4 C10.88 4.2, 12.98 6.94, 15.08 8.75 M14.49 8 C12.84 11.33, 9.1 15.37, 7.92 18.7 M14.38 8.65 C12.09 11.54, 10.1 13.95, 8.05 17.33 M8.75 16.67 C4.62 14.29, 1.69 11.93, -0.62 8.98 M7.69 17.24 C4.56 14.74, 2.29 10.94, -0.29 9.17 M-0.21 8.98 C2.04 6.69, 5.89 1.08, 7.44 -0.78 M0.2 8.65 C2.41 6.45, 3.82 4.62, 7.95 -0.18" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(125.83338928222656 196.39065416925197) rotate(0 64 19)"><path d="M0.91 0.25 C30.95 -0.53, 63.08 2.41, 129.2 1.99 M0.71 0.54 C27.01 -0.82, 51.5 0.38, 127.54 0.47 M126.16 0.87 C126.78 10.12, 128.68 23.6, 129.89 37.98 M127.35 -0.91 C128.16 6.93, 127.82 15.78, 127.39 38.33 M126.32 36.9 C77.8 37.26, 29.42 37.76, -0.04 39.31 M127.28 37.21 C82.54 37.65, 35.65 36.84, 0.28 38.77 M-0.03 36.31 C1.92 27.75, -1.76 17.18, -1.3 -0.92 M-0.58 38.62 C-0.51 26.42, 0.25 15.57, -0.29 0.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(166.83338928222656 205.39065416925197) rotate(0 23 10.5)"><text x="23" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">global</text></g><g stroke-linecap="round"><g transform="translate(143.83338928222656 213.39065416925197) rotate(0 -55.910267871840404 88.2789895329384)"><path d="M0.15 -0.84 C-18.35 4.44, -109.05 2.5, -111.9 32.21 C-114.75 61.91, -32.81 153.51, -16.93 177.4 M-1.23 1.34 C-19.27 6.69, -106.99 4.23, -109.66 33.24 C-112.33 62.26, -32.29 151.64, -17.24 175.43" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(143.83338928222656 213.39065416925197) rotate(0 -55.910267871840404 88.2789895329384)"><path d="M-43.85 157.67 C-38.32 164.23, -29.87 168.43, -19.17 173.93 M-41.46 158.72 C-34.6 165.12, -26.22 170.19, -17.12 175.5" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(143.83338928222656 213.39065416925197) rotate(0 -55.910267871840404 88.2789895329384)"><path d="M-27.5 145.27 C-25.58 154.63, -20.8 161.61, -19.17 173.93 M-25.11 146.31 C-23.53 156.88, -20.53 166.03, -17.12 175.5" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(110.8333740234375 263.8906999456192) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.26 6.3 C0.83 3.72, 3.7 2.96, 5.39 -0.28 M-0.24 6.05 C0.75 4.95, 2.08 3.44, 5.26 0.02 M-0.36 10.74 C2.92 10.21, 4.88 6.44, 10 0.76 M0.06 12.08 C3.47 7.86, 6.84 3.95, 10.09 0.75 M1.4 19.58 C7.11 10.38, 12.38 3.81, 17.24 1.88 M0.34 19.3 C4.65 12.71, 11.03 6.67, 14.65 0.62 M1.01 25.79 C9.52 14.14, 16.85 5.88, 21.34 1.48 M-0.51 23.79 C4.13 19.06, 9.1 12.92, 21.01 -0.89 M1.86 28.79 C5.64 24.79, 12.84 17.87, 27.54 1.24 M-0.71 31.14 C10.07 19.32, 19.11 8.72, 27.21 -0.46 M0.45 32.05 C12.3 24.15, 17.98 11.92, 33.34 0.6 M2.88 33.94 C10.3 26.09, 16.58 17.98, 31.82 0.79 M8.93 34.27 C13.48 27.22, 19.53 20.5, 35.61 -0.59 M7.17 34.08 C15.76 25.69, 22.86 16.81, 37.78 -0.16 M13.01 32.33 C21.8 23.06, 33.58 9.56, 42.41 -1.66 M13.3 33.52 C21.32 23.44, 31.35 14.4, 41.82 -1.01 M17.11 32.68 C31.4 22.08, 39.55 6.83, 48.34 1.33 M17.53 34.58 C26.68 24.59, 35 13.73, 48.5 0.19 M22.93 33.52 C34.95 22.46, 42.2 10.71, 54.28 0.04 M24.41 33.93 C30.55 26.35, 39.42 16.17, 53.6 0.27 M26.72 33.28 C39.89 20.49, 51.47 9.21, 58.78 0.28 M27.74 33.91 C39.96 21.25, 51.06 7.6, 58.16 -0.7 M32.47 33.76 C42.39 25.55, 47.69 19.23, 61.82 -1.59 M34.41 33.57 C43.09 23.01, 52.41 13.19, 63.91 -0.23 M40.5 32.87 C48.65 22.79, 59.1 11.2, 68.14 -0.14 M38.63 34.16 C46.4 27.65, 52.41 18.36, 69.24 0.98 M46.03 35.28 C50.31 25.6, 58.4 15.21, 75.05 -0.52 M45.16 33.69 C52.84 25.09, 61.03 16.35, 74.69 0.21 M50.36 33.62 C56.81 25.28, 61.74 18.45, 79.77 0.04 M50.18 34.96 C60.26 21.71, 69.7 10.26, 78.89 1.11 M56.18 34.93 C65.06 25.85, 69.95 14.77, 83.18 0.63 M55.21 33.86 C62 26.89, 68.58 17.52, 84.04 -1.12 M59.37 33.05 C73.56 22.61, 83.62 6.88, 89.19 -0.88 M60.58 34.57 C66.49 25.07, 74 18.15, 89.91 0.65 M64.32 35.13 C70.12 25.15, 78.36 18.34, 96.54 0.59 M65.42 33.97 C75.96 23.19, 84.07 12.4, 95.25 0.67 M71.74 34 C80.62 21.2, 91.91 9.46, 102.08 -0.24 M71.14 34.8 C79.51 24.13, 87.67 14.04, 99.8 0.65 M77.99 34.65 C84 23.84, 95.31 13.75, 104.63 1.43 M75.36 34.01 C87.69 22.31, 97.82 7.93, 105.76 -0.98 M82.85 34.66 C88.87 24.78, 97.66 14.82, 112.26 -1.06 M81.4 34.02 C93.39 21.24, 106.19 6.36, 111.72 -0.78 M84.89 34.62 C94.27 27.94, 98.76 20.01, 117.46 -0.69 M86.25 35.03 C97.98 21.76, 110.43 6.79, 115.53 -0.29 M93.23 34.58 C100 23.93, 108.74 16.53, 123.72 -2.01 M92.03 34.22 C102.83 23.23, 111.94 12.39, 121.5 0.55 M98.89 32.49 C106.62 23.64, 117.83 11.87, 126.14 -0.51 M97.98 34.16 C108.08 21.94, 117.56 10.31, 126.68 0.86 M102.57 32.63 C111.97 22.89, 120.37 15.36, 132.59 0.6 M103.89 33.94 C109.88 25.34, 117.73 17.17, 132.64 -0.08 M110 36.07 C113.19 28.8, 119.27 20.18, 137 -1.17 M108.11 33.61 C119.08 22.54, 128.53 10.44, 138.5 0.41 M111.71 33.06 C122.83 20.74, 133.89 9.03, 141.18 -1.2 M113 33.31 C121.73 25.12, 131.71 13.53, 143.32 0.68 M118.39 33.51 C131.37 22.14, 141.44 10.26, 148.15 0.75 M118.89 33.68 C126.81 23.51, 135.54 14.55, 149.14 0.11 M124.66 35.41 C130.88 25.64, 141.97 13.83, 151.94 -1.06 M123.56 33.03 C131.98 24.25, 139.91 17.03, 153.39 -0.73 M128.4 35.29 C137.82 23.51, 151.85 10.91, 158.89 2.06 M130.22 33.72 C135.67 25.84, 141.99 19.45, 157.9 -0.69 M134.56 32.61 C141.03 24.18, 149.77 17.03, 165.48 -0.27 M134.95 33.38 C143.16 23.75, 153.26 12.45, 165.36 0.18 M138.5 32.25 C151.71 22.45, 160.77 9.27, 167.64 -1.11 M140.69 33.19 C149.68 23.7, 158.59 12.99, 170.27 -0.06 M145.09 33.67 C151.95 23.39, 163.41 15.63, 174.56 -1.76 M144.05 33.97 C151.72 26.76, 158.27 19.08, 175.42 -0.99 M151.34 33.58 C160.48 24.03, 166.42 14.03, 182 0.71 M150.55 34.62 C161.1 22.42, 171.19 11.02, 180.89 -0.51 M155.01 34.68 C163.79 25.36, 168.49 21.08, 180.2 6.65 M154.89 33.73 C161.8 27.9, 167.16 19.83, 180.54 6.21 M159.72 32.79 C165.89 27.94, 170.7 22.13, 178.23 12.42 M160.73 34.59 C165.63 29.11, 168.61 25.48, 180.09 12.13 M164.3 33.34 C170.26 31.19, 173.35 25.14, 178.8 19.19 M165.69 34.44 C170.1 29.47, 175.07 23.92, 180.57 19.02 M172.31 33.86 C173.92 29.34, 177.58 27.24, 179.28 24.15 M171.81 34.54 C174.81 30.35, 178.45 26.12, 180.36 23.71 M177.27 34.8 C178.54 33.18, 178.93 31.45, 180.09 30.65 M176.72 34.49 C177.75 33.05, 178.59 32.25, 179.87 30.73" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M1.44 1.2 C43.42 -0.49, 81.37 2.01, 181.42 1.09 M0.74 -0.46 C72.33 1.1, 143.79 0.81, 179.08 0.43 M179.85 1.89 C179.7 5.81, 181.67 14.32, 178.71 30.5 M180.1 -0.61 C180.03 9.86, 180.43 18.65, 179.16 31.78 M178.95 32.3 C135.75 33.44, 89.83 31.23, -1.44 30.75 M179.51 32.62 C120.54 30.63, 59.1 30.85, -0.02 31.49 M-0.93 31.04 C-0.87 19.68, 0.53 7.94, -1.16 1.24 M-0.08 32.04 C0.44 24.46, 0.75 15.19, 0.08 0.35" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(189.8333740234375 270.0573716985489) rotate(0 11 10.5)"><text x="11" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[1]</text></g><g transform="translate(186 244.2241044866348) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(111.1666259765625 297.3907762395645) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.94 6.94 C2.17 4.63, 2.94 1.57, 5.7 0.23 M-0.25 6.25 C1.35 4.85, 2.66 2.63, 5.22 0 M1.53 11.07 C4.01 8.17, 6.68 6.14, 9.98 1.36 M0.12 11.62 C3.33 8.02, 7.03 5.81, 10.52 0.67 M-0.87 18.46 C5.55 13.17, 13.17 5.25, 13.77 0.13 M0.03 19.17 C5.19 11.28, 10.92 6.54, 15.35 -0.63 M-1.26 25.62 C5.97 15.84, 15.75 6.03, 21.24 1.53 M0.73 23.67 C4.65 18.62, 8.85 12.79, 21.97 -1.05 M0.96 31.53 C11.49 19.93, 21.82 8.02, 26.03 -0.62 M-0.36 30.57 C5.74 24.41, 11.02 16.58, 26.87 0.37 M2.92 31.88 C7.27 28.19, 15.42 18.77, 30.82 -1.02 M2.88 33.26 C13.52 21.73, 23.98 8.94, 32.85 -0.52 M7.3 34.44 C18.82 20.03, 28.87 7.66, 36.4 0.01 M7.66 34.23 C15.99 25.38, 23.6 15.36, 36.96 0.44 M13.97 34.14 C21.26 23.7, 29.48 13.54, 43.32 1.08 M12.88 34.78 C23.78 22, 31.73 12.38, 42.1 -0.11 M19.12 32.6 C24.93 26.04, 34.49 16.36, 49.09 -1.65 M18.05 34.19 C24.51 26.43, 32.85 17.14, 47.01 0.22 M23.65 32.44 C31.13 25.73, 39.54 14.66, 53.85 -1.97 M24.53 34.74 C34.07 21.53, 46.35 9.2, 53.79 -0.24 M28.37 33.87 C36.73 27.85, 40.97 21.89, 57.62 -1.05 M28.54 33.89 C34.26 26.96, 40.37 19.14, 57.98 0.03 M33 33.94 C42.55 23.87, 47.05 17.58, 61.89 1.16 M33.07 34.28 C45.84 21.46, 56.91 8.26, 64.04 -0.11 M38.65 35.45 C48.69 21.13, 60.59 7.78, 66.88 0.46 M40.19 34.16 C45.28 26.37, 54.12 17.32, 69.43 0.85 M44.32 33.67 C54.3 21.77, 67.35 6.94, 73.22 0.97 M44.31 34.93 C57 21.01, 68.68 6.14, 74.07 -0.78 M47.88 33.72 C57.68 23.32, 69.03 12.65, 79.1 1.71 M49.15 34.02 C58.57 22.21, 70.09 11.16, 78.47 -0.65 M55.31 33.09 C64.46 19.6, 77.78 7.44, 86 1.13 M55.66 34.18 C64.72 21.76, 74.41 12.04, 85.17 -0.14 M62.34 34.21 C67.18 24.71, 74.08 16.1, 91.85 -0.3 M59.64 33.65 C69.78 23.74, 79.02 12.5, 90.82 0.86 M63.66 35.05 C71.19 27.1, 80.83 18.4, 96.73 0.45 M65.74 33.41 C75.32 23.58, 84.31 14.41, 95.7 0.12 M70.63 33.62 C80.83 24.38, 90.35 11.51, 100.04 -0.45 M70.98 33.4 C79.31 23.01, 89.24 13.74, 99.75 0.38 M76.42 34.58 C88.89 19.32, 101.58 8.74, 106.22 -1.11 M76.79 33.71 C82.16 25.93, 89.14 18.4, 106.11 -0.54 M81.73 33.78 C91.32 23.06, 101.49 11.97, 109.93 0.58 M82.55 34.81 C88.88 25.54, 96.52 15.43, 111.13 -0.42 M87.97 32.85 C93.82 28.38, 97.86 22.09, 117.02 0.33 M87.6 34.79 C93.2 25.21, 100.61 16.99, 117.26 0.27 M90.93 35.7 C102.09 24.06, 110.48 11.36, 121.11 -1.77 M92.8 33.56 C101.04 24.45, 108.44 16.25, 122.38 -0.18 M98.02 35.18 C108.98 20.86, 119 9.74, 125.96 -0.44 M96.54 34.08 C107.22 21.74, 119.18 9.71, 126.08 -0.16 M101.89 33.54 C112.79 24.54, 120.27 13.85, 132.54 -1.89 M102.28 34.55 C113.59 20.93, 125.8 6.88, 133.54 -0.88 M109.66 33.06 C119.89 20.3, 129.8 8.48, 138.24 0.75 M108.57 33.65 C118.08 24.54, 126.64 13.64, 136.58 -0.09 M112.59 32.6 C119.19 25.24, 124.66 20.23, 144.5 -2.02 M114.6 34.79 C120.12 26.17, 128.46 18.88, 142.18 -0.85 M119.29 34.14 C129 24.29, 136.22 14.59, 148.07 0.51 M118.22 33.27 C129.31 24.4, 137.84 12.1, 147.52 0.64 M125.38 35.35 C131.89 21.38, 141.89 11.43, 152.63 1.78 M123.46 34.52 C131.73 25.64, 137.41 18.85, 154.49 0.3 M130.68 36.2 C137.42 25.83, 146.04 15.7, 160.02 -1.41 M128.6 33.34 C141.96 19.97, 151.84 6.68, 158.74 0.35 M132.92 35.43 C141.91 25.32, 151.68 14.89, 165.9 1.58 M135.64 34.11 C143.98 24.6, 153.33 14.05, 164.21 0.58 M140.92 33.2 C147.36 24.44, 152.49 18.9, 170.97 -0.12 M140.39 33.98 C152.21 21.99, 162.35 8.08, 170.16 0.54 M143.59 36.36 C155.08 23.43, 162.17 11.92, 176.63 -0.39 M145.32 33.88 C152.58 27.39, 157.33 19.4, 175.68 0.72 M150.46 33.26 C160.35 24.26, 171.27 11.82, 180.17 0.46 M150.87 33.95 C160.21 24.66, 167.52 13.26, 180.76 0.86 M154.07 34.58 C163.95 27, 168.9 17.95, 180.58 5.06 M155.75 34.05 C160.66 28.56, 166.87 21.03, 178.89 5.88 M161.08 32.64 C165.96 27.23, 170.18 22.37, 180.71 13.63 M160.87 33.69 C166.56 28.28, 170.73 22.61, 181.12 12.24 M167.41 33.94 C168.83 30.02, 172.54 28.47, 180.06 16.96 M166.29 34.28 C169.48 31.15, 173.56 26.97, 179.63 19.59 M170.58 33.86 C174.82 29.75, 177.5 28.53, 180.77 23.87 M171.81 34.22 C173.84 31.16, 176.34 28.75, 180.03 23.84 M177 33.99 C178.02 32.92, 179.37 31.45, 180.55 30.67 M176.59 34.22 C177.86 33.2, 178.65 32.59, 180.19 30.81" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M-1.93 -1.5 C67.52 -0.37, 134.97 0.19, 179.09 -1.09 M0.13 0.07 C67.22 -1.76, 135.2 -1.47, 179.12 0.32 M178.13 1.95 C179.25 8.16, 178.48 18.48, 178.17 31.23 M180.85 0.73 C180.44 9.17, 179.25 19.55, 179.22 32.31 M181.16 33.29 C134.4 32.07, 89.33 34.2, 0.65 30.87 M179.62 31.9 C134.6 33.71, 88.7 34.6, -0.15 31.37 M-0.12 32.82 C0.88 22.97, 1.45 15.11, -0.82 0.68 M0.48 32.95 C-0.33 22.97, 0.44 13.84, -0.02 -0.05" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(185.6666259765625 303.5574479924942) rotate(0 15.5 10.5)"><text x="15.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round" transform="translate(111.83343505859375 328.39083727472075) rotate(0 90 15.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.24 6.8 C0.31 4.57, 2.83 3.57, 5.03 -0.33 M-0.31 6.67 C0.71 4.81, 2.59 3.05, 4.86 0.03 M1.09 11.41 C3.95 9.1, 5.63 6.3, 10.49 0.05 M0.28 11.5 C3.75 9.62, 5.66 6.31, 11.24 0.42 M-0.27 20.07 C6.99 12.63, 9.08 5.6, 16.55 2.06 M-0.11 17.47 C4.05 14.39, 7.4 8.37, 15.99 1.18 M-0.9 24.16 C10.08 13.03, 16.59 6.93, 19.71 -0.66 M-0.09 23.83 C4.03 18.04, 10.27 12.36, 22.19 -0.91 M0.93 31.77 C8.48 22.74, 15 11.77, 24.81 1.61 M-0.04 31.44 C8.67 19.76, 19.35 9.12, 25.29 -0.61 M1.59 34.55 C14.08 20.32, 22.76 8.43, 32.92 0.06 M3.83 33.04 C13.68 20.93, 23.67 10.02, 32.68 -0.08 M8.3 32.19 C16.28 22.18, 25.75 12.24, 36.51 -0.02 M8.29 34.36 C17.96 21.86, 28.92 9.57, 36.88 -0.49 M12.79 32.96 C18.73 25.19, 27.82 18.69, 43.12 -0.74 M14.59 32.37 C20.59 24.76, 28.8 14.96, 42.08 -0.89 M17.76 34.26 C30.78 20.61, 42.46 5.99, 46.6 1.02 M17.78 34.42 C28.19 22.72, 37.34 11.32, 47.16 0.09 M23.91 34.16 C35 20.21, 46 7.25, 54.71 0.1 M23.62 33.48 C31.82 25.21, 39.41 15.69, 52.2 -0.61 M31.18 34.04 C37.8 25.44, 45.59 12.88, 56.39 -0.28 M28.56 33.42 C36.91 23.11, 46.14 13.75, 57.57 -0.19 M35.73 31.79 C43.95 21.42, 54.41 9.95, 65.4 -2.08 M34.66 33.88 C42.69 24.46, 51.24 14.89, 64.41 -0.83 M38.42 32.73 C48.64 21.23, 55.97 12.93, 67.53 0.23 M38.92 33.83 C50.31 21.47, 60.05 11.26, 69.67 0.56 M43.32 34.36 C51.54 25.19, 57.58 19.06, 76.27 -1.81 M45.52 34 C55.14 21.33, 64.18 10.43, 74.65 -0.47 M48.68 33.7 C60.55 22.86, 70.1 12.51, 80.01 1.88 M49.76 32.82 C61.61 21.68, 69.55 9.91, 80.06 0.36 M54.16 31.82 C67.9 19.29, 79.5 8.73, 85.73 -1.45 M55.08 32.69 C63.95 23.68, 74.47 11.94, 84.47 -0.78 M60.49 32.46 C70.87 19.46, 84.63 7.63, 90.17 1.14 M61.56 33.18 C68.35 25.19, 74.91 19.61, 89.44 0.44 M64.69 34.52 C74.23 26.2, 81.25 18.51, 95.53 -1.18 M66.98 33.23 C78.18 21.71, 88.38 8.74, 95.97 -0.32 M71.73 34.68 C78.66 24.95, 85.41 16.54, 100.68 1.62 M71.35 32.4 C80.36 24.41, 86.78 15.53, 101.59 0.19 M77.73 31.95 C84.75 27.81, 89.14 18.45, 104.78 -1.07 M75.93 33.08 C85.91 22.02, 96.36 10.61, 106.84 0 M81.63 34.19 C88.6 26.82, 95.57 17.13, 110.56 0.11 M81.76 33.66 C89.19 23.26, 97.65 14.55, 110.36 0.16 M88.42 34.76 C95.88 24.51, 107.42 11.36, 115.27 1.75 M86.72 32.84 C94.19 24.09, 103.56 15.57, 116.69 0.69 M92.77 34.99 C100.66 22.87, 111.2 9.65, 121.19 0.54 M94 32.77 C103.32 22.32, 113.06 10.51, 122.67 -0.92 M98.25 32.78 C105.08 25.09, 112.97 14.25, 128.1 0.05 M97.21 33.32 C108.71 22.21, 117.22 10.41, 126.68 -0.3 M105.04 33.19 C113.12 22.09, 121.05 11.6, 134.28 0.02 M102.85 33.25 C112.05 22.76, 121.22 13.39, 133.54 0.85 M109.07 32.98 C114.29 26.4, 123.84 17.17, 137.73 -1.01 M109.36 34.48 C118.87 22.45, 128.09 9.64, 136.56 -0.1 M113.72 31.12 C119.52 26.11, 128.12 17.22, 141.87 -1.21 M113.66 33.26 C122.32 24.98, 128.11 14.71, 143.05 -0.45 M121.04 33.47 C129.95 21.72, 139.65 10.09, 148.66 -0.84 M120.18 34.45 C125.71 26.06, 131.67 19.32, 148.35 1.06 M123.4 31.21 C130.16 24.57, 136.27 20.18, 152.37 -1.74 M125.38 32.66 C133.62 23.04, 143.92 12.57, 153.37 0.42 M130.7 33.53 C137.84 24.55, 143.55 16.97, 160.7 -0.72 M130.78 32.55 C137.06 23.92, 145.77 15.78, 158.62 -0.36 M134.03 34.09 C143.72 23.89, 153.22 16.31, 164.51 -1.02 M135.52 33.97 C142.43 25.87, 148.63 18.15, 163.74 -1.11 M140.9 31.62 C148.97 22.65, 161.73 10.46, 171.01 -1.74 M141.34 34.25 C150.17 21.72, 161.21 10.7, 169.52 -0.23 M146.24 33.26 C151.36 24, 161.65 16.82, 173.39 -1.3 M146.52 34.12 C153.31 23.81, 163.43 14.83, 175.47 -0.47 M150.86 35.32 C162.83 21.82, 173.49 8.3, 180.1 1.14 M152.12 34.21 C159.52 22.63, 170.02 13.14, 179.8 0.26 M157.97 34.15 C165.82 21.98, 175.88 10.68, 178.53 5.05 M155.36 34.49 C163.54 24.72, 170.78 15.24, 179.07 5.91 M162.14 31.38 C166.75 26.22, 171.77 24.05, 179.32 13.2 M162.45 33.25 C168.35 25.73, 175.91 18.38, 179.26 11.65 M166.54 32.58 C171.45 29.57, 175.15 22.54, 179.01 18.58 M166.64 34.34 C170.34 30.6, 172.79 27.47, 180.32 18.45 M172.55 32.35 C174.27 32.21, 176.61 28.76, 180.35 25.13 M172.02 33.34 C174.06 31.41, 176.4 28.06, 180.91 24.7 M177.41 33.69 C178.45 32.56, 179.87 31.35, 179.96 30.76 M177.58 33.51 C178.3 32.98, 179.11 32.04, 179.92 30.51" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M0.57 1.42 C72.99 3.33, 142.9 0.26, 181.49 -0.91 M-0.16 -0.92 C62.86 -0.75, 123.97 0.2, 179.92 0.94 M178.95 -1.29 C177.88 8.85, 177.88 17.45, 180.19 29.77 M180.64 -0.84 C179.71 9.84, 179.48 20.59, 179.47 30.98 M178.95 29.56 C112.62 32.56, 49.07 30.4, -0.97 31.57 M179.83 30.98 C111.23 31.1, 43.99 29.26, -0.47 30.35 M0.67 29.84 C1.26 22.3, -0.8 15.94, -0.15 -0.59 M-0.43 31.08 C0.2 21.16, -0.17 10.46, -0.23 0.9" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(189.33343505859375 338.39083727472075) rotate(0 12.5 10.5)"><text x="12.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[n]</text></g><g stroke-linecap="round" transform="translate(133.50003051757812 392.2241807805801) rotate(0 98.00007629394531 19.666732788085938)"><path d="M1.09 1.98 C43.2 -2.48, 89.7 -2.3, 196.94 0.25 M196.87 -1.25 C194.18 12.72, 195.79 26.03, 195.98 37.46 M194.17 38.91 C116.26 36.97, 40.37 36.84, 0.65 41.03 M-1.1 38.4 C-1.81 24.62, -1.3 9.97, 1.31 1.16" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(144.83331298828125 401.8907762395645) rotate(0 82 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMGlobalInstance</text></g><g transform="translate(199.6666717529297 503.89079149835356) rotate(0 96.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMExportMemInstance</text></g><g stroke-linecap="round" transform="translate(210.6666717529297 534.5575090276504) rotate(0 88.66665649414062 60.500030517578125)"><path d="M-0.17 -0.97 C41.63 2.13, 85.8 2.63, 178.27 0.73 M0.97 0.13 C45.94 -0.24, 89.54 -1.01, 178 0.87 M177.61 -0.95 C176.35 25.13, 175.92 53.4, 178.34 121.51 M176.78 0.68 C177.23 45.91, 176.17 91.41, 178.28 120.53 M178.75 121.46 C122.16 120.81, 68.13 121.78, -1.41 121.51 M177.37 121.29 C139.52 119.96, 102.64 119.09, -0.18 120.93 M-0.95 120.26 C1.31 88.02, 0.93 55.08, -1.35 1.39 M-0.06 120.77 C1.66 77.55, 1.88 35.53, 0.78 -0.1" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(224.33335876464844 550.5574479924942) rotate(0 58.5 15.5)"><path d="M-0.97 -1.96 C30.4 -1.29, 60.01 1.04, 117.73 -0.93 M0.13 0.97 C30.27 -1.54, 59.95 -0.47, 117.87 -0.81 M116.05 -0.55 C115.55 7.21, 117.34 17.39, 117.51 32.57 M117.68 0.25 C117.02 7.59, 116.74 17.74, 116.53 31.14 M117.46 31.42 C82.01 33.81, 49.41 30.42, 0.51 29.26 M117.29 30.95 C77.65 31.88, 37.49 30.85, -0.07 30.74 M-0.74 32.88 C0.33 21.73, 0.57 8.12, 1.39 1.08 M-0.23 31.51 C-0.58 25.38, 0.24 19.07, -0.1 -0.67" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(230.33335876464844 555.5574479924942) rotate(0 52.5 10.5)"><text x="52.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">char* name </text></g><g stroke-linecap="round" transform="translate(242.00001525878906 594.8907914983536) rotate(0 7.3333282470703125 8.833328247070312)"><path d="M8.72 -0.78 C10.9 3.22, 12.25 4.79, 14.22 9.03 M7.9 -0.23 C10.12 3.88, 13.79 6.63, 14.47 8.82 M13.93 8.46 C12.78 12.25, 10.72 15.28, 7.68 17.26 M14.74 8.56 C13.02 11.65, 11.21 13.33, 7.93 18.05 M7.15 18.84 C4.74 13.64, 2.35 10.23, 0.42 8.35 M7.96 18.16 C5 14.93, 3.08 12.26, 0.28 8.74 M0.12 9.9 C2.31 5.84, 4.91 5.03, 6.86 -0.11 M-0.36 9.44 C2.5 6.79, 4.66 3.27, 7.75 0.55" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(226.6666717529297 587.2241044866348) rotate(0 64 19)"><path d="M-1.39 1.79 C33.15 -0.1, 63.49 -1.62, 128.06 1.94 M-0.4 -0.96 C40.74 1.1, 79.33 -0.13, 127.68 0.14 M127.02 0.44 C128.91 10.12, 129.46 18.63, 127.25 36.89 M127.19 -0.14 C129.04 13.53, 128.23 27.86, 128.7 38.71 M129.98 37.53 C85.24 37.6, 43.57 37.8, -1.1 38.06 M128.84 37.07 C85.69 37.85, 43.49 38.39, -0.44 37.53 M1.5 38.43 C-1.7 29.41, 0.72 16.13, -0.18 -0.12 M0.74 38.21 C0.59 27.39, -0.86 16.57, 0.92 -0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(263.6666717529297 596.2241044866348) rotate(0 27 10.5)"><text x="27" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">memory</text></g><g stroke-linecap="round"><g transform="translate(244.6666717529297 604.2241044866348) rotate(0 -55.152343048587966 88.93260316701065)"><path d="M1.07 0.56 C-17.48 6.14, -107.34 3.25, -110.56 32.61 C-113.79 61.97, -33.92 152.68, -18.27 176.71 M0.18 -0.19 C-18.56 5.62, -108.04 4.15, -111.28 33.85 C-114.53 63.56, -34.59 154.02, -19.28 178.05" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(244.6666717529297 604.2241044866348) rotate(0 -55.152343048587966 88.93260316701065)"><path d="M-43.51 162.44 C-36.31 166.65, -26.15 175.35, -19.02 180 M-43.78 162.59 C-38.23 166.2, -30.65 171.3, -19.76 177.78" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(244.6666717529297 604.2241044866348) rotate(0 -55.152343048587966 88.93260316701065)"><path d="M-27.12 150.09 C-25.99 158.95, -21.8 172.15, -19.02 180 M-27.39 150.23 C-26.51 157.18, -23.55 165.76, -19.76 177.78" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(10 589.224150263002) rotate(0 95 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(WASMMemoryInstance*)</text></g><g stroke-linecap="round" transform="translate(211.66665649414062 654.724150263002) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.94 6.04 C0.85 4.28, 2.89 2.89, 5.49 0.94 M-0.33 6.1 C1.08 4.8, 2.81 2.27, 5.12 0.68 M1.23 12.37 C3.93 7.73, 5.16 6, 10.65 -0.49 M-0.41 11.35 C2.78 9.09, 6 5.95, 11.29 0.54 M-1.38 18.7 C4.44 12.04, 12.89 4.85, 15.08 0.92 M-0.61 18.1 C3.53 12.98, 9.45 8.47, 16.48 0.46 M0.05 22.8 C5.01 17.65, 13.94 9.19, 20.29 -0.34 M0.61 24.4 C5.49 17.48, 11.74 11.88, 21.98 0.01 M0.23 31 C8.3 22.65, 14.9 13.63, 26.79 -0.38 M0.32 31.26 C9.99 18.38, 19.18 6.79, 26.01 -0.03 M3.02 33.54 C7.93 25.44, 12.7 20.52, 32.48 0.15 M2.16 33.92 C8.74 26.32, 14.72 19.8, 32.62 0.29 M6.28 32.24 C15.42 27.31, 21.17 19.08, 37.85 -1.52 M6.61 34.96 C16.55 23.69, 26.64 10.7, 35.91 -0.52 M13.59 35.57 C21.61 20.86, 35.11 10.03, 43.65 -1.73 M13.61 34.04 C22.53 22.89, 31.87 12.28, 41.54 0.78 M17.35 34.22 C29.12 24.4, 35.92 11.57, 48.09 0.23 M17.44 35.05 C26.93 24.79, 33.99 15.91, 46.76 -0.56 M23.17 35.33 C34.84 21.92, 41.51 12.05, 52.53 -1.4 M23.96 33.1 C29.19 27.64, 37.33 20.28, 53.97 -1.11 M29.04 35.15 C37.53 23.07, 48.14 10.78, 58.66 -0.22 M27.69 34.78 C35.48 26.42, 42.21 17.03, 58.71 -0.01 M32.39 34.31 C42.54 24.16, 54.12 11.85, 62.2 -1.16 M33.63 34.05 C44.08 23.29, 55.22 10.52, 63.24 -0.78 M40.54 34.63 C47.71 20.96, 60.32 8.96, 70.08 -1.84 M39.62 34.79 C49.19 23.67, 57.65 14.37, 68.5 -0.08 M43.19 33.95 C51.95 22.46, 60.2 15.17, 74.1 -0.12 M43.61 34.23 C54.96 21.67, 66.31 10.39, 73.74 0.52 M49.43 35.42 C54.3 26.09, 63.35 20.52, 80.18 0.58 M50.57 33.91 C58.03 26.21, 64.79 16.93, 78.45 -0.29 M52.91 34.07 C63.87 23.37, 75.51 11.03, 86 -0.25 M54.5 34.93 C65.15 23.48, 74.87 12.01, 85.96 0.72 M61.58 33.41 C67.32 27.37, 75.02 19.6, 90.18 -1.6 M59.96 34.14 C68.37 26.2, 76.36 16.54, 89.44 0.5 M66.85 35.91 C75.65 23.22, 85.24 11.1, 94.01 -0.38 M66.12 35.37 C77.16 21.1, 88.76 8.99, 95.45 -0.06 M69.25 35.66 C82.45 23.43, 89.72 12.71, 102.6 -0.86 M70.28 33.64 C79.6 25.6, 87.23 16.9, 99.94 -0.89 M75.67 32.86 C84.9 25.43, 93.17 14.46, 106.6 -2.14 M75.89 34.42 C87.27 20.52, 99.07 7.67, 105.83 -0.56 M81.02 34.41 C94.91 22.19, 105.1 8.09, 111.34 0.46 M82.09 33.76 C93.59 21.63, 104.66 8.12, 111 -0.98 M85.4 32.47 C97.15 23.91, 108.02 9.63, 117.91 0.71 M85.77 33.62 C96.26 23.63, 103.7 14.15, 117.18 -0.56 M91.82 33.02 C105.43 20.32, 115.05 7.74, 123.6 0.21 M93.05 34.01 C100.68 24.92, 109.65 14.63, 121.25 -0.61 M99.38 34.44 C108.15 21.48, 117.59 10.43, 128.4 1.31 M97.35 34.22 C105.32 24.74, 113.17 15.47, 127.58 1.05 M104.92 32.03 C112.17 19.8, 124.53 8.62, 133.98 -1.65 M102.89 33.06 C108.1 25.78, 115.8 20.04, 131.89 0.06 M108.29 32.63 C115.84 27.19, 122.47 17.44, 138.91 2.25 M108.75 34.09 C114.34 26.11, 120.51 19.93, 138.25 -0.2 M113.95 35.12 C125.56 23.33, 135.59 12.24, 142.37 -0.96 M114.4 33.78 C124.77 20.69, 135.44 9.49, 143.69 0.53 M120.19 33.05 C124.49 28.04, 129.97 20.31, 147.28 -1.52 M117.71 34.8 C129.75 21.87, 140.95 8.82, 149.14 -0.33 M124.85 35.14 C130.88 26.3, 136.89 21.23, 152.04 0.57 M124.48 34.19 C133.7 22.23, 145.31 10.47, 154.03 -1.02 M130.46 35.88 C141.22 22.4, 151.45 10.81, 157.68 0.14 M128.51 34.6 C138.4 22.51, 148.94 11.8, 159.27 0.8 M133.94 32.09 C143.41 23.26, 153.57 8.85, 163.58 1.39 M135.08 34.49 C141.95 25.35, 150.96 15.8, 163.83 -0.75 M139.81 33.45 C150.23 22.55, 161.85 10.33, 170.64 -1.5 M139.02 33.39 C147.82 25.11, 154.84 16.95, 169.73 0.49 M145.2 35.87 C153.19 25.18, 161.9 16.14, 176.95 -1.88 M145.58 34.81 C153.3 25.29, 160.81 16.32, 174.61 -0.14 M152.32 32.24 C160.4 24.22, 165.8 16.86, 181.02 0 M149.71 33.75 C157.76 25.78, 163.81 17.79, 180.72 0.21 M154.94 33.3 C162.16 27.4, 168.46 19.44, 179.52 6.31 M156.42 35.17 C165.1 24.26, 173.3 14.14, 179.57 5.8 M161.41 34.9 C167.06 30.87, 168.35 26.03, 181.54 12.32 M160.61 33.94 C165.86 27.81, 173.35 20.78, 179.99 12.71 M165.84 34.6 C170.62 28.46, 174.87 25.72, 181.25 19.37 M166.14 35.06 C170.44 29.39, 174.98 25.04, 179.68 18.42 M171.81 34.16 C175.13 31.23, 178.46 27.93, 180.27 25.47 M172.14 34.6 C174.81 31.47, 177.01 28.6, 179.7 24.56 M176.48 34.91 C178.35 32.88, 179.6 31.49, 180.22 30.76 M176.83 34.65 C177.36 33.67, 178.28 32.81, 180.24 30.73" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M-0.93 -0.79 C70.19 1.29, 140.51 1.29, 179.64 -0.81 M-0.81 -0.36 C36.43 -1.42, 73.03 -1.84, 179.33 -0.49 M181.57 -0.58 C179.41 9.31, 181.53 21.34, 180.28 30.72 M180.14 -0.13 C181.01 9.94, 180.53 18.68, 179.28 33.33 M178.26 33.05 C129.12 32.86, 81.02 32.7, -0.13 34.01 M179.74 32.81 C142.33 31.73, 105.18 33.14, 0.1 33.08 M1.08 30.43 C0.04 21.81, -0.25 12.55, -1.21 1.47 M-0.67 31.91 C0.66 21.92, 0.04 12.09, -0.24 -0.43" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(290.6666564941406 660.8908220159317) rotate(0 11 10.5)"><text x="11" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[1]</text></g><g transform="translate(286.8332824707031 635.0575548040176) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(211.99990844726562 688.2242265569473) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.48 6.28 C1.18 5.63, 2.61 4.04, 5.67 0.43 M0.12 6.09 C1.09 4.86, 3.08 2.78, 5.34 -0.01 M-1.37 12.13 C3.65 7.52, 7.39 2.69, 10.08 1.24 M0.61 12.04 C3.38 9.93, 5.69 7.01, 10.71 0.57 M0.27 19.87 C3.46 13.69, 7.92 9.57, 14.67 -0.65 M-0.57 19.07 C4.04 14.89, 7.98 9.23, 14.75 -0.07 M0.42 25.94 C4.87 16.26, 12.29 9.77, 19.97 -1.71 M0.15 23.81 C8.16 16.89, 14.29 8.18, 20.72 0.7 M1.68 29.04 C10.05 21.62, 15.59 13.27, 25.76 0.79 M-0.57 29.67 C7.75 20.25, 16.84 9.49, 25.54 -0.51 M0.55 32.06 C12.35 23.24, 22.32 9.65, 30.61 1.61 M2.4 33.28 C11.4 25.17, 19.23 14.12, 32.73 -0.24 M7.76 35.53 C14.49 26.54, 20.45 17.86, 37.02 0.37 M8.15 33.88 C12.88 25.76, 19.67 19.69, 37.39 -0.64 M12.14 34.6 C23.12 24.05, 30.58 12.3, 41.27 -0.05 M13.25 33.06 C24.41 20.67, 35.2 9.72, 42.65 0.77 M19.83 32.42 C26.27 25.46, 33.84 15.17, 46.68 -1.05 M17.6 34.06 C24.86 24.87, 31.39 17.52, 46.66 0.37 M22.76 32.34 C31.76 23.55, 38.5 13.11, 53.49 -1.91 M24.6 34.73 C34.68 23.53, 42.59 12, 53.03 0.73 M30.02 32.38 C39.28 24.03, 47 11.4, 60.11 0.71 M29.12 33.91 C33.78 27.66, 40.43 20.46, 57.84 -0.1 M34.99 34.36 C41.76 24.84, 47.13 19.06, 64.97 -0.86 M34.34 35.37 C42.93 23.39, 51.46 13.93, 64.09 -0.32 M37.93 34.64 C48.5 23.29, 58.71 9.67, 67.84 -0.81 M38.98 34.41 C49.75 22.15, 58.71 10.88, 68.64 0.92 M42.57 32.81 C52.97 25.72, 59.42 18.51, 75.59 -1.44 M43.55 35.36 C51.85 25.47, 59.44 17.05, 74.72 -0.24 M49.28 34.81 C59.06 25.72, 66.5 14.39, 79.56 -0.72 M50.16 34.63 C60.14 20.29, 71.36 9.23, 78.9 0.97 M56.39 33.46 C62.56 28.66, 67.15 21.49, 85.34 -1.85 M55.49 33.96 C63.62 26.18, 71.61 15.46, 85.5 0.17 M61.97 34.8 C72.75 22.18, 79.82 9.16, 90.11 -0.8 M61.27 34.73 C67.56 25.03, 75.4 17.48, 89.64 -0.82 M65.17 34.65 C75.03 19.93, 87.36 10.31, 96.42 0.07 M65.23 35.22 C76.74 21.42, 87.32 9.38, 95.65 0.22 M72.04 32.9 C78.44 28.75, 82.09 19.01, 101.5 0.52 M71.61 34.92 C78.17 25.74, 82.97 19.01, 100.07 -0.74 M76.8 34.08 C84.32 25.03, 91.34 16.94, 107.13 0.81 M76.06 33.79 C85.15 24.48, 92.58 16.33, 106.1 0.26 M83.7 33.71 C90.82 24.91, 97.66 17.6, 112.88 -1.84 M82.16 34.52 C91.56 22.16, 100.49 11.62, 110.56 0.49 M88.3 34.79 C93.03 28.1, 101.12 18.53, 117.32 1.95 M86.39 33.88 C93.24 28.11, 98 21.11, 115.75 -0.5 M91.3 34.19 C99.67 26.16, 108.8 14.81, 122.57 -1.62 M92.56 34.92 C102.48 20.79, 113.39 9.29, 121.65 0.72 M95.86 35.16 C107.67 22.07, 121.93 6.24, 124.93 1.17 M96.83 34.3 C105.25 24.94, 115.64 14.88, 127.19 -0.05 M101.37 33.66 C114.74 22.17, 125.07 5.52, 134.03 0.76 M102.14 34.55 C112.27 23.77, 120.34 14.07, 133.06 -0.61 M108.82 34.91 C116.66 24.83, 128.78 11.23, 136.11 -1.26 M107.17 33.41 C119.64 22.42, 129.67 9.39, 137.68 -0.03 M114.57 35.75 C124.12 22.1, 131.15 13.49, 141.89 0.27 M112.86 33.98 C125.1 21.61, 136.44 7.44, 142.67 0.53 M119.69 33.13 C130.36 20.6, 139.34 10.33, 149.82 0.53 M119.35 34.17 C125.23 28.18, 130.05 19.25, 148.82 0.23 M123.74 34.47 C135.16 20.82, 144.14 12.24, 153.93 1.18 M124.41 34.82 C133.5 23.39, 142.13 13.06, 153.54 -0.28 M130.12 34.21 C141.55 20.77, 150.09 10.06, 159.15 0.76 M128.48 35.11 C135.05 27.15, 142.88 19.55, 158.87 -0.51 M135.86 32.14 C140.85 24.67, 151.58 16.15, 165.09 -0.87 M135.1 34.75 C143.4 22.59, 152.76 13.25, 164.9 -0.87 M140.93 33.92 C150.4 25.45, 155.76 13.54, 169.38 -0.03 M139.87 33.34 C147.29 27.26, 152.97 19.64, 169.78 -0.4 M145.41 34.21 C155.69 25.5, 162.01 11.7, 175.46 -0.9 M144.29 35.32 C155.09 20.99, 167.13 8.35, 175.16 0.52 M150.08 33.36 C163.78 21.59, 173.68 6.09, 179.92 -0.94 M149.98 33.55 C156.51 27.3, 163.59 18.56, 180.16 0.47 M155 36.17 C160.28 26.53, 168.59 20.73, 178.39 8.2 M155.96 33.86 C165.6 23.31, 173.5 11.77, 178.97 7.01 M162.7 32.98 C168.39 28.45, 173.07 20.17, 179.87 13.35 M161.44 35.01 C165.57 28.72, 171.01 23.81, 179.8 13.15 M165.44 34.16 C171.75 31.27, 174.75 25.39, 179.6 18.58 M165.81 35.05 C170.2 29.46, 174.09 25.66, 179.41 18.99 M172.62 34.38 C175.5 31.04, 178.15 28.01, 181.06 23.01 M171.97 34.38 C174.88 29.9, 178.04 27.54, 180.21 24.52 M176.67 34.79 C177.43 33.65, 178.43 32.12, 179.86 30.48 M176.8 34.54 C177.74 33.41, 178.94 31.79, 180.29 30.4" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M1.94 0.26 C47.59 -0.42, 90.48 -1.97, 181.34 1.74 M0.14 -0.47 C39.11 -0.1, 78.29 0.8, 180.51 0.26 M178.89 1.37 C180.41 12.51, 178.29 24.18, 181.89 31.4 M180.71 0.23 C180.17 9.42, 180.95 20.04, 179.29 32.59 M180.06 32.92 C141.57 31.22, 105.01 29.48, -0.37 32.19 M179.53 31.96 C131.59 31.63, 82.05 31.75, -0.67 33.03 M-0.12 31.86 C1.32 19.67, 1.78 9.86, 1.57 -0.2 M-0.03 32.62 C0.65 24.56, -0.3 16.78, -0.45 1" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(286.4999084472656 694.390898309877) rotate(0 15.5 10.5)"><text x="15.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round" transform="translate(212.66671752929688 719.2242875921036) rotate(0 90 15.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.02 6.9 C1.58 5.19, 2.93 3.61, 4.85 -0.24 M-0.44 6.53 C1.15 4.88, 2.34 3.43, 5.26 0.44 M-0.2 12.06 C3.84 7.01, 7.81 3.98, 9.55 -1.41 M0.83 12.7 C3.38 9.42, 5.65 6.31, 10.13 0.07 M-0.25 17.9 C4.21 13.62, 6.43 8.67, 14.64 -0.36 M0.02 19.31 C3.46 14.22, 5.84 10.17, 15.51 -0.31 M-1.36 23.11 C4.94 17.69, 8.88 10.82, 21.94 0.56 M1.22 24.81 C5.15 18.72, 9.32 13.91, 21.37 0.19 M1.96 31.02 C7.01 23.13, 15.12 12.92, 26.88 1.85 M-0.71 30.24 C7.61 20.78, 14.98 12.04, 26.58 0.13 M3.13 33.7 C11.33 22.74, 17.56 17.23, 31.47 0.01 M3.84 33.84 C11.48 23.15, 20 14.56, 31.35 -1.09 M7.54 34.44 C17.64 20.72, 31.05 6.98, 35.4 1.75 M7.11 32.5 C13.89 26.25, 22.09 16.76, 37.17 1.13 M14.34 34.2 C18.02 26.84, 24.17 19.66, 43.75 0.3 M14.47 32.08 C22.01 24.98, 28.73 16.9, 42.2 -0.12 M19 34.01 C28.9 20.96, 38.61 8.13, 46.41 1.96 M18.57 32.68 C28.98 21.05, 39.9 8.33, 47.28 0.99 M24.5 32.41 C33.89 19.29, 46.14 6.91, 53.81 -1.54 M25.27 33.85 C29.41 26.02, 36.6 18.99, 53.36 0.33 M30.62 33.92 C34.76 25.4, 43.27 20.06, 56.28 1.44 M28.53 33.97 C37.89 23.54, 46.78 12.5, 57.53 0.09 M35.16 32.18 C39.79 26.99, 48.66 17.65, 63.84 -1.13 M34.29 33.21 C42.88 23.13, 53.2 11.66, 64.43 0.05 M38.47 34.67 C44.24 26.33, 51.43 18.24, 69.51 1.5 M40.67 33.1 C50.76 20.53, 61.87 8.72, 68.25 -0.11 M46.05 33.41 C52.49 26.78, 60.74 16.21, 73.17 -0.74 M45.24 33.05 C55.43 21.64, 64.55 11.47, 74.19 0.43 M51.75 34.11 C57.02 25.28, 62.64 18.74, 80.79 -0.23 M49.82 32.38 C61.53 20.49, 72.93 7.56, 78.42 -0.06 M57.05 34.64 C61.35 27.66, 67.69 18.31, 84.32 0.71 M56.49 34.6 C65.35 22.77, 73.87 13.45, 85.58 -0.6 M62.85 33.44 C67.91 22.35, 78.36 12.34, 88.94 0.27 M60.99 32.7 C70.8 22.4, 79.48 10.38, 90.7 0.84 M64.86 31.99 C75.5 24.33, 85.67 12.46, 96.93 1.61 M66.77 33.43 C76.83 21.84, 86.92 10.13, 94.73 0.52 M73.3 35.2 C81.5 20.22, 94.03 9.11, 98.94 -0.69 M72.38 32.54 C82.09 19.72, 93.84 5.99, 100.43 -0.7 M76.34 33.91 C83.73 25.31, 95.22 14.43, 105.83 -0.26 M77.48 33.15 C83.84 26.43, 91.1 17.71, 105.93 -0.13 M83.79 33.27 C93.1 22.79, 104.8 7.14, 111.94 -0.42 M82.32 32.94 C92.23 20.97, 103.43 8.38, 110.61 -0.92 M86.51 35.21 C95.95 23.73, 105.13 15.61, 114.32 -1.05 M87.68 34.49 C97.84 21.55, 109.49 6.98, 115.99 -0.09 M92.16 34.87 C104.64 19.84, 116.25 5.82, 123.24 0.11 M92.35 32.52 C101.63 22.56, 111.18 12.42, 122.91 0.05 M96.55 35.04 C109.44 20.96, 116.66 10.85, 126.84 0.17 M97.11 34.23 C107.22 24.71, 115.09 14.08, 127.85 -0.6 M103.41 34.58 C108.59 24.22, 117.9 19.67, 132.28 -1.75 M104.18 32.49 C110.27 25.23, 116.84 18.21, 132.69 -0.88 M107.77 34.89 C120.59 20.23, 127.34 8.59, 139.02 -0.06 M109.19 34.23 C115.74 25.78, 123.68 16.65, 137.68 0.93 M115.7 32.31 C124.69 21, 135.67 6.98, 144.67 -0.28 M114.66 33.63 C124.33 21.65, 132.34 12.69, 143.95 -0.68 M119.67 32.59 C125.34 26.1, 136.79 15.48, 146.3 1.41 M119.98 34.46 C127.32 22.38, 137.42 13.09, 148.45 0.92 M126.34 31.31 C135.42 22.64, 144.54 11.99, 154.2 0.58 M124.85 33.3 C130.93 25.57, 138.49 16.7, 154.4 0.72 M131.89 32.33 C139.53 22.49, 149.82 11.32, 157.26 1.03 M129.25 33.92 C138.78 24.39, 146.32 13.97, 158.31 -0.62 M133.8 32.2 C143.24 25.22, 148.61 18.15, 164.76 1.21 M134.95 32.44 C142.27 25.1, 150.67 15.15, 164.39 -0.51 M142.22 34.62 C146.35 23.96, 155.68 15.56, 167.67 -1.35 M141.43 33.72 C149.62 23.45, 158.47 12.87, 169.58 0.88 M147.06 35.65 C152.18 23.18, 162.67 13.77, 176.45 0.37 M144.7 33.31 C157.28 20.06, 168.78 7.85, 175.96 -1.13 M152.62 34.34 C162.45 19.11, 173.84 6.26, 178.42 -0.59 M150.6 34.04 C160.9 21.96, 170.44 12.02, 179.77 -0.43 M154.19 33.47 C164.29 25.5, 171.44 16.08, 181.6 7.93 M156.97 33.51 C163.04 24.11, 170.72 16.51, 179.92 6.97 M163.19 34.69 C168.8 25.26, 175.4 18.41, 179.08 11.9 M161.54 33.14 C166.01 29.1, 168.88 25.48, 180.04 12.28 M168.49 35.02 C171.52 29.2, 174.32 24.73, 179.9 19.81 M166.84 33.46 C170.82 29.54, 174.64 24.46, 179.94 18.68 M173.51 33.26 C175.95 30.37, 177.95 26.53, 180.96 25.24 M172.59 32.74 C175.79 30.16, 178.49 26.42, 179.96 24.84 M177.36 33.79 C178.5 32.16, 179.21 31.29, 180.15 31.02 M177.39 33.81 C178.17 32.71, 178.96 31.92, 179.99 30.76" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M1.95 -0.36 C53.75 -2.15, 110.45 1.5, 178.38 -0.72 M-0.28 -0.67 C47.74 1.07, 96.96 1.11, 180.78 -0.29 M180.5 0.28 C178.21 7.85, 181.71 15.34, 180.27 30.74 M180.21 -0.72 C181.21 11.25, 179.51 23.22, 179.13 31.36 M179.9 30.87 C137.58 29.66, 91.44 31.38, -0.52 31.94 M180.94 31.1 C134.74 30.55, 87.32 31.03, 0.54 30.05 M1.01 29.79 C1.49 22.39, 1.59 12.75, -1.34 -0.84 M0.51 30.76 C-0.42 18.38, -0.44 7.72, -0.92 -0.77" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(290.1667175292969 729.2242875921036) rotate(0 12.5 10.5)"><text x="12.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[n]</text></g><g stroke-linecap="round" transform="translate(234.33331298828125 783.0576310979629) rotate(0 98.00007629394531 19.666732788085938)"><path d="M-0.81 -1.92 C62.7 2.09, 121.1 -0.36, 195.36 0.28 M195.02 0.44 C196.9 10.45, 197.46 19.3, 195.25 38.22 M194.39 39.05 C125.69 38.67, 51.89 39.34, 1.41 40.75 M1.98 38.86 C-1.5 27.14, -1.82 14.64, -1.1 0.06" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(245.66659545898438 792.7242265569473) rotate(0 85 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMMemoryInstance</text></g><g stroke-linecap="round"><g transform="translate(761.5000457763672 209.14082201593166) rotate(0 -235.1008458497821 -39.01886975046375)"><path d="M-0.75 0.17 C-46.46 -12.18, -196.76 -64.36, -275.04 -75.04 C-353.32 -85.73, -437.84 -66.07, -470.41 -63.94 M1.06 -0.79 C-44.22 -12.91, -194.16 -63.48, -272.87 -73.88 C-351.59 -84.28, -438.35 -64.77, -471.26 -63.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(761.5000457763672 209.14082201593166) rotate(0 -235.1008458497821 -39.01886975046375)"><path d="M-444.17 -78.4 C-451.98 -73.97, -458.88 -70.9, -470.23 -62.31 M-443.51 -75.75 C-453.75 -71.48, -463.99 -65.95, -470.45 -63.4" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(761.5000457763672 209.14082201593166) rotate(0 -235.1008458497821 -39.01886975046375)"><path d="M-441.79 -58.02 C-449.98 -58.34, -457.44 -60.02, -470.23 -62.31 M-441.13 -55.37 C-452.14 -58.72, -463.27 -60.81, -470.45 -63.4" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(749.5512229860934 386.3933010586473) rotate(0 -181.67109641309762 95.6091543283861)"><path d="M-1.17 -0.18 C-23.58 30.46, -73.38 160.03, -133.81 184.93 C-194.24 209.83, -325.53 155.34, -363.76 149.22 M0.42 -1.32 C-21.69 30.02, -71.37 161.62, -131.68 186.39 C-191.98 211.16, -322.82 153.49, -361.41 147.29" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(749.5512229860934 386.3933010586473) rotate(0 -181.67109641309762 95.6091543283861)"><path d="M-331.78 143.39 C-342.24 143.92, -351.2 145.6, -361.75 147.92 M-331.94 146.05 C-337 146.07, -343.11 146.16, -361.96 146.59" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(749.5512229860934 386.3933010586473) rotate(0 -181.67109641309762 95.6091543283861)"><path d="M-337.44 163.11 C-346.09 156.76, -353.05 151.49, -361.75 147.92 M-337.6 165.78 C-341.66 161.79, -346.6 157.83, -361.96 146.59" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(697.1667327880859 550.8075548040176) rotate(0 92 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMExportTabInstance</text></g><g stroke-linecap="round" transform="translate(695.8333358764648 570.4742265569473) rotate(0 88.66665649414061 60.500030517578125)"><path d="M1.12 -0.79 C66.02 -2.18, 135.42 -1.64, 176.35 -1.15 M-0.71 0.06 C45.96 1.47, 92.21 0.85, 177.8 -0.19 M175.42 0.26 C179.21 34.28, 178.4 65.28, 179.23 121.46 M178.07 0.82 C177.5 26.18, 178.64 50.88, 178.09 120.96 M179.19 119.66 C124.24 123.39, 72.2 121.31, 0.05 122.65 M177.05 120.67 C120.78 122.59, 65.03 121.26, 0.58 120.32 M-1.52 121.71 C0.13 84.97, -0.16 48.99, 0.34 -0.23 M-0.09 121.15 C-1.05 88.88, -1.73 58.86, -0.91 0.3" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(709.5000228881836 586.4741655217911) rotate(0 58.5 15.5)"><path d="M-0.79 -1.67 C25.8 -0.6, 53.63 -1.64, 115.85 -0.75 M0.06 -0.63 C25.04 -0.13, 49.38 1.3, 116.81 -0.3 M117.26 1.45 C118.97 11.04, 117.36 22.71, 117.46 29.22 M117.82 -0.92 C117.88 12.3, 117.03 24.9, 116.96 30.91 M115.66 29.5 C80.43 30.12, 41.01 32.13, 1.65 31.3 M116.67 30.29 C92.42 30.04, 65.83 31.25, -0.68 30.93 M0.71 31.53 C-0.34 20.92, -0.86 10.7, -0.23 -0.84 M0.15 30.95 C-0.74 18.41, 0.46 6.36, 0.3 -0.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(715.5000228881836 591.4741655217911) rotate(0 52.5 10.5)"><text x="52.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">char* name </text></g><g stroke-linecap="round" transform="translate(727.1666793823242 630.8075090276504) rotate(0 7.3333282470703125 8.833328247070312)"><path d="M7.16 0.03 C9.8 2.71, 12.07 6.05, 13.7 8.12 M8.05 -0.54 C9.23 2.36, 10.95 3.99, 14.87 9.55 M15.58 9.35 C13.34 11.85, 12.21 11.62, 8.98 18.58 M15.01 9.12 C12.12 12.59, 9.74 15.36, 8.1 18.17 M8.46 16.51 C4.15 14.23, 2.75 10.98, -0.99 9.61 M8.4 17.3 C5.46 15.6, 3.28 12.86, 0.19 8.54 M-0.35 9.14 C1.09 7.17, 3.41 4.44, 9 -0.61 M-0.54 8.56 C2.49 5.84, 4.82 3.65, 7.64 0.22" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(711.8333358764648 623.1408220159317) rotate(0 64 19)"><path d="M0.05 -0.97 C32.38 -0.19, 65.99 -0.77, 126.43 -1.43 M-0.97 -0.54 C39.69 -0.29, 78.14 0.25, 128.98 -0.96 M128.63 0.05 C130.17 12.36, 126.5 25.58, 129.67 39.47 M128.22 -0.23 C128.4 14.49, 127.56 29.26, 128.91 38.93 M126.03 36.69 C98.25 40.15, 68.71 36.81, 1.04 37.44 M127.37 37.33 C94.45 38.18, 59.67 39.19, -0.78 37.24 M0.24 36.89 C0.24 25.02, -0.94 14.15, -1.02 -0.18 M-0.73 38.3 C-0.89 26.31, -0.18 13.43, 0.36 -0.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(754.3333358764648 632.1408220159317) rotate(0 21.5 10.5)"><text x="21.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">table</text></g><g stroke-linecap="round" transform="translate(696.8333206176758 690.6408677922989) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.72 6.62 C1.4 4.36, 2.32 3.43, 4.33 -0.15 M-0.64 6.18 C1.12 5.09, 2.96 2.75, 5.19 0.19 M0.29 10.46 C4 8.51, 6.74 2.38, 9.61 -0.41 M0.11 11.91 C3 9.02, 5.03 6.31, 11.24 -0.78 M0.6 19.56 C4.55 12.41, 11.72 5.18, 15.47 -0.75 M-0.09 18.08 C4.04 11.98, 9.7 7.26, 14.69 0.12 M1.58 24.77 C6.72 15.26, 13.95 8.09, 19.79 1.58 M0.49 25.04 C7.72 14.17, 17.52 5.75, 20.62 0.17 M-1.47 30.4 C5.47 22.89, 10.6 18.28, 27.44 2.17 M0.95 31.15 C10.66 19.46, 19.94 7.6, 26.72 0.95 M3.43 34.85 C8.49 28.77, 12.47 18.96, 30.26 -0.31 M2.65 34.53 C11.69 21.11, 23.99 10.16, 31.37 0.19 M7.57 35.78 C18.14 21.88, 27.16 11.84, 38 0.41 M6.66 33.3 C15.88 25.34, 23.59 14.41, 36.83 -0.16 M11.29 35.2 C19.47 25.65, 27.64 17.02, 41.95 0.71 M13.32 34.28 C24.11 19.54, 37.53 5.81, 41.78 -0.77 M17.06 32.99 C26.06 23.91, 37.5 15.05, 46.22 -0.31 M18.19 33.23 C24.83 26.14, 33.03 16.54, 48.33 -0.63 M23.85 35.22 C30.61 24.22, 38.81 14.58, 51.36 1.7 M24.24 34.75 C34.09 21.2, 46.07 8.6, 52.59 0.1 M28.36 32.73 C37.69 25.53, 45.23 15.1, 57.55 0.9 M27.94 33.59 C39.59 21.6, 48.91 9.7, 57.64 0.32 M34.01 34.43 C40.75 26.23, 49.26 15.61, 64.33 -0.15 M34.09 33.53 C41.06 25.51, 49.66 14.28, 64.12 -0.75 M39.44 34.08 C47.56 24.26, 53.58 15.17, 69.75 2.05 M39.17 34.92 C47.42 24.69, 55.42 16.09, 69.22 0.62 M44.96 35.21 C53.58 26.27, 60.19 15.14, 74.07 -1.48 M43.6 35.1 C53.68 24.14, 60.94 14.58, 75.25 -0.15 M51.61 34.28 C62.33 21.52, 73.03 10.25, 78.94 0.35 M49.68 34.41 C58.71 24.45, 66.16 15.26, 78.64 0.36 M56.31 33.38 C67.69 20.04, 79.06 9.63, 83.1 1.24 M54.59 34.38 C65.57 22.97, 75.2 10.91, 84.46 0.7 M59.56 34.71 C71.04 23.57, 78.92 11.93, 89.58 -1.88 M60.9 34.95 C70.45 23.4, 78.96 12.03, 89.52 0.83 M64.63 33.17 C75.5 22.47, 86.63 13.38, 97.33 1.67 M65.65 34.71 C75.94 22.09, 87.13 9.1, 94.8 -0.71 M69.28 34.92 C80.09 24.74, 84.98 16.97, 100.47 0.88 M70.81 34.09 C79 23.96, 87.59 14.71, 100.57 -0.52 M76.86 33.94 C83.74 27.36, 88.76 18.58, 107.96 1.64 M76.41 33.61 C86.98 20.46, 99.39 8.28, 106.88 -1.21 M80.11 34.61 C91.31 20.28, 104.55 10.43, 110.77 -0.72 M80.97 33.06 C92.35 22.24, 102.81 10.77, 110.59 0.92 M88.27 36.24 C95.15 25.34, 98.94 18.98, 116.92 1.89 M86.61 33.75 C94.55 24.93, 104.11 14.51, 117.25 -0.23 M90.77 35.65 C101.06 26.4, 105.03 17.42, 121.96 -0.87 M91.52 33.73 C100.77 25.81, 108.4 16.29, 121.43 -0.05 M96.47 35.75 C103.75 26.25, 111.07 18.9, 125.43 1.06 M97.05 34 C104.67 24.77, 113.28 17.11, 126.01 0.24 M101.29 32.05 C108.8 27.29, 118.82 18, 131.88 -0.59 M102.18 33.69 C109.35 25.96, 116.25 19.75, 133.06 0.54 M107.42 33.31 C114.68 25.64, 121.48 17.32, 136.08 2.19 M108.61 34.37 C117.99 23.28, 126.81 13, 137.87 1.12 M115.04 31.99 C122.46 22.93, 132.19 12.33, 144.71 -1.77 M113.25 33.17 C124.63 20.82, 136.22 8.06, 142.49 0.81 M117.44 32.92 C129.3 24.87, 139.52 13.1, 149.49 -0.26 M119.26 35.08 C127.61 23.6, 138.38 11.99, 147.75 0.26 M124.76 35.79 C130.78 24.01, 138.52 17.41, 152.97 -1.12 M124.6 34.08 C130.55 27.47, 137.43 18.46, 152.82 0.09 M131.16 35.75 C136.03 24.16, 145.54 13.95, 157.6 -1.68 M129.04 33.48 C137.26 24.97, 146.31 15.88, 159.18 0.18 M134.51 33.93 C143.88 22.87, 153.6 9.06, 163.53 -0.2 M134.69 33 C144.54 22.21, 152.48 12.3, 164.23 -0.16 M139.58 34.09 C149.94 22.29, 157.04 13.62, 169.7 -1.3 M139.05 35.12 C146.12 27.04, 151.33 21.43, 169.25 1.07 M145.06 33.82 C156.54 23.02, 164.55 9.72, 175.59 0.58 M144.89 34.94 C155.82 21.98, 165.92 11.45, 174.99 0.73 M150.04 33.43 C161.72 21.53, 168.99 12.55, 178.41 -0.21 M150.51 34.72 C161.89 21.35, 172.59 8.38, 179.64 -0.2 M154.47 34.74 C164.46 25.03, 173.51 11.45, 180.82 6.77 M155.12 35.32 C164.7 25.43, 173.03 14.67, 180.51 6.36 M160.2 34.39 C169.63 27.19, 174.69 15.86, 179.22 12.75 M161.67 33.16 C168.34 25.71, 174.91 18.8, 181.08 12.97 M164.18 34.4 C169.61 31.43, 173.71 28.66, 178.41 16.75 M166.91 33.48 C169.04 30.55, 173.06 27.52, 179.54 19.23 M172 34.51 C174.61 30.68, 177.63 26.55, 180.07 23.27 M171.21 34.35 C174.39 29.98, 178.49 26.25, 180.06 23.9 M176.5 34.79 C177.97 33.87, 178.23 32.74, 180.35 31.07 M176.85 34.49 C177.71 33.27, 178.54 32.27, 179.83 30.54" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M-0.99 -1.15 C39.73 -0.86, 79.38 -0.56, 180.13 -1.26 M0.46 -0.19 C55.19 1.33, 111.97 0.01, 180.13 0.72 M181.89 0.46 C178.33 14.18, 181.77 26.25, 181.65 30.49 M180.75 -0.04 C179.98 11.9, 180.99 24.35, 179.33 31.58 M180.05 33.99 C119.34 29.47, 59.13 30.59, -0.67 30.91 M180.58 31.65 C113.87 31.46, 47.09 30.37, 0.36 32.6 M0.34 32.1 C-0.88 25.23, -1.06 14.64, 0.31 -0.11 M-0.91 32.63 C0.03 24.93, 0.59 18.54, 0.63 0.75" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(775.8333206176758 696.8075395452286) rotate(0 11 10.5)"><text x="11" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[1]</text></g><g transform="translate(771.9999465942383 670.9742723333145) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(697.1665725708008 724.1409440862442) rotate(0 90 16.166671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.72 6.19 C1.18 4.26, 1.77 3.26, 4.65 -0.03 M0.07 6.69 C0.53 5.37, 1.76 4.09, 5.27 0.74 M0.84 11.54 C2.21 7.26, 6.37 3.84, 11.44 0.24 M0.22 11.62 C3.74 9.02, 5.66 5.61, 11.24 -0.11 M1.04 17.87 C6.23 12.32, 9.28 6.94, 17.15 1.27 M-0.56 18.07 C5.5 12.15, 9.28 7.99, 14.76 0.59 M-0.27 23.26 C8.37 13.87, 17.19 8.37, 22.82 1.88 M0.06 25.02 C7.67 15.79, 13.8 7.94, 21.02 0.77 M-0.45 28.97 C7.82 24.92, 13.78 18.85, 27.28 -0.96 M0.82 29.7 C11.12 18.95, 21.14 5.63, 26.18 0.41 M4.24 31.88 C11.63 20.23, 22.85 11.04, 33.51 -0.68 M1.73 34.56 C12.41 22.49, 21.79 11.99, 32.5 -0.64 M5.43 35.85 C14.87 24.52, 25.59 12.55, 36.11 1.48 M8.35 33.48 C14.22 26.36, 20.83 17.92, 36.49 -0.27 M12.54 34.64 C17.89 26.03, 26.3 21.3, 41.11 0.82 M12.43 34.52 C21.92 22.06, 31.84 11.61, 42.34 -0.96 M17.99 35.36 C27.34 24.44, 32.65 16.29, 49.32 -0.3 M18.66 34.25 C27.65 24.27, 36.39 12.35, 47.92 0.6 M23.68 32.59 C32.49 21.59, 43.63 14.39, 52.13 -0.08 M23.91 33.7 C34.53 21.21, 44.93 9.45, 52.22 0.76 M30.35 32.92 C38.72 23.81, 46.52 15.71, 58.79 1.18 M28.2 33.7 C35.36 25.55, 42.69 17.76, 57.36 1.17 M34.73 34.06 C42.89 24.1, 53 11.98, 64.27 1.5 M34.49 33.91 C43.76 22.97, 54.48 10.04, 64.01 0.08 M38.09 33.56 C46.75 24.45, 59.43 12.35, 68.53 -0.3 M38.91 34.32 C47.83 24.6, 56.68 13.74, 69.38 0.64 M44.89 35.49 C52.51 22.15, 63.18 10.67, 76.36 -0.21 M44.09 33.81 C51.63 26.82, 58.39 18.44, 74.72 0.13 M49.92 35.61 C62.53 20.23, 72.92 7.11, 80.7 1.42 M49.88 34.17 C58.31 23.53, 66.59 15.52, 79.22 0.3 M53.57 35.88 C67.65 19.36, 79.04 9.21, 86.42 0.35 M55.37 34.37 C63.44 24.2, 72.33 15.66, 85.55 0.61 M61.71 32.79 C68.83 24.9, 73.35 17.05, 89.65 -1.16 M60.35 33.88 C69.37 21.81, 81.01 11.03, 89.78 0.52 M64.95 35.87 C75.1 27.12, 83.2 17.65, 97.59 -1.9 M65.29 34.9 C74.06 22.57, 84.02 12.12, 94.88 -1.21 M70.5 32.11 C77.59 26.65, 84.04 19.45, 99.84 0.78 M70.77 33.68 C78.97 25.01, 86.34 15.42, 100.65 -0.26 M77.41 32.41 C87.28 24.28, 98.52 12.61, 108.19 -0.69 M75.5 34.78 C86.83 23.66, 95.36 12.25, 107.25 0.54 M80.47 35.97 C89.08 26.17, 93.76 20.34, 111.94 -1.58 M81.74 34.36 C89.04 25.69, 96.01 18.21, 111.09 -0.51 M85.46 32.8 C97.73 22, 110.14 8.47, 117.04 0.31 M87.32 34.47 C95.5 25.84, 103.21 14.58, 115.71 0.05 M92.98 32.09 C98.39 26.35, 104.18 18.11, 120.72 -0.7 M93.04 34.31 C98.75 26.1, 105 18.9, 121.01 -0.63 M97.77 32.7 C106.3 24.4, 112.87 16.62, 128.06 -1.44 M96.73 34.52 C106.17 24.49, 113.13 15.76, 127.47 -0.16 M104.51 35.55 C110.08 26.18, 115.38 17.94, 133.15 1.27 M102.62 34.46 C110.2 27.08, 116.43 18.52, 132.01 0.06 M107.16 34.09 C114.74 23.66, 126.04 16.14, 136.39 -0.91 M107.39 34.53 C118.26 22.19, 130.05 9.59, 136.93 0.23 M112.73 34.75 C123.39 22.88, 134.1 10.58, 142.34 -1.45 M113.59 33.36 C121.92 24.56, 130.12 16.74, 142.37 0.32 M120.63 35.32 C127.4 27.33, 132.5 18.59, 148.97 1.53 M119.64 34.2 C129.88 21.78, 139.72 9.32, 147.32 -0.58 M122.46 33.45 C133.33 22.15, 142.07 10.34, 153.54 -0.32 M125.26 34.12 C133.34 21.65, 144 11.33, 154.03 -0.02 M129.32 33.05 C140.55 19.89, 150.38 7.37, 157.88 -1.14 M129.48 34.32 C138.44 25.36, 145.79 15.94, 159.04 1.14 M135.65 32.75 C141.47 23.51, 151.37 15.11, 166.19 1.57 M134.08 33.41 C143.13 23.95, 151.56 14.9, 163.59 -1.04 M138.51 32.32 C148.99 24.73, 155.17 12.9, 170.38 -0.59 M139.58 33.72 C146.92 26.58, 153.15 19.77, 168.66 -0.27 M144.78 33.86 C152.44 24.14, 164.4 13.67, 175.87 -0.53 M144.04 35.27 C154.16 23.78, 163.75 13.88, 175.35 0.25 M149.68 32.49 C160.55 22.96, 166.52 16.6, 178.88 0.83 M150.3 34.34 C158.37 23.51, 167.53 14.82, 179.93 1.09 M157.44 33.05 C160.97 28.7, 167.69 21.69, 178.39 7.74 M156.26 35.02 C161.23 27.81, 167.7 20.64, 180.35 5.71 M162.41 33.27 C164.18 27.48, 171.27 24.13, 180.44 12.2 M160.65 34.19 C168.49 27.24, 175.48 17.77, 180.27 11.79 M166.41 36.22 C169.77 29.71, 169.85 26.82, 180.98 18.8 M166.05 34.85 C172.15 28.15, 177.3 23.54, 180.54 17.98 M172.25 33.19 C174.68 30.75, 176.17 29.03, 181.59 23.97 M171.49 34.25 C173.31 31.81, 175 29.68, 180.94 23.96 M177.16 34.27 C177.74 33.76, 178.77 32.53, 180.11 30.4 M176.73 34.25 C177.9 32.97, 178.8 31.75, 180 30.49" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M-1.73 -1.57 C43.69 0.8, 88.96 0.84, 178.07 -1.08 M0.36 0.98 C61.36 0.68, 125.35 1.38, 180.32 0.03 M181.79 1.67 C181.54 14.41, 178.24 26.77, 180.45 31.88 M180.19 0.91 C180.91 11.47, 179.24 24.66, 179.02 31.68 M178.32 33.38 C125.03 31.93, 69.76 33.94, -1.25 31 M180.33 31.55 C114.8 32.56, 51.39 31.92, 0.12 31.78 M1.65 31.31 C-0.14 22.4, -0.07 10.05, -1.45 0.6 M-0.6 32.69 C-0.3 26.21, 0.65 19.52, 0.73 -0.76" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(771.6665725708008 730.3076158391739) rotate(0 15.5 10.5)"><text x="15.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round" transform="translate(697.833381652832 755.1410051214004) rotate(0 90 15.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.08 5.74 C1 4.24, 2.9 2.05, 4.24 -0.07 M-0.59 6.6 C0.96 4.86, 2.86 3.4, 5.03 -0.04 M-1.16 11.02 C3.08 7.48, 7.65 4.56, 10.59 -0.29 M0.6 12.65 C2.84 8.9, 7.65 4.06, 10.92 0.42 M1.04 18.29 C2.26 14.94, 8.44 11.21, 15.68 -0.39 M0.66 17.51 C3.11 15.03, 5.83 11.01, 16.28 0.67 M0.77 22.61 C7.33 19.88, 12.59 13.81, 21.71 1.85 M1.13 23.44 C5.55 17.43, 10.08 13.22, 20.52 -0.11 M1.86 31.67 C9 24.52, 15.21 13.21, 28.13 1.64 M0.98 30.95 C9.27 19.54, 17.4 10.43, 26.78 0.79 M2.03 31.48 C11.27 24.49, 21.86 12.65, 32.45 1.24 M3.62 32.58 C9.31 26.37, 15.4 19.07, 32 0.68 M6.62 34.58 C19.74 19.99, 30.08 8.55, 35.48 -1.59 M7.77 33.41 C15.83 23.14, 24.43 13.43, 36.03 0.94 M12.44 32.5 C22.51 25.81, 28.19 15.65, 43.17 0.77 M12.92 32.33 C19.21 26.07, 25.66 18.25, 42.06 -0.73 M20.3 32.14 C25.15 24.34, 34.53 16.55, 47.92 -1.69 M18.51 34.26 C24.82 24.87, 33.32 17.12, 47.62 0.94 M24.2 31.24 C33.15 26.72, 37.27 17.18, 54.38 1.76 M24.83 32.47 C30.55 26.02, 35.44 19.98, 53.02 -0.88 M30.66 32.81 C38.35 24.67, 46.95 14.64, 56.8 -0.93 M28.95 32.9 C40.11 20.99, 49.77 10.19, 58.34 0.15 M33.87 34.3 C41.44 24.94, 49.2 18.68, 64.77 -2.16 M33.54 34.09 C39.84 26.07, 47.04 19.44, 63.88 -0.22 M38.26 34.34 C51.97 21.36, 59.8 10.04, 68.61 1.75 M40.13 33.82 C49.62 22.29, 58.91 12.75, 69.13 0.52 M43.14 33.38 C55.32 19.89, 70.29 6.49, 73.14 1.01 M45.36 34.56 C56.65 21.23, 68.48 7.56, 75.28 -0.14 M51.8 32.87 C61.86 19.88, 74.05 8.85, 79.01 0.78 M50.79 32.57 C61.88 21.29, 72.56 7.93, 80.12 -0.41 M56.88 31.75 C68.21 21.71, 79.03 8.89, 84.5 -0.39 M55.84 33.11 C67.01 21.77, 77.23 10, 84.57 0.05 M62.14 32.84 C68.79 22.49, 80.17 9.69, 90.83 1.9 M60.3 32.78 C72.35 21.63, 81.75 9.87, 89.6 -0.54 M67.78 35.31 C77.27 24.14, 86.27 11.02, 95.98 0.31 M65.31 32.78 C74.8 22.79, 83.39 11.94, 94.74 0.14 M72.29 33.07 C82.76 21.63, 91.15 11.17, 100.01 0.21 M71.75 33.17 C78.27 24.8, 85.77 17.1, 101.03 -0.16 M77.69 35.28 C87.86 24.87, 97.09 12.12, 106.87 -1.87 M77.31 34.19 C83.79 25.26, 93.26 16.75, 105.48 -0.03 M83.43 32.7 C89.57 25.15, 98.61 13.71, 109.7 -1.83 M82.87 32.52 C92.88 21.45, 101.32 10.63, 112.05 0.97 M87.61 34.23 C99.96 21.23, 110.03 8.85, 115.99 -0.79 M87.53 34.56 C93.1 25.5, 99.63 18.3, 115.46 1.23 M92.88 33.23 C102.67 20.53, 112.89 8.46, 120.17 -0.44 M93.06 32.7 C102.76 21.17, 111.84 9.57, 121.46 0.7 M99.69 32.07 C105.29 25.57, 112.32 16.83, 126.24 -0.27 M98.85 32.66 C105.5 24.47, 113.51 16.09, 126.04 -0.59 M104.13 32.48 C109.81 23.29, 117.87 18.33, 130.86 -0.48 M104.41 33.67 C113.18 22.18, 120.84 12.92, 132.25 -0.53 M107.25 32.06 C119 24.2, 124.28 13.21, 138.74 0.52 M108.32 33.85 C120.11 21.4, 129.12 9.38, 138.23 -0.64 M112.83 34.65 C121.25 25.02, 130.56 12.15, 142.37 -1.49 M114.68 32.43 C122.08 25.7, 127.21 17.93, 142.58 -0.74 M120.75 34.81 C128 23.07, 138.89 12.59, 149.41 1.95 M120.13 33.07 C125.17 25.77, 130.55 18.33, 148.4 1.25 M124.76 32.24 C131.52 23.12, 139.52 16.22, 154.44 0.36 M124.29 32.1 C132.93 23.65, 141.03 14.48, 154.75 0.65 M129.82 32.25 C133.91 26.5, 140.81 18.66, 158.33 -1.21 M130.69 33.83 C136.88 25.63, 144.25 18.03, 158.59 0.3 M133.89 32.14 C142.83 24.85, 152.05 17.86, 163.98 -1.76 M135.33 32.84 C146.79 20.74, 156.88 7.11, 164.28 -0.19 M141.25 33.68 C148.53 21.11, 160.24 11.6, 167.73 2.11 M141.55 33.24 C151.25 22.69, 159.32 10.72, 169.51 -0.15 M143.66 34.3 C157.2 22.14, 168.09 8.53, 175.06 0.64 M145.92 33.69 C158.12 20.89, 168.85 7.84, 174.82 -0.54 M152.97 31.73 C161.32 23.02, 170.89 10.42, 180.01 1.35 M150.44 32.96 C160.51 23.25, 170.37 12.12, 179.53 0.29 M155.66 34.76 C162.27 27.74, 166.82 20.92, 178.99 8.22 M155.81 34.45 C164.24 24.67, 173.47 13.26, 179.31 6.71 M160.07 32.37 C168.99 26.83, 175.45 17.86, 181.21 10.34 M162.26 34.24 C168.87 25.32, 174.38 18.68, 179.2 12.18 M167.65 32.19 C169.24 27.42, 176.45 23.88, 181.46 16.66 M167.47 33.31 C170.96 30.58, 174.46 24.94, 180.08 18.95 M172.66 33.08 C173.57 32.04, 177.7 28.37, 179.25 24.78 M172.23 33.07 C173.8 31.11, 176.31 29.28, 179.98 24.7 M177.59 33.9 C178.75 32.5, 179.45 31.17, 180.16 30.76 M177.48 33.48 C178.11 32.64, 178.91 31.81, 180.03 30.79" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M-1.43 0.13 C46.03 1.58, 92.65 0.33, 180.92 -0.37 M-0.96 0.13 C49.24 -0.94, 97.35 -1.75, 180.95 0.23 M181.47 1.65 C178.44 7.79, 180.72 12.64, 181.51 30.92 M180.93 -0.67 C179.31 9.4, 179.08 17.38, 180.02 31.83 M179.44 30.33 C121.89 33.28, 65.39 30.6, 1.16 29.64 M179.24 31.36 C127.53 29.3, 74.64 29.04, 0.17 30.88 M-0.18 31.31 C-0.36 21.21, -1.71 15.6, -1.82 0.6 M-0.2 31.63 C0.94 23.02, 0.92 12.89, 0.58 0.86" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(775.333381652832 765.1410051214004) rotate(0 12.5 10.5)"><text x="12.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[n]</text></g><g transform="translate(496.5000457763672 650.4744249212051) rotate(0 85.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(WASMTableInstance *)</text></g><g stroke-linecap="round"><g transform="translate(736.8334197998047 638.4742418157364) rotate(0 -34.455977577799935 9.294579118872093)"><path d="M-0.72 -0.69 C-12.42 2.1, -58.41 14.61, -70.01 17.95 M1.1 1.56 C-10.21 5.03, -56.15 16.62, -67.65 19.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(736.8334197998047 638.4742418157364) rotate(0 -34.455977577799935 9.294579118872093)"><path d="M-43.86 1.49 C-50.97 6.05, -56.41 14.2, -67.07 17.43 M-43.09 2.02 C-50.31 6.5, -57.45 12.67, -67.01 19.65" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(736.8334197998047 638.4742418157364) rotate(0 -34.455977577799935 9.294579118872093)"><path d="M-38.99 21.43 C-47.82 19.73, -54.77 21.65, -67.07 17.43 M-38.22 21.96 C-46.86 20.6, -55.42 20.97, -67.01 19.65" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(763.1667327880859 446.2527698473692) rotate(0 -42.13499375757368 64.13821360776171)"><path d="M0.89 0.88 C-12.53 16.57, -69.56 72.86, -81.37 94.05 C-93.17 115.23, -71.89 122.56, -69.93 127.98 M-0.11 0.29 C-13.58 16.1, -70.92 74.01, -82.16 94.97 C-93.39 115.93, -69.6 120.65, -67.52 126.04" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(763.1667327880859 446.2527698473692) rotate(0 -42.13499375757368 64.13821360776171)"><path d="M-82.47 120.71 C-81.71 120.15, -75.23 121.95, -68.47 125.54 M-84.43 119.95 C-77.42 122.33, -72.24 123.45, -67.59 125.83" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(763.1667327880859 446.2527698473692) rotate(0 -42.13499375757368 64.13821360776171)"><path d="M-74.97 111.63 C-75.94 113.2, -71.17 117.09, -68.47 125.54 M-76.93 110.87 C-72.53 116.48, -69.99 120.8, -67.59 125.83" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(460.5000457763672 453.8075548040176) rotate(0 86.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunctionInstance</text></g><g stroke-linecap="round" transform="translate(1096.029450416565 615.4406999456194) rotate(0 114.66668701171875 35.666656494140625)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.5 6.59 C0.65 4.18, 2.98 2.72, 4.92 -0.07 M-0.65 6.06 C1.45 4.46, 3.19 2.46, 4.84 -0.03 M0.85 13.15 C3.1 9.65, 4.83 5.36, 10.18 -0.87 M-0.06 11.61 C3.92 8.19, 7.1 4.57, 10.98 0.75 M0.13 18.46 C4.32 11.99, 8.72 9, 15.38 2.08 M-1.1 18.33 C3.42 14.19, 7.04 10.61, 16.47 -0.24 M-0.31 24.39 C5.08 17.86, 9.85 12.38, 20.55 1.81 M1.1 25.05 C7.57 15.95, 15.63 7.79, 20.99 0.92 M-1.65 31.55 C7.97 20.15, 19.3 9.14, 24.29 1.02 M0.92 30.02 C10.68 19.38, 19.96 6.04, 26.84 -0.6 M-0.22 35.35 C8.88 23.57, 20.49 10.61, 30.09 -1.13 M0.69 36.94 C12.16 22.22, 24.24 9.05, 32.82 0.26 M-0.68 40.96 C10.69 28.81, 24 13.36, 35.51 -0.77 M-0.09 43.36 C8.91 32.54, 15.87 24.23, 37.2 0.01 M0.48 48.04 C16.63 32.78, 32.92 13.54, 41.99 1.11 M-0.5 48.29 C12.14 34.91, 24.04 21.74, 42.25 0.81 M0.21 53.84 C8.5 42.91, 18.96 32.55, 48.17 -0.86 M-0.4 55.14 C10.41 43.5, 20.62 32.66, 47.18 -0.15 M-1.88 61.76 C20.58 37.72, 37.13 17.71, 51.7 -2.09 M0.56 61.06 C13.63 45.25, 27.29 31.13, 52.62 -0.49 M1.7 68.43 C16.24 51.65, 29.19 33.47, 58.55 0.54 M0.74 67.97 C14.77 50.8, 31.06 31.72, 57.59 0.75 M-0.48 71.69 C15.67 55.41, 29.34 37.35, 64.83 -1.02 M1.41 71.28 C19.43 49.72, 40.25 28.62, 63.95 -0.65 M7.15 73.51 C22.03 49.54, 40.17 32.66, 70.09 -1.43 M7.29 72.74 C19.93 56.27, 33 40.24, 69.4 -0.84 M11.18 70.5 C26.29 54.75, 37.84 37.66, 75.15 0.37 M12.27 71.74 C30.49 50.22, 49.56 27.49, 73.93 0.43 M16.91 73.03 C36.62 52.34, 54.12 28.04, 79.38 1.7 M17.71 72.25 C34.17 51.99, 51.16 30.84, 78.78 1.06 M21.71 74.14 C42.13 48.81, 58.88 30.58, 86.57 -1.52 M21.51 72.69 C40.03 50.84, 58.67 29.74, 84.92 -1.1 M28.84 72.04 C40.8 56.44, 54.12 40.06, 90.17 1.75 M28.51 72.14 C39.46 58.07, 52.78 43.8, 90.04 1.03 M32.76 70.53 C52.92 48.76, 71.97 24.73, 95.18 0.05 M33.53 71.66 C51.79 50.07, 70.97 29.06, 94.96 0.02 M36.91 73.42 C63.04 42.38, 86.93 17.49, 99.38 -0.11 M37.78 72.58 C58.44 46.81, 79.1 24.71, 100.68 -0.76 M43.09 72.97 C61.24 52.92, 78.96 32.76, 107.21 0.16 M43.88 71.74 C56.85 55.97, 70.73 40.5, 106.76 -0.9 M48.56 73.12 C65.46 54.85, 81.09 33.4, 111.05 0.62 M47.63 72.58 C67.74 50.11, 86.93 27.65, 110.37 0.41 M54.66 70.1 C70.35 53.26, 85.49 37.3, 116.39 1.01 M54.29 72.6 C72.42 52.05, 91.22 30.4, 116.04 1.3 M57.38 71.19 C80.98 49.54, 101.89 24.45, 122.42 1.79 M59.81 71.97 C72.34 58.25, 84.66 42.13, 121.94 0.86 M66.54 71.87 C82.74 51.36, 101.8 29.43, 128.6 -1.15 M63.66 71.49 C77.96 55.69, 90.89 40.97, 127.15 -0.41 M69.12 74.29 C92.69 47.48, 113.63 18.12, 133.85 0.6 M68.79 72.92 C94.44 45.84, 118.51 16.32, 132.42 -0.53 M77 71.63 C98.23 47.49, 117.68 22.04, 135.86 -1.45 M75.07 72.24 C91.62 54.33, 105.83 36.49, 138.17 0.26 M78.37 70.65 C103.71 42.11, 129.09 15.84, 142.89 -0.41 M79.33 71.93 C93.18 55.7, 107.43 40.29, 143.98 0.72 M85.44 72.02 C103.58 51.83, 118.98 33.05, 149.05 0.58 M86.77 72.25 C106.14 49.83, 125.99 25.49, 148.5 0.96 M89.86 72.86 C111.63 47.47, 133.29 22.68, 154.21 0.64 M90.92 71.56 C103.72 58.13, 116.7 42.77, 152.98 -0.34 M98.42 71.07 C119.31 43.16, 145.48 16.49, 159.18 -0.27 M97.16 71.52 C113.98 50.23, 132.91 29.21, 159.19 0.4 M100.48 71.85 C122.79 47.52, 144.67 22.84, 165.66 -1.02 M100.66 71.46 C113.5 56.67, 127.02 40.16, 164.94 -1.09 M107.67 72.11 C122.89 51.71, 140.95 34.57, 167.43 -0.83 M107.84 71.6 C126.85 49.62, 143.99 27.95, 169.99 -0.63 M113.28 70.89 C130.84 49.73, 150.18 29.57, 174.24 1.17 M112.37 71.36 C129 54.75, 145.48 36.45, 175.57 -0.33 M116.05 73.84 C131.91 54.14, 146.34 38.74, 179.11 0.37 M118.58 72.63 C132.85 54.59, 148.36 37.38, 180.3 -0.27 M123.47 71.61 C136.75 56.57, 148.78 40.33, 186.11 -0.88 M123.51 72.06 C144.75 48.34, 166.18 23.08, 185.73 0.73 M127.6 72.3 C147.26 50.15, 165.94 31.52, 189.72 1.18 M128.3 72.33 C144.18 53.02, 159.9 35.51, 190.21 -0.57 M132.4 71.95 C154.32 47.52, 178.61 22.18, 194.58 0.11 M134.23 72.45 C157.41 43.79, 180.04 18.06, 196.47 -0.56 M137.51 70.88 C153.9 56.04, 166.82 38.56, 202.89 1.77 M138.11 71.01 C156.01 53.1, 170.79 33.45, 201.48 -0.5 M145.59 72.23 C164.84 51.47, 183.62 30.72, 206.13 0.72 M144.34 72.49 C162.34 51, 181.7 29.89, 206 -1.26 M150.12 70.3 C163.66 55.04, 180.81 39.12, 212.43 -1.33 M150.29 72.52 C163.17 58.11, 177 42.82, 212.51 1.03 M154.71 73.09 C179.88 45.39, 202.2 14.75, 218.37 0.9 M154.34 72.21 C173 48.26, 193.76 26.65, 216.71 0.16 M160.28 71.39 C182.62 49, 204.94 21.31, 224.28 -1.26 M158.63 72.1 C173.84 57.02, 188.37 38.93, 223.43 0.2 M163.6 73.52 C187.93 45.93, 211.97 17.93, 230.08 -2.05 M164.38 72.74 C183.26 50.39, 201.05 30.86, 228.15 -1.23 M169.95 74.04 C183.72 55.19, 197.91 42.11, 232.6 3.46 M170.06 72.24 C188.38 51.4, 207.52 30.48, 231.01 1.55 M174.23 72.86 C194.15 52.33, 211.92 31.1, 232 8.79 M175.29 71.27 C194.58 49.29, 215.34 26.23, 230.85 8.56 M182.29 71.77 C195.53 54.06, 213.87 33.92, 231.08 13.93 M181.73 72.33 C198.33 51.86, 216.45 31.75, 231.16 13.94 M184.74 72.8 C200.52 55.93, 213.84 40.54, 231.15 18.87 M185.58 72.07 C197.61 59.13, 208.92 46.3, 231.64 20.25 M190.27 70.69 C204.38 60.07, 213.71 45.09, 230.67 26.23 M190.58 72.55 C207.02 53.83, 222.05 37.38, 231.5 26.99 M195.44 71.34 C208.97 60.22, 217.4 49.79, 232.4 34.49 M196.43 71.5 C206.16 61.56, 214.95 50.25, 232.21 32.64 M202.02 72.23 C208.45 62.49, 218.39 54.76, 229.96 36.62 M201.77 71.65 C211.7 60.29, 222.63 48.54, 230.82 39.18 M206.78 72.86 C216.57 63.6, 224.2 50.54, 232.47 44.81 M208.68 70.98 C213.47 65.57, 219.61 58.23, 232.13 45.64 M210.82 71.19 C217.38 65.48, 225.66 56.47, 233.68 49.66 M213.6 72 C217.31 66.13, 223.75 60.3, 232.58 51.09 M217.37 70.07 C223.21 67.29, 224.66 64.02, 233.28 56.6 M217.85 72.03 C221 68.88, 224.23 65.15, 231.16 55.98 M224.41 73.13 C226.24 70.02, 227.49 68.7, 230.54 64.32 M222.88 72.41 C225.44 68.88, 228.47 66.64, 231.25 63.16" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M0.71 0 C75.59 2.1, 153.26 0.4, 230.69 -1.61 M-0.84 -0.07 C60.93 -0.45, 122 0.31, 228.82 -0.21 M228.47 0.44 C229 25.48, 227.51 48.99, 228.23 69.41 M229.14 0.06 C229.25 26.01, 229.15 53.62, 229.07 71.52 M228.11 72.27 C180.8 71.27, 135 73.1, 0.42 70.68 M228.85 71.01 C143.18 69.95, 56.15 70.57, -0.62 70.49 M0.44 73.32 C-1.79 47.63, 1.23 23.86, -0.57 -1.49 M-0.47 71.08 C0.44 53.33, 0.47 36.37, 0.63 -0.21" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1197.1961374282837 641.5073564397596) rotate(0 13.5 10.5)"><text x="13.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[..]</text></g><g transform="translate(1096.3040761947632 586.8410966741346) rotate(0 105.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunction (per module)</text></g><g stroke-linecap="round"><g transform="translate(664.1667633056641 499.14083727472075) rotate(0 217.55445830263196 59.90798367224636)"><path d="M0.5 -0.88 C39.23 5.05, 158.83 15.25, 231.19 35.52 C303.54 55.78, 400.52 106.55, 434.61 120.7" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(664.1667633056641 499.14083727472075) rotate(0 217.55445830263196 59.90798367224636)"><path d="M403.24 120.23 C411.02 117.42, 416.21 119.73, 433.64 121.79" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(664.1667633056641 499.14083727472075) rotate(0 217.55445830263196 59.90798367224636)"><path d="M411.81 101.58 C417.85 102.55, 421.32 108.61, 433.64 121.79" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1406.500015258789 558.8907914983536) rotate(0 24 14.5)"><path d="M-1.96 0.73 C19.08 -0.02, 32.79 1.46, 47.09 0.57 M0.6 -0.89 C18.18 1.09, 35.25 0.31, 47.24 -0.61 M46.2 -1.03 C49.66 7.7, 46.39 15.83, 48.12 29.36 M48.93 0.37 C48.3 6.28, 47.44 13.09, 47.22 28.05 M46.64 27.97 C31.65 30.13, 19.37 28.26, 1.69 30.6 M48.32 28.75 C35.55 28.84, 21.68 29.75, -0.44 29.48 M-0.53 30.25 C-0.55 18.88, -2.18 6.19, -1.26 0.62 M-0.27 29.95 C-1 21.35, 0.2 13.91, -0.36 -0.65" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1406.1666412353516 592.0574174749161) rotate(0 24 14.5)"><path d="M1.96 0.35 C16.71 1.66, 35.4 0.39, 49.44 -1.75 M0.32 0.8 C10.98 0.45, 22.15 -0.19, 47.4 -0.14 M49.7 0.74 C46.17 7.86, 47.86 12.3, 46.66 28.78 M48.33 -0.47 C47.75 9.4, 47.49 18.67, 48.09 28.58 M46.5 30.41 C37.46 28.3, 26.48 30.35, -0.55 28 M48.63 28.4 C28.99 29.18, 9.86 29.37, 0.8 29.89 M-0.29 29.91 C-1.85 19.28, -1.18 11.7, -0.81 0.05 M-1 28.88 C0.29 19, -0.28 8.41, -0.33 -0.16" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1430.1666412353516 599.7240739690567) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.11 11 C3.75 9.46, 4.78 7.12, 8.6 4.05 M1.82 10.93 C3.76 9.47, 5.16 7.86, 7.71 4.13 M3.57 13.79 C6.98 12.65, 7.18 10.74, 10.07 7.1 M4.54 14.33 C5.33 12.51, 7.26 10.96, 10.12 7.15" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.18 -0.74 C7.91 1.31, 8.21 4.33, 9.78 8.38 M6.4 -0.24 C7.61 2.84, 8.97 6.16, 10.59 8.52 M11.03 8.23 C10.57 10.92, 8.84 12.02, 5.89 18.04 M10.44 8.74 C8.66 12.04, 6.56 15.88, 5.79 17.38 M6.75 18.23 C4.41 16.5, 4.11 13.31, -0.53 9.98 M5.68 17.58 C4.19 14.59, 2.29 12.37, 0.47 9.05 M0.49 7.96 C1.17 5.87, 3.56 3.65, 6.03 0.47 M-0.07 9.11 C1.54 6.41, 2.84 3.97, 5.91 -0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1405.8333282470703 625.3907609807754) rotate(0 24 14.5)"><path d="M-1.45 1.83 C15.24 0.48, 33.75 -1.83, 46.77 1.19 M-0.47 0.02 C9.37 -1, 19.67 -0.53, 47.06 -0.9 M46.43 1.9 C48.37 7.57, 46.9 14.19, 48.77 30.86 M47.48 -0.41 C47.32 8.82, 48.19 19.11, 47.42 28.32 M49.06 28.54 C37.76 30.94, 23.59 28.34, 1.85 29.65 M47.83 29.3 C34.35 29.2, 22.38 29.6, 0.09 28.74 M-1.93 28.24 C-1.21 19.11, -0.76 8.03, 0.87 -0.54 M0.21 28.97 C-0.07 16.89, -0.04 5.92, -0.06 0.33" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1404.4999542236328 653.0574174749161) rotate(0 24 14.5)"><path d="M1.83 -0.91 C19.67 1.79, 36.45 -0.88, 49.19 -1.78 M0.02 -0.76 C15.31 -0.37, 31.7 -0.71, 47.1 -0.52 M49.9 0.12 C48.47 9.82, 47.89 23.09, 49.86 29.73 M47.59 -0.78 C46.92 9.76, 47.44 18.76, 47.32 28.48 M47.54 30.69 C38.8 28.7, 25.4 31.11, 0.65 28.5 M48.3 28.56 C31.05 29.72, 14.03 29.01, -0.26 29.62 M-0.76 27.74 C0.49 19.91, -0.08 13.31, -0.54 1.9 M-0.03 28.64 C-0.62 22.86, -0.12 17.31, 0.33 -0.54" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1427.1666412353516 661.3907609807754) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.94 11.06 C2.42 10.22, 4.38 7.41, 7.46 3.66 M2.08 11.26 C3.89 8.78, 5.37 6.9, 7.83 3.93 M4.75 13.45 C6.41 12.6, 6.59 10.59, 10.62 6.84 M4.08 14.46 C6.39 11.77, 8.28 9.46, 9.93 7.52" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.54 0.29 C8.15 1.93, 8.28 6.28, 9.77 9.32 M5.61 -0.31 C7.43 3.34, 9.02 6.38, 10.41 9.43 M10.73 9.18 C8.37 11.86, 7.83 15.8, 6.36 18 M10.28 8.53 C9.49 10.97, 7.97 13.03, 5.75 17.3 M6.89 18.51 C3.44 13.91, 2.48 11.57, -0.26 9.67 M5.77 17.92 C5 16.07, 3.18 13.39, 0.33 8.92 M-0.68 9.34 C1.72 5.94, 4.71 2.51, 7.03 -1.08 M-0.19 8.65 C1.53 6.33, 3.4 4, 5.71 -0.49" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1428.500015258789 630.3074632512833) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.03 10.18 C4.51 8.71, 5.04 6.32, 7.33 4.05 M2.22 11.19 C3.58 8.78, 5.54 6.7, 7.59 3.77 M3.4 15.07 C5.56 12.17, 6.57 11.36, 9.48 8.12 M4.41 14.25 C6.12 11.81, 8.21 9.81, 10.17 7.7" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.29 0.73 C6.26 1.45, 8.81 3.21, 10.99 9.81 M5.69 -0.3 C7.11 1.83, 7.9 4.32, 11.1 9.19 M10.84 8.34 C9.61 11.3, 9.6 13.2, 6.33 17.21 M10.2 9.05 C9.27 10.82, 7.98 13, 5.63 18.01 M6.84 17.38 C3.37 15.63, 2.12 11.33, 0.67 8.37 M6.26 18.09 C4.74 15.23, 2.43 13.06, -0.08 9.24 M0.34 8.56 C1.28 7.68, 2.19 6.4, 4.92 -0.13 M-0.35 8.82 C1.84 6.1, 4.04 2.95, 5.51 -0.1" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1378.1667938232422 531.4741655217911) rotate(0 49.333343505859375 88.66667175292969)"><path d="M24.67 0 M24.67 0 C45.43 -1.89, 62.09 1.05, 74 0 M24.67 0 C34.61 -0.37, 44.73 -1.01, 74 0 M74 0 C89.25 -0.29, 96.78 6.43, 98.67 24.67 M74 0 C89.26 1.95, 99.51 6.42, 98.67 24.67 M98.67 24.67 C97.4 74.98, 99.51 127.59, 98.67 152.67 M98.67 24.67 C98.57 67.35, 98.32 109.91, 98.67 152.67 M98.67 152.67 C98.85 168.27, 89.28 175.97, 74 177.33 M98.67 152.67 C97.48 167.39, 92.07 178.56, 74 177.33 M74 177.33 C59.77 176.73, 48.51 178.38, 24.67 177.33 M74 177.33 C60.26 177.34, 46.4 177.52, 24.67 177.33 M24.67 177.33 C9.83 179.11, 0.18 168.58, 0 152.67 M24.67 177.33 C9.66 177, 1.05 166.9, 0 152.67 M0 152.67 C0 119.19, 1.68 85.07, 0 24.67 M0 152.67 C1.48 102.05, 0.91 50.85, 0 24.67 M0 24.67 C-0.65 7.91, 8.09 0.67, 24.67 0 M0 24.67 C-1.25 6.14, 7.81 -1.97, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1519.8704613579644 367.0852868054282) rotate(0 35.177210150509666 -0.9148575513004289)"><path d="M-0.74 0.72 C10.61 0.79, 56.99 -0.24, 68.94 -0.63 M1.08 0.05 C12.71 -0.16, 59.49 -2.45, 71.09 -2.55" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1519.8704613579644 367.0852868054282) rotate(0 35.177210150509666 -0.9148575513004289)"><path d="M44.43 6.81 C54.33 6.21, 63.11 0.51, 69.57 -3.78 M42.34 8.07 C50.79 6.54, 55.85 4.45, 71.15 -2.37" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1519.8704613579644 367.0852868054282) rotate(0 35.177210150509666 -0.9148575513004289)"><path d="M43.79 -13.7 C53.75 -6.67, 62.77 -4.73, 69.57 -3.78 M41.69 -12.44 C50.28 -9.03, 55.49 -6.2, 71.15 -2.37" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(1426.833511352539 609.8075242864395) rotate(0 -52.90143446885048 1.9388250406831844)"><path d="M-0.39 -0.19 C-17.89 0.62, -87.81 3.6, -105.41 4.07" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(1426.833511352539 609.8075242864395) rotate(0 -52.90143446885048 1.9388250406831844)"><path d="M-77.92 -7.32 C-84.35 -5.4, -94.17 -1.7, -107.12 2.72" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(1426.833511352539 609.8075242864395) rotate(0 -52.90143446885048 1.9388250406831844)"><path d="M-77.19 13.19 C-83.68 9.69, -93.69 7.98, -107.12 2.72" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1509.8704918755425 357.75197381714696) rotate(0 6.666656494140625 5.833335876464844)"><path d="M0.26 1.55 C0.26 1.55, 0.26 1.55, 0.26 1.55 M0.26 1.55 C0.26 1.55, 0.26 1.55, 0.26 1.55 M0.65 7.19 C1.57 4.97, 4.28 4.16, 5.25 1.91 M0.65 7.19 C1.89 6.37, 3.04 4.78, 5.25 1.91 M1.71 12.08 C5.03 8.04, 5.65 6.77, 10.23 2.27 M1.71 12.08 C5.46 7.99, 8.08 3.74, 10.23 2.27 M7.35 11.69 C10.17 7.94, 13.63 5.02, 15.22 2.63 M7.35 11.69 C9.17 8.71, 12.46 6.27, 15.22 2.63" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M2.92 0 M2.92 0 C6.29 0.7, 9.41 0.39, 10.42 0 M10.42 0 C10.9 -0.02, 14.91 0.55, 13.33 2.92 M13.33 2.92 C13.63 4.79, 13.74 6.48, 13.33 8.75 M13.33 8.75 C12.25 9.45, 14.24 11.66, 10.42 11.67 M10.42 11.67 C9.51 11.88, 6.46 11.07, 2.92 11.67 M2.92 11.67 C2.68 13.19, -1.24 10.53, 0 8.75 M0 8.75 C0.25 6.69, 0.18 4.84, 0 2.92 M0 2.92 C0.9 0.73, -0.67 -1.71, 2.92 0" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(1339.2039744059243 505.9929117918648) rotate(0 88 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::functions</text></g><g stroke-linecap="round" transform="translate(1672.4258931477864 157.650120128589) rotate(0 35.000030517578125 12.833343505859375)"><path d="M1.9 -0.25 C21.27 0.13, 42.01 0.25, 68.79 -1.69 M-0.09 -0.42 C25.4 1.3, 50.17 -0.34, 69.1 0.17 M70.9 -0.01 C71.04 6.87, 71.24 14.79, 68.32 25.02 M70.89 0.58 C70.92 9.73, 70.46 20.3, 69.3 25.18 M69.39 27.61 C49.37 24.69, 31.07 25.44, -0.09 25.55 M70.41 24.83 C52.77 26.49, 38.11 26.01, -0.34 24.98 M1.44 24.03 C1.54 21.48, -0.15 15.6, -0.97 0.91 M-0.43 26.22 C-0.24 17.68, -0.29 9.7, 0.92 -0.97" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1655.4259847005208 129.2334941520265) rotate(0 49.333343505859375 76.50001525878906)"><path d="M24.67 0 M24.67 0 C40.75 1.67, 53.12 0.24, 74 0 M24.67 0 C36.67 -1.19, 49.26 -0.27, 74 0 M74 0 C89.75 -1.95, 96.94 9.12, 98.67 24.67 M74 0 C90.43 1.49, 98.74 9.94, 98.67 24.67 M98.67 24.67 C99.59 62.16, 97.69 100.79, 98.67 128.33 M98.67 24.67 C100 62.04, 98.88 98.36, 98.67 128.33 M98.67 128.33 C98.5 145.45, 89.32 152.39, 74 153 M98.67 128.33 C100.9 144.55, 89.77 155.22, 74 153 M74 153 C57.46 152.34, 44.19 153.8, 24.67 153 M74 153 C64.14 153.42, 52.33 152.61, 24.67 153 M24.67 153 C6.65 153.45, -1 146.21, 0 128.33 M24.67 153 C6.34 154.84, 1.73 144.68, 0 128.33 M0 128.33 C0.45 92.47, -0.78 51.73, 0 24.67 M0 128.33 C-0.05 90.84, 0.9 53.8, 0 24.67 M0 24.67 C-1.09 9.51, 6.92 0.98, 24.67 0 M0 24.67 C1.74 10.2, 9.05 0.73, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1666.759538438585 331.6039012565187) rotate(0 79.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::globals</text></g><g stroke-linecap="round" transform="translate(1667.7594197591145 195.40021931071792) rotate(0 35.000030517578125 12.833343505859375)"><path d="M0.64 1.04 C24.38 -1.37, 50.92 0.37, 70.2 -1.03 M-0.17 0.01 C28.54 -0.16, 54.58 0.08, 70.35 0.2 M69.12 -1.58 C69.15 7.93, 71.82 18.41, 70 24.82 M70.89 -0.54 C69.43 10.08, 69.93 20.03, 70.42 25.23 M70.75 25.16 C53.17 26.71, 34.49 25.21, 0.47 27.09 M69.43 25.75 C52.32 25.98, 35.56 24.82, 0.2 25.72 M-0.1 25.47 C0.98 16.09, 0.18 11.42, -0.01 -1.06 M-0.24 26.54 C0.07 18.74, -1.03 13.14, 0.35 -0.76" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1674.4261678059895 230.73353229899917) rotate(0 35.000030517578125 12.833343505859375)"><path d="M1.04 -1.92 C25.89 -1.92, 54.65 -0.02, 68.97 1.91 M0.01 0.86 C18.03 -0.67, 36.61 0.47, 70.2 0.81 M68.42 -1.02 C67.99 11.06, 68.68 18.83, 69.15 27.43 M69.46 -0.54 C69.89 7.37, 69.87 15.24, 69.56 25.32 M69.5 27.4 C56.29 27.54, 39.66 26.4, 1.42 24.48 M70.09 24.84 C42.8 24.53, 14.21 25.47, 0.05 25.67 M-0.2 26.62 C-1.71 18.37, 1.34 10.74, -1.06 -1.11 M0.87 25.78 C-0.65 16.56, 0.02 9.77, -0.76 -0.76" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1591.8705071343315 358.75197381714696) rotate(0 8 9.500045776367188)"><path d="M8.33 0.84 C10.04 0.81, 12.15 1.69, 13.5 3.06 C14.85 4.44, 16.38 7.22, 16.43 9.1 C16.48 10.97, 14.96 12.65, 13.83 14.31 C12.7 15.98, 11.29 18.55, 9.65 19.09 C8.02 19.63, 5.57 18.27, 4.04 17.55 C2.5 16.82, 1.17 16.34, 0.45 14.75 C-0.28 13.15, -0.76 10.08, -0.31 7.97 C0.13 5.86, 1.59 3.47, 3.13 2.09 C4.68 0.72, 7.77 -0.21, 8.95 -0.3 C10.13 -0.39, 9.98 1.33, 10.22 1.56 M12.2 2.15 C13.57 2.93, 15 4.91, 15.51 6.48 C16.02 8.06, 15.62 9.66, 15.26 11.6 C14.9 13.55, 14.48 16.86, 13.35 18.17 C12.22 19.48, 10.38 19.78, 8.48 19.46 C6.58 19.15, 3.61 17.61, 1.95 16.29 C0.3 14.97, -1.11 13.37, -1.44 11.56 C-1.77 9.74, -1.31 7.31, 0 5.41 C1.3 3.52, 4.53 0.96, 6.38 0.18 C8.23 -0.61, 10.18 0.68, 11.1 0.71 C12.02 0.74, 11.65 0.32, 11.88 0.36" stroke="none" stroke-width="0" fill="#7950f2"></path><path d="M5.22 -0.11 C6.59 -1.08, 9.03 -0.84, 10.69 -0.21 C12.35 0.41, 14.42 1.67, 15.19 3.65 C15.96 5.63, 15.45 9.51, 15.29 11.66 C15.12 13.8, 15.21 15.42, 14.19 16.52 C13.17 17.63, 11.01 18.06, 9.15 18.28 C7.29 18.49, 4.5 19.07, 3.04 17.82 C1.58 16.58, 0.83 12.87, 0.41 10.83 C-0.02 8.8, -0.57 7.27, 0.48 5.62 C1.53 3.96, 5.67 1.77, 6.7 0.89 C7.73 0.02, 6.67 0.32, 6.66 0.38 M6.65 0.15 C8.28 -0.26, 10.4 -0.27, 11.86 0.78 C13.31 1.84, 14.67 4.66, 15.36 6.48 C16.04 8.3, 16.39 9.98, 15.98 11.7 C15.57 13.42, 14.54 15.55, 12.88 16.79 C11.23 18.02, 8.12 19.51, 6.04 19.09 C3.97 18.67, 1.55 15.75, 0.45 14.29 C-0.65 12.82, -0.93 12.22, -0.55 10.3 C-0.17 8.38, 1.55 4.58, 2.73 2.76 C3.9 0.95, 5.85 -0.09, 6.5 -0.56 C7.14 -1.04, 6.65 -0.19, 6.58 -0.1" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1602.0187208387588 364.75202807061913) rotate(0 29.761134833707672 -77.71932307722645)"><path d="M-0.4 -0.2 C4.02 -20.5, 16.18 -96.42, 26.23 -122.26 C36.29 -148.1, 54.24 -149.85, 59.93 -155.24 M1.58 -1.35 C5.89 -21.44, 15.76 -95.44, 25.31 -120.89 C34.86 -146.34, 53 -148.64, 58.88 -154.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1602.0187208387588 364.75202807061913) rotate(0 29.761134833707672 -77.71932307722645)"><path d="M43.38 -135.58 C47.38 -141.51, 51.7 -145.75, 59.64 -155.86 M43.91 -136.49 C48.85 -142.91, 56.02 -149.01, 58.64 -154.3" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1602.0187208387588 364.75202807061913) rotate(0 29.761134833707672 -77.71932307722645)"><path d="M35.12 -149.63 C41.32 -151.7, 47.89 -152.12, 59.64 -155.86 M35.65 -150.53 C43.6 -151.66, 53.87 -152.47, 58.64 -154.3" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1692.6109347873262 390.3166782883112) rotate(0 35.000030517578125 12.833343505859375)"><path d="M-0.98 1.8 C18.27 -0.48, 39.05 -1.16, 68.35 -1.35 M-0.03 0.18 C17.59 -0.39, 36.73 -0.73, 70.15 -0.21 M68.23 -1.45 C68.62 6.41, 68.33 13.99, 71.88 25.26 M69.21 -0.51 C70.86 7.49, 69.21 15.8, 69.29 26.05 M69.04 25.76 C56.51 25.43, 42.16 24.34, 0.73 25.09 M69.8 24.84 C44.72 26.58, 17.34 25.5, 0.35 26.02 M0.46 25.58 C-0.42 15.46, 0.58 6.33, -0.02 1.41 M0.63 26.17 C0.8 17, 0.31 7.91, -0.95 0.45" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1675.6110263400606 361.9000523117487) rotate(0 49.333343505859375 76.50001525878906)"><path d="M24.67 0 M24.67 0 C40.56 -0.92, 52.61 0.44, 74 0 M24.67 0 C36.76 0.53, 50.32 0.3, 74 0 M74 0 C90.8 -0.64, 98.71 10.05, 98.67 24.67 M74 0 C89.71 0.33, 98.18 8.44, 98.67 24.67 M98.67 24.67 C97.28 56.36, 97.2 89.19, 98.67 128.33 M98.67 24.67 C99.58 45.79, 100.19 66.44, 98.67 128.33 M98.67 128.33 C97.65 146.58, 90.34 151.51, 74 153 M98.67 128.33 C100.32 143.15, 91.33 150.82, 74 153 M74 153 C57.07 153.64, 39.06 153.67, 24.67 153 M74 153 C64.78 151.9, 55 152.66, 24.67 153 M24.67 153 C6.57 154.14, 0.68 142.85, 0 128.33 M24.67 153 C6.51 153.81, 0.81 145.84, 0 128.33 M0 128.33 C-0.57 99.7, -1.8 72.57, 0 24.67 M0 128.33 C0.65 106.11, -0.52 82.96, 0 24.67 M0 24.67 C1.01 10.21, 9.55 1.02, 24.67 0 M0 24.67 C2.11 6.05, 9.27 0.18, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1633.7593587239583 101.90029178996596) rotate(0 78 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::tables</text></g><g stroke-linecap="round" transform="translate(1686.2407124837239 430.99273504422484) rotate(0 35.000030517578125 12.833343505859375)"><path d="M-0.25 0.2 C16.65 -1.24, 33.79 -0.48, 70.39 1.17 M0.02 0.91 C20.47 0.37, 41.37 0.32, 70.19 0.06 M68.47 -1.72 C67.92 7.3, 69.41 10.73, 69.69 26.77 M69.95 -0.75 C70.59 4.96, 70.25 10.39, 70.45 26.6 M69.11 26.57 C50.37 26.7, 34.14 27.36, -1.92 27.31 M70.34 24.7 C49.65 26.41, 31.15 26.53, -0.29 26.14 M-1.32 26.17 C-1.55 17.36, 1.42 10.36, 1.56 -1.06 M0.66 26.18 C0.79 15.41, 0.32 7.12, -0.16 -0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1692.9074605305989 466.3260480325061) rotate(0 35.000030517578125 12.833343505859375)"><path d="M0.2 -0.92 C25.64 -1.26, 53.68 0.48, 71.17 -0.06 M0.91 -0.32 C22.4 -0.23, 44.6 0.18, 70.06 -0.89 M68.28 -1.89 C71.69 5.44, 69.69 11.38, 71.1 24.08 M69.25 0.72 C69.52 6.78, 69.28 13.25, 70.93 25.19 M70.91 23.69 C49.4 24.78, 28.72 23.44, 1.65 25.27 M69.04 24.92 C55.13 26.26, 40.02 25.62, 0.47 25.9 M0.51 24.1 C0.04 19.49, 1.34 12.05, -1.06 1.26 M0.51 26.58 C-1.2 17.12, -0.18 7.51, -0.03 -0.85" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1037.8333435058594 235.80750139825568) rotate(0 8.66668701171875 6.500007629394531)"><path d="M10.67 -0.17 L16.1 8.99 L7.53 13.21 L1.22 6.79" stroke="none" stroke-width="0" fill="#12b886" fill-rule="evenodd"></path><path d="M9.84 0.55 C12.06 2.6, 13.18 3.25, 18.13 6.07 M9.09 -0.5 C10.86 1.75, 13.65 4.1, 17.47 6.49 M17.26 6.29 C14.41 8.96, 13.54 9.83, 9.39 13.08 M17.61 6.49 C15.17 8.47, 13.76 10.1, 8.64 12.6 M8.99 12.18 C6.36 11.32, 3.42 8.47, -0.13 5.96 M8.68 13.29 C7.43 11.24, 4.82 10.32, -0.26 7.33 M-1 6.94 C2.6 4.91, 5.92 2.58, 9.18 -0.32 M-0.16 6.52 C2.47 5.35, 6.17 2.67, 8.68 0.04" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1039.8333435058594 252.14082964532597) rotate(0 8.66668701171875 6.500007629394531)"><path d="M8.83 -1.24 L19.32 5.53 L9.21 14.22 L-0.21 8.37" stroke="none" stroke-width="0" fill="#12b886" fill-rule="evenodd"></path><path d="M9.55 0.7 C12.72 2.09, 14.58 6.02, 16.4 6.77 M8.5 -0.44 C10.96 1.82, 13.52 3.74, 16.82 6.82 M16.62 6.26 C14.43 9.96, 10.44 12.08, 9.08 12.26 M16.82 6.69 C14.23 9.53, 11.29 11.28, 8.6 13.05 M8.18 13.15 C6.5 11.29, 2.96 9.47, -1.04 6.03 M9.29 13.33 C5.72 10.63, 3.16 8.82, 0.33 7.08 M-0.06 6.75 C2.67 5.31, 5.11 3.27, 8.68 0.18 M-0.48 6.63 C3.32 5.36, 5.62 2.41, 9.04 0.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1039.8333435058594 267.8075013982557) rotate(0 8.66668701171875 6.500007629394531)"><path d="M8.78 -0.04 L15.46 7.94 L9.47 12.93 L-1.52 7.14" stroke="none" stroke-width="0" fill="#12b886" fill-rule="evenodd"></path><path d="M7.98 -0.35 C12.56 1.78, 14.03 3.5, 16.54 7.4 M9.04 -0.39 C12.43 2.75, 15.26 4.46, 17 7.06 M16.53 7.1 C14.4 9.9, 11.76 10.19, 9.14 13.09 M16.84 6.54 C14.91 8.39, 12 10.85, 9.31 12.59 M9.67 13.17 C6.79 11.59, 3.95 10.16, -0.24 7.11 M8.85 13.09 C6.16 11, 3.09 8.72, -0.35 7.52 M0.08 7.95 C3.37 3.65, 8.06 0.81, 9.12 0.7 M0 7.15 C2.3 5.17, 5.65 2.88, 8.57 0.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1061.3423705607133 431.95786937466056) rotate(0 132.7897097155657 56.31549565361678)"><path d="M0.83 -1.16 C-4.86 5.41, -87.37 21.06, -34.56 40.07 C18.26 59.09, 259 100.75, 317.71 112.93 M-0.19 0.85 C-5.46 7.52, -85.15 22.57, -32.2 41.4 C20.75 60.22, 259.68 101.71, 317.53 113.79" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1061.3423705607133 431.95786937466056) rotate(0 132.7897097155657 56.31549565361678)"><path d="M285.98 117.44 C295.13 118.94, 302.28 117.66, 316.4 114.37 M288.88 119.2 C295.94 117.81, 302.47 116.6, 317.85 113.57" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1061.3423705607133 431.95786937466056) rotate(0 132.7897097155657 56.31549565361678)"><path d="M289.83 97.29 C298.06 104.2, 304.19 108.31, 316.4 114.37 M292.73 99.04 C298.87 102.76, 304.42 106.69, 317.85 113.57" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1679.2410617404512 534.1224072006648) rotate(0 85.99999999999994 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::memories</text></g><g stroke-linecap="round" transform="translate(1705.0924580891924 592.8351842324573) rotate(0 35.000030517578125 12.833343505859375)"><path d="M-1.58 0.06 C26.66 0.76, 55.86 1.99, 71.62 0.68 M0.8 -0.54 C26.47 0.54, 51.99 -0.19, 70.53 0.64 M70.07 1.64 C68.61 6.66, 68.35 11.19, 71.4 27.33 M70.69 0.99 C70.29 8.33, 70.78 19, 70.79 26.62 M70.71 24.55 C47.29 27.76, 26.4 25.52, 1.64 25.37 M70.09 26.58 C52.02 25.64, 33.74 27.13, 0.9 24.95 M0.09 23.78 C-0.54 15.53, 0.92 9.62, 1.3 -1.4 M-0.46 24.76 C0.18 20.48, 0.24 14.7, 0.66 -0.35" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1688.0925496419268 564.4185582558948) rotate(0 49.333343505859375 76.50001525878906)"><path d="M24.67 0 M24.67 0 C41.7 0.07, 59.27 2.29, 74 0 M24.67 0 C44.84 -0.73, 62.79 0.63, 74 0 M74 0 C89.36 1.49, 98.53 9.3, 98.67 24.67 M74 0 C88.61 1.23, 100.14 6.66, 98.67 24.67 M98.67 24.67 C100.2 50.82, 99.27 78, 98.67 128.33 M98.67 24.67 C100.01 52.27, 100.31 79.99, 98.67 128.33 M98.67 128.33 C100.65 145.21, 88.53 154.41, 74 153 M98.67 128.33 C99.63 146.6, 92.64 153.19, 74 153 M74 153 C61.44 152.03, 53 152.72, 24.67 153 M74 153 C59.63 152.63, 47.03 153.01, 24.67 153 M24.67 153 C10.05 152.91, -1.29 144.01, 0 128.33 M24.67 153 C10.16 155.07, -1.65 145.54, 0 128.33 M0 128.33 C-1.12 104.89, -0.82 83.65, 0 24.67 M0 128.33 C-1.42 92.15, -0.09 54.67, 0 24.67 M0 24.67 C-1.81 8.8, 9.41 0.69, 24.67 0 M0 24.67 C1.36 9.73, 7.43 -1.01, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1698.7222357855903 633.5112409883709) rotate(0 35.000030517578125 12.833343505859375)"><path d="M-0.32 0.67 C22.02 1.88, 41.85 0.66, 71.35 -1.12 M0.74 -0.07 C15.49 -0.42, 30.43 1.02, 69.32 -0.35 M68.7 0.71 C68.45 6.71, 71.41 16.54, 71.24 26.24 M70.22 -0.96 C70.88 10.47, 70.97 21.06, 70.08 24.99 M68.86 27.55 C46.46 24.92, 25.47 24.98, -0.88 25.07 M69.95 25.02 C42.41 27.15, 16.5 25.59, 0.33 24.86 M-0.75 24.08 C0.7 20.91, 1.28 12.63, -1.5 0.82 M0.29 26.26 C0.46 17.05, 0.78 6.91, -0.44 -0.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1705.3889838324653 668.8445539766522) rotate(0 35.000030517578125 12.833343505859375)"><path d="M0.67 1.9 C17.38 1.73, 31.64 1.46, 68.88 -1.73 M-0.07 0.54 C25.79 0.01, 53.82 -1.2, 69.65 -0.1 M70.71 -1.56 C69.48 9.19, 71.87 16.82, 70.57 27.5 M69.04 0.71 C70.67 10.26, 71.21 19.02, 69.32 25.96 M71.88 25.21 C46.16 26.9, 22.74 24.39, -0.6 27.44 M69.36 25.28 C49.24 26.54, 26.07 25.97, -0.81 24.93 M-1.58 26.38 C1.3 19.15, -1.16 8.54, 0.82 1.17 M0.59 26.01 C0.82 19.81, -0.11 12.19, -0.25 -0.05" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1584.5003662109375 45.40013326810172) rotate(0 143.33333333333343 353.51851569281683)"><path d="M32 0 M32 0 C119.88 0.8, 209.01 2.43, 254.67 0 M254.67 0 C276.74 -0.47, 286.6 10.38, 286.67 32 M286.67 32 C288.43 288.84, 288.48 544.85, 286.67 675.04 M286.67 675.04 C287.47 695.54, 275.73 706.97, 254.67 707.04 M254.67 707.04 C210.86 706.24, 164.34 708.01, 32 707.04 M32 707.04 C10.49 706.85, 1.01 694.7, 0 675.04 M0 675.04 C-0.92 431.89, -1.08 189.39, 0 32 M0 32 C-0.12 12, 9.22 1.41, 32 0" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g stroke-linecap="round"><g transform="translate(1222.3507160661097 222.4371646537352) rotate(0 175.92464774687824 -105.80122052398973)"><path d="M0.84 -1.17 C14.63 -34.61, 24.98 -172.48, 83.51 -201.55 C142.04 -230.62, 307.41 -179.69, 352.02 -175.59 M-0.17 0.83 C13.44 -32.85, 24.3 -173.37, 82.89 -203.13 C141.49 -232.89, 306.69 -182.18, 351.41 -177.72" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1222.3507160661097 222.4371646537352) rotate(0 175.92464774687824 -105.80122052398973)"><path d="M319.82 -172.04 C334.4 -174.51, 344.21 -177.56, 349.8 -175.81 M321.17 -173.17 C332.37 -174.86, 343.01 -177.23, 352.01 -177.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1222.3507160661097 222.4371646537352) rotate(0 175.92464774687824 -105.80122052398973)"><path d="M323.77 -192.18 C336.76 -187.24, 345.12 -182.9, 349.8 -175.81 M325.12 -193.3 C334.79 -187.46, 343.96 -182.3, 352.01 -177.47" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(1600.796583387587 366.14091356866584) rotate(0 40.66995592665228 32.37065500637928)"><path d="M-0.16 -0.3 C13.63 10.48, 69.34 54.01, 83.04 65.13 M-1.7 -1.51 C11.91 9.37, 67.77 55.28, 82.14 66.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1600.796583387587 366.14091356866584) rotate(0 40.66995592665228 32.37065500637928)"><path d="M53.19 56.85 C61.68 58.36, 73.05 64.87, 81.73 64.26 M52.73 57.69 C61.25 58.55, 66.73 61.1, 82.52 65.88" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1600.796583387587 366.14091356866584) rotate(0 40.66995592665228 32.37065500637928)"><path d="M65.97 40.8 C70.35 47.53, 77.56 59.26, 81.73 64.26 M65.52 41.63 C70.87 46.48, 73.23 52.95, 82.52 65.88" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(1600.796651204427 372.4371985621554) rotate(0 49.48869147395931 114.28871736108223)"><path d="M-0.62 0.56 C7.11 32.75, 29.27 154.02, 45.97 192.05 C62.67 230.09, 90.74 222.9, 99.6 228.78 M1.25 -0.2 C9.42 31.74, 31.96 152.37, 48.32 190.23 C64.67 228.09, 90.84 220.64, 99.4 226.96" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1600.796651204427 372.4371985621554) rotate(0 49.48869147395931 114.28871736108223)"><path d="M70.37 227.41 C78.3 230.1, 86.91 228.86, 98.58 227.39 M69.96 227.83 C78.85 228.46, 88.45 228.41, 98.43 227.04" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1600.796651204427 372.4371985621554) rotate(0 49.48869147395931 114.28871736108223)"><path d="M76.34 207.78 C82.52 215.61, 89.55 219.54, 98.58 227.39 M75.93 208.2 C83.02 215.34, 90.64 221.78, 98.43 227.04" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(1597.0929022894966 375.0298024575547) rotate(0 -70.445805440899 117.2991348266643)"><path d="M0.73 0.61 C-4.45 25.06, -7.51 108.89, -31.06 147.68 C-54.6 186.48, -122.27 219.12, -140.56 233.38 M-0.35 -0.12 C-5.13 24.44, -5.16 110.03, -28.7 149.17 C-52.25 188.31, -122.91 220.53, -141.62 234.72" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1597.0929022894966 375.0298024575547) rotate(0 -70.445805440899 117.2991348266643)"><path d="M-121.97 210.07 C-128.53 217.43, -133.88 224.11, -141.77 232.78 M-122.86 210.7 C-128.98 218.33, -133.67 223.94, -142.56 235.53" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1597.0929022894966 375.0298024575547) rotate(0 -70.445805440899 117.2991348266643)"><path d="M-111.22 227.54 C-121.14 229.74, -129.7 231.19, -141.77 232.78 M-112.11 228.18 C-121.29 230.72, -129.09 231.28, -142.56 235.53" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1089.5743882921008 423.54835714505475) rotate(0 99 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunction **functions;</text></g><g stroke-linecap="round" transform="translate(1043.9077623155383 408.88173116849225) rotate(0 108 21.33331298828125)"><path d="M-1.15 -0.41 C71.94 -1.24, 144.84 -1.68, 214.86 0.45 M0.01 0.86 C81.18 -0.86, 160.97 -1.5, 216.05 0.11 M217.15 -0.58 C215.55 10.11, 215.66 21.6, 215.07 43.03 M216.28 0.61 C214.85 11.92, 215.41 21.67, 216.87 42.28 M215.58 43.89 C148.97 45.24, 82.99 44.86, 1.56 41.17 M216.05 41.96 C140.96 41.97, 68.08 41.38, 0.62 42.2 M0.79 41.5 C-1.47 29.32, 0.16 15.9, -1.15 0.29 M-0.95 41.7 C0.73 27.61, 0.84 14.25, -0.84 -0.93" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1058.5745103624133 419.548418180211) rotate(0 7.666656494140625 11.333343505859375)"><path d="M7.67 0.02 C10.24 4.57, 12.15 6.52, 15.69 13.05 M8.7 0.24 C11.17 3.78, 13.37 8.91, 15.42 11.81 M14.96 11.7 C12.14 15.03, 9.82 17.88, 8.24 22.2 M15.73 11.37 C13.77 14.51, 10.9 18.1, 7.75 22.72 M8.93 22.41 C5.7 19.17, 2.58 16.3, -1.14 12.58 M7.46 22.08 C5.42 19.41, 2.17 15.68, -0.36 12.03 M-0.84 10.95 C2.18 8.47, 4.27 3.91, 8.21 0.57 M-0.69 12.46 C1.72 9.26, 4.77 4.75, 7.33 0.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1246.7225884331597 369.8446624835964) rotate(0 68.83580672299297 -44.336174603751914)"><path d="M-0.61 0.46 C9.96 -11.52, 39.34 -57.85, 62.49 -72.78 C85.64 -87.72, 125.52 -86.6, 138.29 -89.13 M1.26 -0.34 C11.86 -12.1, 39.37 -56.88, 62.07 -71.54 C84.78 -86.2, 124.54 -85.79, 137.49 -88.33" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1246.7225884331597 369.8446624835964) rotate(0 68.83580672299297 -44.336174603751914)"><path d="M111.38 -73.32 C115.65 -77.88, 120.84 -79.44, 137.81 -88.03 M109.78 -75.56 C120.23 -80.21, 131.15 -84.7, 137.86 -89.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1246.7225884331597 369.8446624835964) rotate(0 68.83580672299297 -44.336174603751914)"><path d="M109.1 -93.72 C113.72 -93.81, 119.41 -90.9, 137.81 -88.03 M107.51 -95.95 C118.93 -92.97, 130.71 -89.8, 137.86 -89.2" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(764.5002983940975 229.84464552938653) rotate(0 82.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_global_count</text></g><g stroke-linecap="round" transform="translate(751.9817470974394 225.49280837118334) rotate(0 87.33334350585938 12.685162014431455)"><path d="M-1.73 -1.68 C49.47 1.22, 96.69 -1.01, 176.24 0.2 M0.99 0.47 C61.61 -0.96, 123.31 -2.27, 175.24 0.66 M176.01 -0.37 C173.51 10.25, 172.88 18.97, 176.43 24.1 M173.81 0.04 C173.86 10.21, 175.29 18.61, 175.56 26.11 M172.69 24.7 C121.04 28.04, 67.66 25.2, -0.34 24.59 M174.83 24.38 C107.24 27.86, 39.27 27.27, 0.06 24.65 M1.92 23.58 C1.17 17.04, -1.65 12.14, 1.23 0.79 M-0.12 24.67 C-0.04 16.31, -0.93 9.05, -0.39 0.95" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(748.418830871582 395.92424944513095) rotate(0 87 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_memory_count</text></g><g stroke-linecap="round" transform="translate(746.0855178833008 394.42409685724033) rotate(0 91.16665649414062 12.5)"><path d="M-0.98 -1.69 C67.21 -2.59, 132.38 -1.95, 181.81 1.3 M0.34 -0.54 C48.21 0.18, 98.96 0.48, 181.54 -0.63 M182.41 -0.85 C182.75 5.85, 183.11 16.58, 181.36 26.92 M182.26 -0.51 C182.74 7.48, 181.43 13.65, 182.33 24.89 M182.67 26.97 C124.35 25.21, 66.26 23.8, -0.99 23.81 M182.83 25.91 C113.93 24.69, 46.88 24.45, -0.34 25.09 M-0.3 23.62 C0 18.31, -0.09 10.16, -0.4 0.67 M-0.45 24.53 C0.1 16.88, -0.15 10.8, 0.77 -0.8" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(762.0855178833008 462.7574098455216) rotate(0 81 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">export_table_count</text></g><g stroke-linecap="round" transform="translate(754.7522048950195 461.7574403630997) rotate(0 87.16665649414062 12.166717529296875)"><path d="M1.92 1.54 C49.93 -1.24, 101.57 0.34, 172.33 1.12 M-0.79 -0.93 C50.85 0.23, 103.27 -0.97, 174.67 0.42 M176.22 1.98 C174.82 6.63, 173.45 8.84, 172.61 22.76 M174.91 0.21 C174.91 8.42, 174.49 16.89, 174.51 23.8 M174.69 23.24 C112.93 24, 50.73 24.65, -1.99 25.5 M175.02 24.3 C113.97 25.05, 54.47 26.38, 0.85 23.39 M-1.49 22.61 C-0.92 15.52, -0.73 3.7, 0.39 -1.61 M-0.03 24.88 C-1.06 15.33, 0.76 7.02, -1 -0.35" stroke="#000000" stroke-width="1" fill="none"></path></g></svg> \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.excalidraw b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.excalidraw
new file mode 100644
index 000000000..8c59bdbca
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.excalidraw
@@ -0,0 +1,7754 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
+ "elements": [
+ {
+ "type": "rectangle",
+ "version": 215,
+ "versionNonce": 1880133867,
+ "isDeleted": false,
+ "id": "4o9JHPgrKQSqK-ibc0qs_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2254.5001678466797,
+ "y": 1663.1666412353516,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 150.66668701171875,
+ "height": 43.000030517578125,
+ "seed": 4270136,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "PsNatrhOR918YjbmvyT9x",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 230,
+ "versionNonce": 1135445829,
+ "isDeleted": false,
+ "id": "94gfo2BctxYsRP6cuuIbI",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1297.1946105957031,
+ "y": 1755.6666768391929,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 214.33333333333348,
+ "height": 122.66668701171875,
+ "seed": 305330883,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "9vnyulmvSUCDWXvSKKyJ6",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 162,
+ "versionNonce": 1027947403,
+ "isDeleted": false,
+ "id": "JWlL3nHzTP4pxrEVYolFx",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2226.416498184204,
+ "y": 1001.3333435058594,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 278.6666259765625,
+ "height": 244.00003051757812,
+ "seed": 1502608995,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "70jp9eV1jV2_kUBbN055m",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 115,
+ "versionNonce": 291919525,
+ "isDeleted": false,
+ "id": "Cc8lshSSJ7lAY4RPjzS5A",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1289.1666717529297,
+ "y": 1285.8333587646484,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 178,
+ "height": 20,
+ "seed": 411108936,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMFunctionInstance",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunctionInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 100,
+ "versionNonce": 1607176747,
+ "isDeleted": false,
+ "id": "onh-wm6wgKrkH94fakl6O",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1291.1666107177734,
+ "y": 1309.1666717529297,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 259.33331298828125,
+ "height": 210.3333435058593,
+ "seed": 2073695304,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "fltFoJAyfls8KPkBw6X_P",
+ "type": "arrow"
+ },
+ {
+ "id": "MLVyGZQLa4jU554J6bsmJ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 113,
+ "versionNonce": 34486789,
+ "isDeleted": false,
+ "id": "eAtZfC7P3ZafizTDITzz-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1363.1666717529297,
+ "y": 1335.500015258789,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 12.333343505859375,
+ "seed": 136923720,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 139,
+ "versionNonce": 411964619,
+ "isDeleted": false,
+ "id": "GmBiArFp8A3Q9NaPWxp3Q",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1395.8332977294922,
+ "y": 1332.8333587646484,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 94,
+ "height": 20,
+ "seed": 258177848,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nUF7GyfmAGZN3iZvBfYtq",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_import",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func_import"
+ },
+ {
+ "type": "text",
+ "version": 239,
+ "versionNonce": 245543269,
+ "isDeleted": false,
+ "id": "YdCXv7DFgrOOU2wowasgm",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1748.499984741211,
+ "y": 1142.4999237060547,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 164,
+ "height": 20,
+ "seed": 1678600520,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMFunctionImport:",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunctionImport:"
+ },
+ {
+ "type": "rectangle",
+ "version": 254,
+ "versionNonce": 656884587,
+ "isDeleted": false,
+ "id": "1Oi1iFkA8pBbaQpvduCq1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1738.499984741211,
+ "y": 1161.1666717529297,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 176,
+ "height": 200.33340454101554,
+ "seed": 1244990536,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nUF7GyfmAGZN3iZvBfYtq",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 701,
+ "versionNonce": 879836357,
+ "isDeleted": false,
+ "id": "nUF7GyfmAGZN3iZvBfYtq",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1502.280048689805,
+ "y": 1332.5712493918486,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 234.84228393034437,
+ "height": 170.17912641351631,
+ "seed": 213606712,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "GmBiArFp8A3Q9NaPWxp3Q",
+ "focus": 0.8789861743715494,
+ "gap": 14.558826765976846
+ },
+ "endBinding": {
+ "elementId": "w7-3leJjFtbtDhwDpkUjF",
+ "focus": 0.9853865103923569,
+ "gap": 6.774518257019281
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 157.46964422706515,
+ -143.2377075217314
+ ],
+ [
+ 234.84228393034437,
+ -170.17912641351631
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 197,
+ "versionNonce": 1944165899,
+ "isDeleted": false,
+ "id": "bM6INpWVFBvURve3zdbdf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1396.1666717529297,
+ "y": 1355.5000457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 34,
+ "height": 20,
+ "seed": 379599688,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func"
+ },
+ {
+ "type": "diamond",
+ "version": 140,
+ "versionNonce": 1796693029,
+ "isDeleted": false,
+ "id": "3cBYbIbQEyvFuXBMoyida",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1364.8332977294922,
+ "y": 1360.3333435058594,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 12.333343505859375,
+ "seed": 1837623096,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 310,
+ "versionNonce": 2042078379,
+ "isDeleted": false,
+ "id": "9KTm6XzaqX3iZ90_AL3RN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1900.8332977294922,
+ "y": 1530.166732788086,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 211,
+ "height": 20,
+ "seed": 1970637640,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Bnf72M4RGMZjNgBlzk90B",
+ "type": "arrow"
+ },
+ {
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "type": "arrow"
+ },
+ {
+ "id": "S1cN82-5SoSu4e4SWfAUw",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMFunction (per module)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunction (per module)"
+ },
+ {
+ "type": "rectangle",
+ "version": 261,
+ "versionNonce": 1518505861,
+ "isDeleted": false,
+ "id": "0kWlc6iPzGzhrfIVEPeOM",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1902.1667938232422,
+ "y": 1559.6667175292969,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 225.33337402343744,
+ "height": 200.9999389648438,
+ "seed": 2020723016,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "type": "arrow"
+ },
+ {
+ "id": "Bnf72M4RGMZjNgBlzk90B",
+ "type": "arrow"
+ },
+ {
+ "id": "uC3ZSm-IltHDllxDGLJ9v",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 675,
+ "versionNonce": 1884542795,
+ "isDeleted": false,
+ "id": "zzj3BPEivUiaW1sqpfx7J",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2266.8334197998047,
+ "y": 1673.8333282470703,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 129,
+ "height": 20,
+ "seed": 26708536,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "type": "arrow"
+ },
+ {
+ "id": "PsNatrhOR918YjbmvyT9x",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "internal function",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "internal function"
+ },
+ {
+ "type": "arrow",
+ "version": 666,
+ "versionNonce": 1357928165,
+ "isDeleted": false,
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1434.5331571443298,
+ "y": 1377.528759465866,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 458.6267427864543,
+ "height": 186.82387510648414,
+ "seed": 535299656,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "evHonaxVjRvjwFP08UX9x",
+ "focus": -0.827785929496437,
+ "gap": 16.471286310501227
+ },
+ "endBinding": {
+ "elementId": "9KTm6XzaqX3iZ90_AL3RN",
+ "focus": -1.317866862333605,
+ "gap": 14.985901784264229
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 184.63351460859985,
+ 58.63791228706373
+ ],
+ [
+ 458.6267427864543,
+ 186.82387510648414
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 145,
+ "versionNonce": 907064811,
+ "isDeleted": false,
+ "id": "WfHCEtd4eDaOU42FFn9wo",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1341.1666717529297,
+ "y": 1321.500015258789,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 186.00006103515625,
+ "height": 65,
+ "seed": 663703880,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 166,
+ "versionNonce": 2028876357,
+ "isDeleted": false,
+ "id": "QbAKq7kA_EZo7yxdpqj6F",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1742.499984741211,
+ "y": 1166.8332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 158.66668701171872,
+ "height": 45.33337402343752,
+ "seed": 757681480,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 170,
+ "versionNonce": 2046345355,
+ "isDeleted": false,
+ "id": "w7-3leJjFtbtDhwDpkUjF",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1715.499984741211,
+ "y": 1169.1666412353516,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 187,
+ "height": 40,
+ "seed": 1177365064,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "nUF7GyfmAGZN3iZvBfYtq",
+ "type": "arrow"
+ },
+ {
+ "id": "70jp9eV1jV2_kUBbN055m",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": " char *module_name;\n char *field_name;",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " char *module_name;\n char *field_name;"
+ },
+ {
+ "type": "rectangle",
+ "version": 190,
+ "versionNonce": 1331274149,
+ "isDeleted": false,
+ "id": "m6kQPfRjltByoJapP3m-h",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1744.499984741211,
+ "y": 1234.499984741211,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 155.33337402343747,
+ "height": 35.666656494140625,
+ "seed": 613948728,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 184,
+ "versionNonce": 633763627,
+ "isDeleted": false,
+ "id": "IXwlC5RgaF1iJPCtg6-Er",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1768.4999237060547,
+ "y": 1243.499984741211,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 125,
+ "height": 20,
+ "seed": 664043080,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "l4S1IXvHmVx_wl8DPQXk3",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_ptr_linked",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func_ptr_linked"
+ },
+ {
+ "type": "rectangle",
+ "version": 230,
+ "versionNonce": 1499473157,
+ "isDeleted": false,
+ "id": "o1vzUOCoilIzaDJdTpt35",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1735.8333587646484,
+ "y": 932.4999542236328,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 155.33331298828125,
+ "height": 90.33334350585938,
+ "seed": 1170302520,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "l4S1IXvHmVx_wl8DPQXk3",
+ "type": "arrow"
+ },
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 211,
+ "versionNonce": 132405707,
+ "isDeleted": false,
+ "id": "Kpjtivj-7LYLq1nuvC4KS",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1742.5000457763672,
+ "y": 940.8332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 123,
+ "height": 20,
+ "seed": 1541878344,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "l4S1IXvHmVx_wl8DPQXk3",
+ "type": "arrow"
+ },
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "native function:",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "native function:"
+ },
+ {
+ "type": "arrow",
+ "version": 755,
+ "versionNonce": 444546149,
+ "isDeleted": false,
+ "id": "l4S1IXvHmVx_wl8DPQXk3",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1751.6334408235434,
+ "y": 1247.8332977294922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 121.88354763506686,
+ "height": 307.57912212433075,
+ "seed": 203809096,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "OpV38MM8YOexWG_e-5_hX",
+ "focus": -0.4013706262952343,
+ "gap": 1.943772417380456
+ },
+ "endBinding": {
+ "elementId": "Kpjtivj-7LYLq1nuvC4KS",
+ "focus": 1.1040701980735919,
+ "gap": 6.6751580517609455
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -121.88354763506686,
+ -191.16677856445312
+ ],
+ [
+ -15.808553098937182,
+ -307.57912212433075
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 185,
+ "versionNonce": 1030547563,
+ "isDeleted": false,
+ "id": "5EDlNHzjVbZ3Rx8ny3SUe",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1742.6665802001953,
+ "y": 1279.1666412353516,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 165.16677856445304,
+ "height": 73.666748046875,
+ "seed": 202955336,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 241,
+ "versionNonce": 1250191301,
+ "isDeleted": false,
+ "id": "wc-s6ecXMbmh2ViGrkOa4",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1757.8332977294922,
+ "y": 1289.5000457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 152,
+ "height": 40,
+ "seed": 1536408648,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "S1cN82-5SoSu4e4SWfAUw",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "import_module;\nimport_func_linked;",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "import_module;\nimport_func_linked;"
+ },
+ {
+ "type": "arrow",
+ "version": 788,
+ "versionNonce": 1546298123,
+ "isDeleted": false,
+ "id": "S1cN82-5SoSu4e4SWfAUw",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1741.963485458681,
+ "y": 1322.4954523286892,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 248.14874440629774,
+ "height": 238.16542426722026,
+ "seed": 1657735240,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "-vw33v9u2Ko2ayilI0CXG",
+ "focus": 2.0635763351494516,
+ "gap": 4.200185998866319
+ },
+ "endBinding": {
+ "elementId": "9KTm6XzaqX3iZ90_AL3RN",
+ "focus": -1.1514950968199016,
+ "gap": 11.294143807823616
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -88.79684422332912,
+ 88.33793695353734
+ ],
+ [
+ 159.35190018296862,
+ 238.16542426722026
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 234,
+ "versionNonce": 1267541797,
+ "isDeleted": false,
+ "id": "jF8UBxFom2hco1NronB-_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1639.2142922537669,
+ "y": 1510.404782976423,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 137,
+ "height": 20,
+ "seed": 548488008,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(WASMFunction *)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(WASMFunction *)"
+ },
+ {
+ "type": "diamond",
+ "version": 76,
+ "versionNonce": 1553467819,
+ "isDeleted": false,
+ "id": "jJOCFAslIe3JYgWsRnIKx",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1915.8334197998047,
+ "y": 1577.1667022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 17.33331298828125,
+ "height": 15.666656494140625,
+ "seed": 1470386504,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [
+ {
+ "id": "PsNatrhOR918YjbmvyT9x",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 88,
+ "versionNonce": 1611070085,
+ "isDeleted": false,
+ "id": "V1RSJPoudlOhc-GaAxPSa",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1947.8334197998047,
+ "y": 1577.500015258789,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 37,
+ "height": 20,
+ "seed": 1209849672,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "PsNatrhOR918YjbmvyT9x",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "code",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "code"
+ },
+ {
+ "type": "rectangle",
+ "version": 217,
+ "versionNonce": 1138728011,
+ "isDeleted": false,
+ "id": "tXHmR9TBkCnxMdo_pd0XG",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2255.833480834961,
+ "y": 1603.1666412353516,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 149.3333740234375,
+ "height": 114.33340454101562,
+ "seed": 321892664,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 182,
+ "versionNonce": 548364773,
+ "isDeleted": false,
+ "id": "Zsg-OsrfZ2doJiTuOOpPu",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2277.166793823242,
+ "y": 1576.1666107177734,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70,
+ "height": 20,
+ "seed": 40194872,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "bytecode",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "bytecode"
+ },
+ {
+ "type": "arrow",
+ "version": 545,
+ "versionNonce": 232512235,
+ "isDeleted": false,
+ "id": "PsNatrhOR918YjbmvyT9x",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1990.5000762939453,
+ "y": 1589.1666717529297,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 264.9616597351928,
+ "height": 70.73153780068333,
+ "seed": 1716226360,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "V1RSJPoudlOhc-GaAxPSa",
+ "focus": -0.13746287298855567,
+ "gap": 7.9146728515625
+ },
+ "endBinding": {
+ "elementId": "4o9JHPgrKQSqK-ibc0qs_",
+ "focus": 0.060950944035830956,
+ "gap": 3.268431681738548
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 149.9165802001953,
+ 22.1666259765625
+ ],
+ [
+ 191.24952507019043,
+ 48.83355712890625
+ ],
+ [
+ 264.9616597351928,
+ 70.73153780068333
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 79,
+ "versionNonce": 848551237,
+ "isDeleted": false,
+ "id": "sWaZg1Dcn3g0Qfdc7onW_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1916.5001068115234,
+ "y": 1629.8333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 18.6666259765625,
+ "height": 15,
+ "seed": 238700600,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 84,
+ "versionNonce": 1461142923,
+ "isDeleted": false,
+ "id": "U5NUD0rdNNDuY14J1ZRMu",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1954.8333587646484,
+ "y": 1628.8333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 110,
+ "height": 20,
+ "seed": 744475464,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "code_compiled",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "code_compiled"
+ },
+ {
+ "type": "rectangle",
+ "version": 431,
+ "versionNonce": 1024584869,
+ "isDeleted": false,
+ "id": "gk39IBXF-F8MrwhzL35C6",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2462.5001068115234,
+ "y": 1639.5001373291016,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 114.66674804687503,
+ "height": 119.33334350585936,
+ "seed": 201839672,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 444,
+ "versionNonce": 1187798059,
+ "isDeleted": false,
+ "id": "ZRckuyHrC8P5etlpd8MWT",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2443.166793823242,
+ "y": 1616.833480834961,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 161,
+ "height": 20,
+ "seed": 2016979784,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "precompiled-bytecode",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "precompiled-bytecode"
+ },
+ {
+ "type": "rectangle",
+ "version": 437,
+ "versionNonce": 534188037,
+ "isDeleted": false,
+ "id": "qGjmy62MZbL7zALsNU2dL",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2463.166793823242,
+ "y": 1699.5001373291016,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 114.00006103515625,
+ "height": 43.000030517578125,
+ "seed": 1165004088,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "iqe6U9xOE6ECb18moJnw-",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 68,
+ "versionNonce": 954572491,
+ "isDeleted": false,
+ "id": "SiZHwNA9YKd93iwc74wxB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1942.4999542236328,
+ "y": 1667.833480834961,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 175,
+ "height": 20,
+ "seed": 1708294472,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "HCvGV6j45DG_BGeI3J7ut",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929331,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "fast_jit_jitted_code",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "fast_jit_jitted_code"
+ },
+ {
+ "type": "diamond",
+ "version": 85,
+ "versionNonce": 1759561573,
+ "isDeleted": false,
+ "id": "ODI38iO5_5uu6RobQgkVa",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1912.499984741211,
+ "y": 1672.3333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 18.6666259765625,
+ "height": 15,
+ "seed": 297387080,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 93,
+ "versionNonce": 670928235,
+ "isDeleted": false,
+ "id": "gNxfqnpn5KEfZX8dL5GX3",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1913.499984741211,
+ "y": 1717.666732788086,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 18.6666259765625,
+ "height": 15,
+ "seed": 1391035448,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 99,
+ "versionNonce": 175936197,
+ "isDeleted": false,
+ "id": "sYSDwbrpZl0692xpkcG4z",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1946.499984741211,
+ "y": 1713.166763305664,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 143,
+ "height": 20,
+ "seed": 1305637176,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "RckpORzYftIA2k4VSkTaW",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "llvm_jit_func_ptr",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "llvm_jit_func_ptr"
+ },
+ {
+ "type": "text",
+ "version": 450,
+ "versionNonce": 1465821195,
+ "isDeleted": false,
+ "id": "1iUf8pP_YoM8qCPpSEahX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2383.0000762939453,
+ "y": 1788.8333129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 142,
+ "height": 20,
+ "seed": 68451128,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "fast jitted coode",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "fast jitted coode"
+ },
+ {
+ "type": "rectangle",
+ "version": 501,
+ "versionNonce": 1363669541,
+ "isDeleted": false,
+ "id": "qVsRlSPxTl9a8XrnRMl2a",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2405.6665802001953,
+ "y": 1827.4999389648438,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 103.33337402343747,
+ "height": 29.2,
+ "seed": 1374549064,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "HCvGV6j45DG_BGeI3J7ut",
+ "type": "arrow"
+ },
+ {
+ "id": "BF2h7Ub5gAf2yYxLfQSFh",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 447,
+ "versionNonce": 1023635115,
+ "isDeleted": false,
+ "id": "bu6GnR96DeCSFWu3DhMIJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2419.499954223633,
+ "y": 1890.1666870117188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 133,
+ "height": 20,
+ "seed": 713214264,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "RckpORzYftIA2k4VSkTaW",
+ "type": "arrow"
+ },
+ {
+ "id": "kjpM2qWJqDrV-jr9XK8QR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "llvm jitted coode",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "llvm jitted coode"
+ },
+ {
+ "type": "rectangle",
+ "version": 395,
+ "versionNonce": 439379333,
+ "isDeleted": false,
+ "id": "Z9cJSNSjDvW2uPNthdOW9",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2406.1666412353516,
+ "y": 1916.1666870117188,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 150.66668701171875,
+ "height": 43.000030517578125,
+ "seed": 1255376456,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "4E9MghnYo6hn8E82pmPMe",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 266,
+ "versionNonce": 731275595,
+ "isDeleted": false,
+ "id": "evHonaxVjRvjwFP08UX9x",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1335.1666259765625,
+ "y": 1394.0000457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 187.33343505859372,
+ "height": 73.666748046875,
+ "seed": 873572680,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "78xSb96N8EcRm2LhdCNjJ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 258,
+ "versionNonce": 1215524069,
+ "isDeleted": false,
+ "id": "4R5zAaFl-qG-PwNUPfyXq",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1360.4999389648438,
+ "y": 1404.6667022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 157,
+ "height": 40,
+ "seed": 237924152,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "import_module_inst;\nimport_func_inst;",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "import_module_inst;\nimport_func_inst;"
+ },
+ {
+ "type": "diamond",
+ "version": 132,
+ "versionNonce": 1014104043,
+ "isDeleted": false,
+ "id": "-cXxAxf0DBRaXH85Wn82G",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1341.4998168945312,
+ "y": 1408.6666564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 12.333343505859375,
+ "seed": 1993562680,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "MLVyGZQLa4jU554J6bsmJ",
+ "type": "arrow"
+ },
+ {
+ "id": "9vnyulmvSUCDWXvSKKyJ6",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 136,
+ "versionNonce": 2073987141,
+ "isDeleted": false,
+ "id": "V3cEII-BWPnk8MmO8v9Hw",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1342.8331909179688,
+ "y": 1431.6666564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 12.333343505859375,
+ "seed": 374375752,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "MLVyGZQLa4jU554J6bsmJ",
+ "type": "arrow"
+ },
+ {
+ "id": "9vnyulmvSUCDWXvSKKyJ6",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 196,
+ "versionNonce": 2040580747,
+ "isDeleted": false,
+ "id": "jccHI4GP5zADwZpJ6_F0e",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1020.4999542236328,
+ "y": 1294.5002899169922,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 132.66668701171866,
+ "height": 34.3333740234375,
+ "seed": 1209325128,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "eyNKBEqdZDGI0jikxT-7-"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 28,
+ "versionNonce": 1577034445,
+ "isDeleted": false,
+ "id": "eyNKBEqdZDGI0jikxT-7-",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1050.8332977294922,
+ "y": 1302.066976928711,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 72,
+ "height": 20,
+ "seed": 13177699,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247195,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "functions",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "jccHI4GP5zADwZpJ6_F0e",
+ "originalText": "functions"
+ },
+ {
+ "type": "diamond",
+ "version": 157,
+ "versionNonce": 1205682475,
+ "isDeleted": false,
+ "id": "DpQKmgYqIbva-oudQDKVA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1029.8332977294922,
+ "y": 1302.8336334228516,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1787304760,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 460,
+ "versionNonce": 544406277,
+ "isDeleted": false,
+ "id": "fltFoJAyfls8KPkBw6X_P",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1152.0382824623548,
+ "y": 1307.393701716202,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 140.3213191272912,
+ "height": 0.8215748529805751,
+ "seed": 1890946120,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "onh-wm6wgKrkH94fakl6O",
+ "focus": 1.0244280280971265,
+ "gap": 2.5945448897082315
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 140.3213191272912,
+ -0.8215748529805751
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 245,
+ "versionNonce": 277996491,
+ "isDeleted": false,
+ "id": "BpsyACMObLF20Fkti2Uqq",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1020.8332061767578,
+ "y": 1339.000228881836,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 130.00000000000009,
+ "height": 31,
+ "seed": 1664170040,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "22kjCR2ZOQmZQXYgnarEF"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 50,
+ "versionNonce": 1029340291,
+ "isDeleted": false,
+ "id": "22kjCR2ZOQmZQXYgnarEF",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "dotted",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1058.3332061767578,
+ "y": 1344.900228881836,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 55,
+ "height": 20,
+ "seed": 1753405955,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247196,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "globals",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "BpsyACMObLF20Fkti2Uqq",
+ "originalText": "globals"
+ },
+ {
+ "type": "diamond",
+ "version": 201,
+ "versionNonce": 735654507,
+ "isDeleted": false,
+ "id": "66O-4o40vS3pLIeBqwFBW",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1030.1665802001953,
+ "y": 1344.000228881836,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 231180104,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 336,
+ "versionNonce": 2136587717,
+ "isDeleted": false,
+ "id": "l2Sz8ohFcHQT7gWys1M9D",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 751.1665802001953,
+ "y": 1311.6668853759766,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 158,
+ "height": 32,
+ "seed": 1571295288,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "o-cON41NQVHvHqkgeW_6m"
+ },
+ {
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 115,
+ "versionNonce": 956023085,
+ "isDeleted": false,
+ "id": "o-cON41NQVHvHqkgeW_6m",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 824.6665802001953,
+ "y": 1317.1668853759766,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 11,
+ "height": 20,
+ "seed": 1939939267,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247196,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "e",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "l2Sz8ohFcHQT7gWys1M9D",
+ "originalText": "e"
+ },
+ {
+ "type": "diamond",
+ "version": 340,
+ "versionNonce": 659012901,
+ "isDeleted": false,
+ "id": "_eiwTSAQSXB8P2k-PDhNa",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 769.8332061767578,
+ "y": 1323.6668548583984,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1019883336,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 238,
+ "versionNonce": 536466347,
+ "isDeleted": false,
+ "id": "OLHiYmF0KqdbZBgecyb7T",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1017.1665802001953,
+ "y": 1430.6669158935547,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 131.33337402343759,
+ "height": 32.33331298828125,
+ "seed": 1564507192,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 172,
+ "versionNonce": 1409208453,
+ "isDeleted": false,
+ "id": "qUAVJJGhHiEU00yvj5Xwy",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1041.1665802001953,
+ "y": 1438.3335723876953,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1916699464,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 170,
+ "versionNonce": 209200715,
+ "isDeleted": false,
+ "id": "ZzKApm4TYPqV3EGJbMuQ3",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1001.6664886474609,
+ "y": 1253.9168853759766,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 214,
+ "height": 20,
+ "seed": 1061991496,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstanceExtra",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstanceExtra"
+ },
+ {
+ "type": "rectangle",
+ "version": 195,
+ "versionNonce": 859600869,
+ "isDeleted": false,
+ "id": "SWgPVXvgjtN7AVlTfBUDR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1009.2498474121094,
+ "y": 1279.9169082641602,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 155,
+ "height": 200.41667938232422,
+ "seed": 1419979080,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 389,
+ "versionNonce": 114500843,
+ "isDeleted": false,
+ "id": "3rcvtpnHrIvCrE__yw5GU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1339.5831756591797,
+ "y": 1031.000186920166,
+ "strokeColor": "#d9480f",
+ "backgroundColor": "transparent",
+ "width": 174,
+ "height": 40,
+ "seed": 1610110792,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "AuwWYqGK5XChc2C2ZDCOd",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstance::\nimport_func_ptrs",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance::\nimport_func_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 137,
+ "versionNonce": 1594766149,
+ "isDeleted": false,
+ "id": "IK-a-uPI373j3VM1YHdKy",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1390.1666870117188,
+ "y": 1107.625286102295,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1938455864,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "dA4sHNYw9NqC0yRSl1ByC",
+ "type": "arrow"
+ },
+ {
+ "id": "AuwWYqGK5XChc2C2ZDCOd",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 123,
+ "versionNonce": 110448523,
+ "isDeleted": false,
+ "id": "xEmeSz_qg3vcIV0Kjo_4r",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1414.1666870117188,
+ "y": 1115.2919425964355,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1045500488,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "AuwWYqGK5XChc2C2ZDCOd",
+ "type": "arrow"
+ },
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 158,
+ "versionNonce": 1406239397,
+ "isDeleted": false,
+ "id": "u6aTea5vKrjtv4E0SAr_D",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1389.8333129882812,
+ "y": 1140.7919120788574,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1488328248,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 144,
+ "versionNonce": 771302955,
+ "isDeleted": false,
+ "id": "6petv8iQ_6W4RCCyGVs86",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1413.8333129882812,
+ "y": 1148.458568572998,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1174899016,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 146,
+ "versionNonce": 640935429,
+ "isDeleted": false,
+ "id": "HWwjwJX9MC7vOni7CdfwU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1389.5,
+ "y": 1174.1252555847168,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 654741304,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 158,
+ "versionNonce": 1944660171,
+ "isDeleted": false,
+ "id": "3V6VqEBHUeHRXm4rtMN9P",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1388.1666259765625,
+ "y": 1201.7919120788574,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 652208184,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 138,
+ "versionNonce": 2033376613,
+ "isDeleted": false,
+ "id": "s3LweJMlqb3u8zFFOtRWC",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1410.8333129882812,
+ "y": 1210.1252555847168,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 630970184,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 748,
+ "versionNonce": 234870635,
+ "isDeleted": false,
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1423.3266279235036,
+ "y": 1116.6584335466105,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 310.5923414580757,
+ "height": 177.73696684706545,
+ "seed": 561180216,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "xEmeSz_qg3vcIV0Kjo_4r",
+ "focus": -0.6524247058306003,
+ "gap": 2.5695135809208747
+ },
+ "endBinding": {
+ "elementId": "Kpjtivj-7LYLq1nuvC4KS",
+ "focus": 1.1530360747961412,
+ "gap": 8.581076394787942
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 125.75645618294175,
+ -55.99185334641493
+ ],
+ [
+ 310.5923414580757,
+ -177.73696684706545
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 115,
+ "versionNonce": 874244293,
+ "isDeleted": false,
+ "id": "SosCUEMFvN64e8eYhtj4S",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1748.0836486816406,
+ "y": 1289.8335762023926,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 8.333282470703125,
+ "height": 13.75,
+ "seed": 1668126536,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "S1cN82-5SoSu4e4SWfAUw",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 119,
+ "versionNonce": 445100555,
+ "isDeleted": false,
+ "id": "-vw33v9u2Ko2ayilI0CXG",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1745.5836486816406,
+ "y": 1319.8335762023926,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10.833282470703125,
+ "height": 9.583320617675781,
+ "seed": 2012578120,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "S1cN82-5SoSu4e4SWfAUw",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 648,
+ "versionNonce": 2022475813,
+ "isDeleted": false,
+ "id": "MLVyGZQLa4jU554J6bsmJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1347.8331909179688,
+ "y": 1415.2017225151058,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 179.41659545898438,
+ "height": 304.1667256414903,
+ "seed": 1591654456,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "V3cEII-BWPnk8MmO8v9Hw",
+ "focus": 3.669987091693772,
+ "gap": 10.369642504898593
+ },
+ "endBinding": {
+ "elementId": "Rcref7JZ-AhlcXLLdwY5D",
+ "focus": -0.4568695235814372,
+ "gap": 6.321478788304148
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -179.41659545898438,
+ 169.4649187202458
+ ],
+ [
+ -89.48586426600582,
+ 304.1667256414903
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 807,
+ "versionNonce": 175847595,
+ "isDeleted": false,
+ "id": "tUs9waDW6sL0AbyoZYJ5Q",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 867.8295186360679,
+ "y": 823.9724260965983,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 672,
+ "height": 160,
+ "seed": 709576760,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "this is the one actually referred during executing opcode\n\nduring model load, if import can be solved through the native api registeration,\nthe pointer of native function will be filled.\n\nc-api could change the pointer later, then it will point to a different native function\n\nNULL: means multi-module import, go to \"import_func_inst\" field for target function",
+ "baseline": 154,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "this is the one actually referred during executing opcode\n\nduring model load, if import can be solved through the native api registeration,\nthe pointer of native function will be filled.\n\nc-api could change the pointer later, then it will point to a different native function\n\nNULL: means multi-module import, go to \"import_func_inst\" field for target function"
+ },
+ {
+ "type": "rectangle",
+ "version": 410,
+ "versionNonce": 1483881349,
+ "isDeleted": false,
+ "id": "kARKLR5va5hDwe-2JCl7d",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 855.623291015625,
+ "y": 824.4128579639253,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 691.1904471261159,
+ "height": 170.05954742431626,
+ "seed": 1355113288,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "AuwWYqGK5XChc2C2ZDCOd",
+ "type": "arrow"
+ },
+ {
+ "id": "j_Tg3JOansfDRNxNBUMfi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 1427,
+ "versionNonce": 1267002187,
+ "isDeleted": false,
+ "id": "AuwWYqGK5XChc2C2ZDCOd",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1132.2583561737392,
+ "y": 997.6315427986297,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 188.93306844281233,
+ "height": 54.67370578283135,
+ "seed": 1524992312,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "kARKLR5va5hDwe-2JCl7d",
+ "gap": 3.1591374103880994,
+ "focus": 0.5842950344963632
+ },
+ "endBinding": {
+ "elementId": "3rcvtpnHrIvCrE__yw5GU",
+ "gap": 18.39175104262814,
+ "focus": -0.7039875993615579
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 188.93306844281233,
+ 54.67370578283135
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 363,
+ "versionNonce": 1275757285,
+ "isDeleted": false,
+ "id": "_pYmb7H1lxRLE4Qw_MajA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1034.3336715698242,
+ "y": 1680.4170036315918,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 176,
+ "height": 20,
+ "seed": 764509256,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstance*",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance*"
+ },
+ {
+ "type": "text",
+ "version": 314,
+ "versionNonce": 838814187,
+ "isDeleted": false,
+ "id": "GBXnnFKM_76tjt1WAlYnV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1250.0279070536296,
+ "y": 1605.2504641215007,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 198,
+ "height": 20,
+ "seed": 1630119496,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "9vnyulmvSUCDWXvSKKyJ6",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(WASMFunctionInstance*)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(WASMFunctionInstance*)"
+ },
+ {
+ "type": "arrow",
+ "version": 881,
+ "versionNonce": 1742921285,
+ "isDeleted": false,
+ "id": "9vnyulmvSUCDWXvSKKyJ6",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1347.3662637658592,
+ "y": 1437.871212796838,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 109.83801974730454,
+ "height": 307.7636946939249,
+ "seed": 422577480,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "-cXxAxf0DBRaXH85Wn82G",
+ "focus": -3.9115852992052806,
+ "gap": 11.29853538112821
+ },
+ "endBinding": {
+ "elementId": "94gfo2BctxYsRP6cuuIbI",
+ "gap": 10.033975741878294,
+ "focus": -0.6520703073991437
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -109.83801974730454,
+ 135.3790961936404
+ ],
+ [
+ -51.493209521376,
+ 307.7636946939249
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 207,
+ "versionNonce": 2116029227,
+ "isDeleted": false,
+ "id": "kliwot061_yUhDMDbVbQe",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1354.3614679972331,
+ "y": 1779.417065938314,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 12.333343505859375,
+ "seed": 82951992,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 233,
+ "versionNonce": 2082066693,
+ "isDeleted": false,
+ "id": "mvfNSPpLgMxaEaQuXYPrl",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1387.0280939737956,
+ "y": 1776.7504094441733,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 94,
+ "height": 20,
+ "seed": 1266085960,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_import",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func_import"
+ },
+ {
+ "type": "text",
+ "version": 265,
+ "versionNonce": 1206611403,
+ "isDeleted": false,
+ "id": "Oe13Ts1dEazuz8ilwnZiL",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1398.6947809855144,
+ "y": 1806.7504094441733,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 34,
+ "height": 20,
+ "seed": 2145720376,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func"
+ },
+ {
+ "type": "diamond",
+ "version": 230,
+ "versionNonce": 287533157,
+ "isDeleted": false,
+ "id": "nyquujDKZGyYvDs-a_GQ-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1356.0280939737956,
+ "y": 1811.5837071736655,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 10,
+ "height": 12.333343505859375,
+ "seed": 784443208,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 252,
+ "versionNonce": 326204523,
+ "isDeleted": false,
+ "id": "cGQYK5rXelrtuGolytFol",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1332.3614679972331,
+ "y": 1765.417065938314,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 154.00006103515616,
+ "height": 79,
+ "seed": 1426411832,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "9vnyulmvSUCDWXvSKKyJ6",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 521,
+ "versionNonce": 868422597,
+ "isDeleted": false,
+ "id": "VRweEUgFB9qqzjdTwpHnK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1323.694574991862,
+ "y": 1739.194897969564,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 117,
+ "height": 20,
+ "seed": 155802936,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929332,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMFunction ",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunction "
+ },
+ {
+ "type": "arrow",
+ "version": 621,
+ "versionNonce": 746370827,
+ "isDeleted": false,
+ "id": "CUEfVWpVIuIHc_5h3VskN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1459.8716446745273,
+ "y": 1829.1380187988277,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 394.2706533635544,
+ "height": 82.19527893066447,
+ "seed": 1854588984,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "epVvbDyPF40MaERFnDDJy",
+ "focus": 0.2506598246466399,
+ "gap": 9.849883651733307
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 153.21163779617586,
+ 82.19527893066447
+ ],
+ [
+ 394.2706533635544,
+ 27.990782200797412
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 309,
+ "versionNonce": 1880511269,
+ "isDeleted": false,
+ "id": "OTP338ttAjF_rIJwNKA1S",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1298.416748046875,
+ "y": 1343.3333587646484,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 38,
+ "height": 20,
+ "seed": 1994699981,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "union",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "union"
+ },
+ {
+ "type": "rectangle",
+ "version": 62,
+ "versionNonce": 25664939,
+ "isDeleted": false,
+ "id": "7kmKkWcfD2eeTgLmci_TA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1289.75,
+ "y": 1517.3333282470703,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fab005",
+ "width": 260.66668701171875,
+ "height": 61.333343505859375,
+ "seed": 1810842211,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "fr9-3bNKWz24759an1jPs"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 13,
+ "versionNonce": 914224163,
+ "isDeleted": false,
+ "id": "fr9-3bNKWz24759an1jPs",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "dotted",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1404.5833435058594,
+ "y": 1538.4,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 20,
+ "seed": 1884299875,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247200,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "7kmKkWcfD2eeTgLmci_TA",
+ "originalText": "[...]"
+ },
+ {
+ "type": "line",
+ "version": 176,
+ "versionNonce": 1373083019,
+ "isDeleted": false,
+ "id": "pYd8BNqe32DQ1BK15gl1X",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "dotted",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1607.7500610351565,
+ "y": 911.2331604003898,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 2.2737367544323206e-13,
+ "height": 1207.7780151367188,
+ "seed": 1889947117,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533932559,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -2.2737367544323206e-13,
+ 1207.7780151367188
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 58,
+ "versionNonce": 2111671781,
+ "isDeleted": false,
+ "id": "-EA8TtLR5unZFdjT-k9mq",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "dotted",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1404.4167785644531,
+ "y": 1492.6665802001953,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 1174452173,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "text",
+ "version": 225,
+ "versionNonce": 49704683,
+ "isDeleted": false,
+ "id": "al3s0Ce-XZ_FiU84jmv0f",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 729.2799504597981,
+ "y": 1209.9554656982423,
+ "strokeColor": "#e67700",
+ "backgroundColor": "transparent",
+ "width": 171,
+ "height": 19,
+ "seed": 1330045933,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModuleInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 102,
+ "versionNonce": 555518277,
+ "isDeleted": false,
+ "id": "TxSoCCktw7hU7jU0cN2he",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 723.0834655761719,
+ "y": 1240.9998931884766,
+ "strokeColor": "#d9480f",
+ "backgroundColor": "transparent",
+ "width": 210.66668701171875,
+ "height": 305.33334350585943,
+ "seed": 598232163,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 113,
+ "versionNonce": 1941920139,
+ "isDeleted": false,
+ "id": "uyhu5MiXRFgQansSAKgbz",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1858.638671875,
+ "y": 1857.11110941569,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 229.3333740234375,
+ "height": 71.33331298828125,
+ "seed": 1064313101,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "4W7-B8UsG2Kp0-6eEN0-h"
+ },
+ {
+ "id": "CUEfVWpVIuIHc_5h3VskN",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 67,
+ "versionNonce": 1873089421,
+ "isDeleted": false,
+ "id": "4W7-B8UsG2Kp0-6eEN0-h",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1959.8053588867188,
+ "y": 1883.1777659098307,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 27,
+ "height": 20,
+ "seed": 1206387267,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247203,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[..]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "uyhu5MiXRFgQansSAKgbz",
+ "originalText": "[..]"
+ },
+ {
+ "type": "arrow",
+ "version": 335,
+ "versionNonce": 1028780075,
+ "isDeleted": false,
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 780.7038274166374,
+ "y": 1329.8562414550568,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 227.1615634556406,
+ "height": 49.895659740248675,
+ "seed": 1282951939,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "_eiwTSAQSXB8P2k-PDhNa",
+ "focus": -0.16162303890895813,
+ "gap": 1.5411549516792498
+ },
+ "endBinding": {
+ "elementId": "SWgPVXvgjtN7AVlTfBUDR",
+ "focus": 1.0022214255263049,
+ "gap": 1.3844565398313762
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 227.1615634556406,
+ -49.895659740248675
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 380,
+ "versionNonce": 1831123973,
+ "isDeleted": false,
+ "id": "EjfvS52mTJV_ntE7FAmqi",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 749.41650390625,
+ "y": 1265.500015258789,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 163,
+ "height": 38.333343505859375,
+ "seed": 908455875,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 372,
+ "versionNonce": 395899749,
+ "isDeleted": false,
+ "id": "0n8DknkuWXlRynFJmYm-N",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 760.0831298828125,
+ "y": 1276.500015258789,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1140391779,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "dA4sHNYw9NqC0yRSl1ByC",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 131,
+ "versionNonce": 169804459,
+ "isDeleted": false,
+ "id": "xwVumJFL4-d-8BM7nSKzG",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1406.5276896158855,
+ "y": 1849.9999745686848,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 25,
+ "height": 20,
+ "seed": 813534477,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[n]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[n]"
+ },
+ {
+ "type": "arrow",
+ "version": 164,
+ "versionNonce": 1833439621,
+ "isDeleted": false,
+ "id": "dA4sHNYw9NqC0yRSl1ByC",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 767.0830841064453,
+ "y": 1278.6665496826172,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 617.3333435058594,
+ "height": 168.00003051757812,
+ "seed": 1360269091,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "0n8DknkuWXlRynFJmYm-N",
+ "focus": -0.6970200254594874,
+ "gap": 1
+ },
+ "endBinding": {
+ "elementId": "IK-a-uPI373j3VM1YHdKy",
+ "focus": 0.91934006004951,
+ "gap": 5.7502593994140625
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 283.33331298828125,
+ -86.66671752929688
+ ],
+ [
+ 617.3333435058594,
+ -168.00003051757812
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 370,
+ "versionNonce": 2015327563,
+ "isDeleted": false,
+ "id": "1uhr4l-w9t4eVo0gQ06SH",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1628.0831146240234,
+ "y": 1047.333236694336,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 60,
+ "height": 20,
+ "seed": 2127932547,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "70jp9eV1jV2_kUBbN055m",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(void *)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(void *)"
+ },
+ {
+ "type": "diamond",
+ "version": 110,
+ "versionNonce": 867539173,
+ "isDeleted": false,
+ "id": "OpV38MM8YOexWG_e-5_hX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1751.5831604003906,
+ "y": 1244.7915496826172,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 8.333282470703125,
+ "height": 13.75,
+ "seed": 1876974509,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "l4S1IXvHmVx_wl8DPQXk3",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 201,
+ "versionNonce": 1052283883,
+ "isDeleted": false,
+ "id": "0VYDhNUTpNaSbemsP54Zy",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 982.6778793334961,
+ "y": 1174.3998931884767,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 68,
+ "height": 20,
+ "seed": 2080172771,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(void **)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(void **)"
+ },
+ {
+ "type": "text",
+ "version": 52,
+ "versionNonce": 364590149,
+ "isDeleted": false,
+ "id": "mEKNbQ7XuwA2N2CRqO86h",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1395.7501068115234,
+ "y": 1178.6665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 43,
+ "height": 20,
+ "seed": 95270211,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "NULL",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "NULL"
+ },
+ {
+ "type": "rectangle",
+ "version": 348,
+ "versionNonce": 306207333,
+ "isDeleted": false,
+ "id": "FKonkUbaqKFXKyt5VSiGE",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 743.0831654866537,
+ "y": 1476.5000508626301,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174.66668701171875,
+ "height": 31.666625976562507,
+ "seed": 710825357,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "0dTwoTnwCJUbyz3e0bm1O",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533956228,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 376,
+ "versionNonce": 1951705707,
+ "isDeleted": false,
+ "id": "xNodTFHQFtS6jmRfbZDpo",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 748.4164784749349,
+ "y": 1484.1667073567708,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1417026541,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533956228,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 82,
+ "versionNonce": 678544837,
+ "isDeleted": false,
+ "id": "8i8vmtgsTLeEQt_E_hLrk",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 768.4165089925131,
+ "y": 1481.0000508626301,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 149,
+ "height": 20,
+ "seed": 1944091203,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "yu3un9i0kAGrZ8bAnVMa3",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533956228,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_type_indexes",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func_type_indexes"
+ },
+ {
+ "type": "rectangle",
+ "version": 210,
+ "versionNonce": 1441855435,
+ "isDeleted": false,
+ "id": "IwrJYgHbhcHGM-MPt77v3",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 907.3989664713541,
+ "y": 1609.9723409016926,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 919532995,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 230,
+ "versionNonce": 2006154853,
+ "isDeleted": false,
+ "id": "XRMQmYFkm-FtbS8PBuF_X",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 907.0655924479166,
+ "y": 1643.1389668782551,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 361842019,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 218,
+ "versionNonce": 473286251,
+ "isDeleted": false,
+ "id": "nsMfEXFd6IeqB7fL4ngUa",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 906.7322794596354,
+ "y": 1676.4723103841145,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1923653891,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 227,
+ "versionNonce": 1069574597,
+ "isDeleted": false,
+ "id": "R5ioSAhKEdUlCurXbrHuN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 905.3989054361979,
+ "y": 1704.1389668782551,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1469286563,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 323,
+ "versionNonce": 617227531,
+ "isDeleted": false,
+ "id": "yu3un9i0kAGrZ8bAnVMa3",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 753.0831654866537,
+ "y": 1487.6672379829788,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 200.16657758128372,
+ "height": 153.3329247774377,
+ "seed": 1439562723,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533956229,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "8i8vmtgsTLeEQt_E_hLrk",
+ "focus": 1.0014597510870404,
+ "gap": 15.333343505859375
+ },
+ "endBinding": {
+ "elementId": "p5TPteQC3PraRMJtt4XsT",
+ "focus": 0.36261877029011863,
+ "gap": 3.9746450546211918
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -60.000050862630246,
+ 26.332884087333696
+ ],
+ [
+ -40.88889567057288,
+ 105.11070594605758
+ ],
+ [
+ 62.88881429036462,
+ 153.3329247774377
+ ],
+ [
+ 140.16652671865347,
+ 150.58490939994954
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 99,
+ "versionNonce": 2113464613,
+ "isDeleted": false,
+ "id": "a8gv4R6T3PYjKJhay9vMv",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 802.4165191650391,
+ "y": 1604.7780354817708,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 70,
+ "height": 20,
+ "seed": 453646061,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint32 *",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "uint32 *"
+ },
+ {
+ "type": "text",
+ "version": 97,
+ "versionNonce": 692152235,
+ "isDeleted": false,
+ "id": "eNJLe1mhF_AWRUyt9lO6k",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2227.083185195923,
+ "y": 955.9999694824219,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 96,
+ "height": 19,
+ "seed": 1711184323,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModule",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule"
+ },
+ {
+ "type": "rectangle",
+ "version": 247,
+ "versionNonce": 329940101,
+ "isDeleted": false,
+ "id": "25KRboddeZem953trnn-R",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2216.416498184204,
+ "y": 985.9999389648438,
+ "strokeColor": "#1864ab",
+ "backgroundColor": "transparent",
+ "width": 308,
+ "height": 568,
+ "seed": 847170787,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 135,
+ "versionNonce": 799881803,
+ "isDeleted": false,
+ "id": "NnvrV9DcfaaiOCGPUdP78",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2229.083246231079,
+ "y": 1003.3333129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 263,
+ "height": 224,
+ "seed": 2117157197,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": " WASMImport *import_tables;\n WASMImport *import_memories;\n WASMImport *import_globals;\n\n WASMType **types;\n WASMImport *imports;\n WASMTable *tables;\n WASMMemory *memories;\n WASMGlobal *globals;\n WASMExport *exports;\n WASMTableSeg *table_segments;\n WASMDataSeg **data_segments;",
+ "baseline": 220,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " WASMImport *import_tables;\n WASMImport *import_memories;\n WASMImport *import_globals;\n\n WASMType **types;\n WASMImport *imports;\n WASMTable *tables;\n WASMMemory *memories;\n WASMGlobal *globals;\n WASMExport *exports;\n WASMTableSeg *table_segments;\n WASMDataSeg **data_segments;"
+ },
+ {
+ "type": "rectangle",
+ "version": 123,
+ "versionNonce": 1486005221,
+ "isDeleted": false,
+ "id": "O5y5oOsgUB5ue4vWSQB0i",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2232.4165592193604,
+ "y": 1301.3332824707031,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 273.3333740234375,
+ "height": 44,
+ "seed": 1988414157,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 145,
+ "versionNonce": 709212395,
+ "isDeleted": false,
+ "id": "6xufIeHeKpvDChXCTeKSb",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2294.4165592193604,
+ "y": 1314.6665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 198,
+ "height": 19,
+ "seed": 2026661485,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMFunction **functions;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunction **functions;"
+ },
+ {
+ "type": "diamond",
+ "version": 108,
+ "versionNonce": 1354686277,
+ "isDeleted": false,
+ "id": "s4lQvHIN1eAAubp7DkNrk",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2245.083246231079,
+ "y": 1318,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 26.6666259765625,
+ "height": 19.333343505859375,
+ "seed": 1489582509,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Bnf72M4RGMZjNgBlzk90B",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 354,
+ "versionNonce": 1184195467,
+ "isDeleted": false,
+ "id": "Bnf72M4RGMZjNgBlzk90B",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2250.416437149048,
+ "y": 1332.0000305175781,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 163.1120623945253,
+ "height": 15.460472501937602,
+ "seed": 1550987139,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "s4lQvHIN1eAAubp7DkNrk",
+ "focus": -0.36983487209914556,
+ "gap": 1
+ },
+ "endBinding": {
+ "elementId": "swt6lb3ztkUJAvM41XHBK",
+ "focus": -0.7544161254824635,
+ "gap": 5.555002272222737
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -163.1120623945253,
+ 15.460472501937602
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 138,
+ "versionNonce": 579645093,
+ "isDeleted": false,
+ "id": "TfktbM2ODt0uHXCbkJtbX",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2277.4166202545166,
+ "y": 1269.3333435058594,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 229,
+ "height": 19,
+ "seed": 2140950979,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMImport *import_functions;",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMImport *import_functions;"
+ },
+ {
+ "type": "rectangle",
+ "version": 99,
+ "versionNonce": 483834411,
+ "isDeleted": false,
+ "id": "sIxEmRk_EPaTumCGaxM6t",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2231.749994277954,
+ "y": 1254.6667175292969,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 276,
+ "height": 42.6666259765625,
+ "seed": 2140310499,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 86,
+ "versionNonce": 1286181381,
+ "isDeleted": false,
+ "id": "_er3JaiUwljITdxfog0w_",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2246.416742324829,
+ "y": 1265.3334045410156,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 15.33331298828125,
+ "height": 22.66668701171875,
+ "seed": 568056877,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 453,
+ "versionNonce": 1509178571,
+ "isDeleted": false,
+ "id": "70jp9eV1jV2_kUBbN055m",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2253.0103282895525,
+ "y": 1275.9391811320388,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 323.49287390894006,
+ "height": 187.53914675447618,
+ "seed": 638625069,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "JWlL3nHzTP4pxrEVYolFx",
+ "focus": -1.0762119763220488,
+ "gap": 30.60580710860131
+ },
+ "endBinding": {
+ "elementId": "1rZk-xFL82XSp5Mpcqy4f",
+ "focus": -1.2708836305762516,
+ "gap": 14.434116596798958
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -146.59352492956714,
+ -83.93927268477319
+ ],
+ [
+ -323.49287390894006,
+ -187.53914675447618
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 145,
+ "versionNonce": 471009637,
+ "isDeleted": false,
+ "id": "4BwxH9WndrjsXga95YTvm",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1705.7500858306885,
+ "y": 1086.6665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 222.6666259765625,
+ "height": 303.33331298828125,
+ "seed": 803769283,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "70jp9eV1jV2_kUBbN055m",
+ "type": "arrow"
+ },
+ {
+ "id": "nUF7GyfmAGZN3iZvBfYtq",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 270,
+ "versionNonce": 696806251,
+ "isDeleted": false,
+ "id": "RR6mIlX4wkxcfcv6RQ8Wa",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1708.416711807251,
+ "y": 1062.6665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 97,
+ "height": 19,
+ "seed": 2042686211,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 2,
+ "text": "WASMImport",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMImport"
+ },
+ {
+ "type": "rectangle",
+ "version": 191,
+ "versionNonce": 1645647045,
+ "isDeleted": false,
+ "id": "1rZk-xFL82XSp5Mpcqy4f",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1745.749963760376,
+ "y": 1097.3333129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 169.3333740234375,
+ "height": 31,
+ "seed": 176484109,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "qkiSeaixB8ivmpNxhvY6l"
+ },
+ {
+ "id": "70jp9eV1jV2_kUBbN055m",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 162,
+ "versionNonce": 395409347,
+ "isDeleted": false,
+ "id": "qkiSeaixB8ivmpNxhvY6l",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1750.749963760376,
+ "y": 1102.3333129882812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 79,
+ "height": 20,
+ "seed": 2146735565,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247208,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint8 kind",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "middle",
+ "containerId": "1rZk-xFL82XSp5Mpcqy4f",
+ "originalText": "uint8 kind"
+ },
+ {
+ "type": "rectangle",
+ "version": 175,
+ "versionNonce": 1783739429,
+ "isDeleted": false,
+ "id": "R_f4RWhd20C8JXmaJofMm",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1706.7500247955322,
+ "y": 1390.6665954589844,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 221,
+ "height": 31,
+ "seed": 691699363,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "jXOu2RGl7KTvcY3-hwIj2"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 56,
+ "versionNonce": 2117409261,
+ "isDeleted": false,
+ "id": "jXOu2RGl7KTvcY3-hwIj2",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1806.2500247955322,
+ "y": 1396.0665954589845,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 22,
+ "height": 20,
+ "seed": 776900557,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247209,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[1]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "R_f4RWhd20C8JXmaJofMm",
+ "originalText": "[1]"
+ },
+ {
+ "type": "text",
+ "version": 51,
+ "versionNonce": 816965509,
+ "isDeleted": false,
+ "id": "JvLqnDwgx42bo19rINn18",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1807.083490371704,
+ "y": 1371.9998474121094,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 2020174093,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 185,
+ "versionNonce": 1499856715,
+ "isDeleted": false,
+ "id": "Xj5n84LklLY7rIUbMpV30",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1708.2501163482666,
+ "y": 1422.3332061767578,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 221,
+ "height": 31,
+ "seed": 1499618403,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "LOWTAqc1KaVYNxnLkXHB4"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 61,
+ "versionNonce": 2125694819,
+ "isDeleted": false,
+ "id": "LOWTAqc1KaVYNxnLkXHB4",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1803.2501163482666,
+ "y": 1427.733206176758,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 20,
+ "seed": 701124429,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247210,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Xj5n84LklLY7rIUbMpV30",
+ "originalText": "[...]"
+ },
+ {
+ "type": "rectangle",
+ "version": 50,
+ "versionNonce": 178118123,
+ "isDeleted": false,
+ "id": "qd-T97QOO_xa4SGTgkrAj",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1363.083200454712,
+ "y": 1076.0001373291016,
+ "strokeColor": "#d9480f",
+ "backgroundColor": "transparent",
+ "width": 96,
+ "height": 170.66668701171875,
+ "seed": 215655011,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "AuwWYqGK5XChc2C2ZDCOd",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 169,
+ "versionNonce": 1562872389,
+ "isDeleted": false,
+ "id": "EAEAQzFaB6T9-rCB0X-61",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2303.749662399292,
+ "y": 1418.0001983642578,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 160,
+ "height": 20,
+ "seed": 1651418499,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "fast_jit_func_ptrs",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "fast_jit_func_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 195,
+ "versionNonce": 312535179,
+ "isDeleted": false,
+ "id": "n3LUTZSRU6GJ4nfF98WsH",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2233.7496013641357,
+ "y": 1409.6669158935547,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 273.3333740234375,
+ "height": 44,
+ "seed": 1123016931,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 173,
+ "versionNonce": 312998309,
+ "isDeleted": false,
+ "id": "SOlRVdTv-nHYKomLm0-Lr",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2246.749662399292,
+ "y": 1421.000244140625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 26.6666259765625,
+ "height": 19.333343505859375,
+ "seed": 381478531,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929333,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 61,
+ "versionNonce": 1193910059,
+ "isDeleted": false,
+ "id": "RckpORzYftIA2k4VSkTaW",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2093.082914352417,
+ "y": 1731.3334503173828,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 314.6666564941406,
+ "height": 191.3333740234375,
+ "seed": 1221862445,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "sYSDwbrpZl0692xpkcG4z",
+ "focus": -0.8132904069013918,
+ "gap": 6.05506706237793
+ },
+ "endBinding": {
+ "elementId": "bu6GnR96DeCSFWu3DhMIJ",
+ "focus": -1.5131314965155,
+ "gap": 13.30013732910163
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 150.66665649414062,
+ 128.66668701171875
+ ],
+ [
+ 314.6666564941406,
+ 191.3333740234375
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 66,
+ "versionNonce": 1361280261,
+ "isDeleted": false,
+ "id": "HCvGV6j45DG_BGeI3J7ut",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2116.4162578582764,
+ "y": 1692.6667938232422,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 288.25032234191895,
+ "height": 141.39862277829707,
+ "seed": 298119629,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "SiZHwNA9YKd93iwc74wxB",
+ "focus": -0.7153529191190878,
+ "gap": 5.633312988281318
+ },
+ "endBinding": {
+ "elementId": "qVsRlSPxTl9a8XrnRMl2a",
+ "focus": -0.10195339456743455,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 125.33331298828125,
+ 108.66665649414062
+ ],
+ [
+ 288.25032234191895,
+ 141.39862277829707
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 81,
+ "versionNonce": 1654817227,
+ "isDeleted": false,
+ "id": "iqe6U9xOE6ECb18moJnw-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2083.0828227996826,
+ "y": 1640.0001068115234,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 380,
+ "height": 114.66668701171875,
+ "seed": 1655019469,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "qGjmy62MZbL7zALsNU2dL",
+ "focus": 0.8815432234830397,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 202.66668701171875,
+ 114.66668701171875
+ ],
+ [
+ 380,
+ 64
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 196,
+ "versionNonce": 1880593509,
+ "isDeleted": false,
+ "id": "pWu_lwlXIT6mrZDyT6QkK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2690.0828075408936,
+ "y": 1522.750244140625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 162247299,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "NSz4yfxdToa5c5At8YYeR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 181,
+ "versionNonce": 1847988331,
+ "isDeleted": false,
+ "id": "rBPIesLQ3_hwRCCEZDo_K",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2714.0828075408936,
+ "y": 1530.4169006347656,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 2113989421,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 216,
+ "versionNonce": 2068955077,
+ "isDeleted": false,
+ "id": "1nU3Tx2BdlitDqcIjhR6O",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2689.749433517456,
+ "y": 1555.9168701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 255355427,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 202,
+ "versionNonce": 1803471627,
+ "isDeleted": false,
+ "id": "qPuFVkGJxscoxDIlxjxO7",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2713.749433517456,
+ "y": 1563.5835266113281,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1853160845,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 205,
+ "versionNonce": 686784293,
+ "isDeleted": false,
+ "id": "ijtdWkKxrTh4Pnlp14iE0",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2689.416120529175,
+ "y": 1589.2502136230469,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 495791555,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "BF2h7Ub5gAf2yYxLfQSFh",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 215,
+ "versionNonce": 1059533227,
+ "isDeleted": false,
+ "id": "jFcNDR-eUAEW7pedWkAdo",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2688.0827465057373,
+ "y": 1616.9168701171875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 796378093,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 196,
+ "versionNonce": 257839749,
+ "isDeleted": false,
+ "id": "q4AkedYi9svz1WOMHGyiP",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2710.749433517456,
+ "y": 1625.2502136230469,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 2009628003,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 195,
+ "versionNonce": 1514783819,
+ "isDeleted": false,
+ "id": "NSz4yfxdToa5c5At8YYeR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2491.7495250701904,
+ "y": 1437.3335571289062,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 199.43811857564833,
+ "height": 81.5190719332436,
+ "seed": 909964067,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "pWu_lwlXIT6mrZDyT6QkK",
+ "focus": 0.37183947794184286,
+ "gap": 3.8976150784751553
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 199.43811857564833,
+ 81.5190719332436
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 222,
+ "versionNonce": 458996197,
+ "isDeleted": false,
+ "id": "BF2h7Ub5gAf2yYxLfQSFh",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2718.826031777619,
+ "y": 1626.7287320369785,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 207.0765067074285,
+ "height": 202.09118637438291,
+ "seed": 358411853,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "D0065Oo1uIjEqNG6iDJjn",
+ "focus": -2.935287320516118,
+ "gap": 14.961736017351072
+ },
+ "endBinding": {
+ "elementId": "qVsRlSPxTl9a8XrnRMl2a",
+ "focus": 0.3455990175110858,
+ "gap": 2.749570846557617
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -84.40981969570976,
+ 140.60479457434963
+ ],
+ [
+ -207.0765067074285,
+ 202.09118637438291
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 207,
+ "versionNonce": 616628971,
+ "isDeleted": false,
+ "id": "D0065Oo1uIjEqNG6iDJjn",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2712.0828075408936,
+ "y": 1594.1669158935547,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1454945635,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "BF2h7Ub5gAf2yYxLfQSFh",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 61,
+ "versionNonce": 1173697861,
+ "isDeleted": false,
+ "id": "OI5mleCPF3WYtCzvosMk1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2661.7495861053467,
+ "y": 1495.3336181640625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 177.33334350585938,
+ "seed": 617283619,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 81,
+ "versionNonce": 655846795,
+ "isDeleted": false,
+ "id": "4Q_PdspTfAcKBYqfwEOrl",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2534.4162731170654,
+ "y": 1478.0003051757812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 68,
+ "height": 20,
+ "seed": 468048995,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(void **)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(void **)"
+ },
+ {
+ "type": "text",
+ "version": 215,
+ "versionNonce": 176702629,
+ "isDeleted": false,
+ "id": "zEBN6RuZylHRtnzhMAsfm",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2302.082899093628,
+ "y": 1367.6669006347656,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 80,
+ "height": 20,
+ "seed": 1726260589,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_ptrs",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "func_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 240,
+ "versionNonce": 1955038251,
+ "isDeleted": false,
+ "id": "Q1RbJ8FG5PuoKZ0jGW-AG",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2232.0828380584717,
+ "y": 1359.3336181640625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 273.3333740234375,
+ "height": 44,
+ "seed": 1664381923,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 218,
+ "versionNonce": 482502661,
+ "isDeleted": false,
+ "id": "lKOq2jf5D0WXwfNx9mwVb",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2245.082899093628,
+ "y": 1370.6669464111328,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 26.6666259765625,
+ "height": 19.333343505859375,
+ "seed": 1869049805,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 197,
+ "versionNonce": 1425786571,
+ "isDeleted": false,
+ "id": "5_VLE0dE94H4gwxL9iUpC",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2851.4160289764404,
+ "y": 1432.750228881836,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1330766563,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "8jHbZMq4zvKK9AxPUw9Qf",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 181,
+ "versionNonce": 1587617637,
+ "isDeleted": false,
+ "id": "k1p6Nabm5uz-_RQk8vKUy",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2875.4160289764404,
+ "y": 1440.4168853759766,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1901883597,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 216,
+ "versionNonce": 789493099,
+ "isDeleted": false,
+ "id": "BH3ZK-RnoIcnosroWZ9_J",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2851.082654953003,
+ "y": 1465.9168548583984,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 897158787,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 202,
+ "versionNonce": 376564421,
+ "isDeleted": false,
+ "id": "cAmZfC7YbkEqrmByhjjHI",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2875.082654953003,
+ "y": 1473.583511352539,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 596561709,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 205,
+ "versionNonce": 839569419,
+ "isDeleted": false,
+ "id": "yAeZ1rNDP97dzjt5edJvJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2850.7493419647217,
+ "y": 1499.2501983642578,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1022019107,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 215,
+ "versionNonce": 1691503141,
+ "isDeleted": false,
+ "id": "h_AbFbWb_N0KfOV68sJf6",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2849.415967941284,
+ "y": 1526.9168548583984,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1889952141,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 196,
+ "versionNonce": 1072338603,
+ "isDeleted": false,
+ "id": "OKOuC260x6EDIVInqBKer",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2872.082654953003,
+ "y": 1535.2501983642578,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 479463875,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 208,
+ "versionNonce": 2058337669,
+ "isDeleted": false,
+ "id": "zQXps3l6_CULfrKz0sxFV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2873.4160289764404,
+ "y": 1504.1669006347656,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 769435629,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "4E9MghnYo6hn8E82pmPMe",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 61,
+ "versionNonce": 391678283,
+ "isDeleted": false,
+ "id": "4EdLS1fcNDOsz52Mf7ATN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2823.0828075408936,
+ "y": 1405.3336029052734,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 177.33334350585938,
+ "seed": 697555299,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 108,
+ "versionNonce": 256361701,
+ "isDeleted": false,
+ "id": "8jHbZMq4zvKK9AxPUw9Qf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2495.082899093628,
+ "y": 1376.0003051757812,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 355.3333740234375,
+ "height": 55.999969482421875,
+ "seed": 424364771,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "5_VLE0dE94H4gwxL9iUpC",
+ "focus": 0.6186308498480104,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 355.3333740234375,
+ 55.999969482421875
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 44,
+ "versionNonce": 1034889195,
+ "isDeleted": false,
+ "id": "PamsTN-BPmxTRCvWvz1kZ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2636.5496044158936,
+ "y": 1377.7335876464845,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 68,
+ "height": 20,
+ "seed": 508079075,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(void **)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(void **)"
+ },
+ {
+ "type": "arrow",
+ "version": 101,
+ "versionNonce": 371712069,
+ "isDeleted": false,
+ "id": "4E9MghnYo6hn8E82pmPMe",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2877.7495250701904,
+ "y": 1546.6669921875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 317.33331298828125,
+ "height": 370,
+ "seed": 625293229,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "zQXps3l6_CULfrKz0sxFV",
+ "focus": -3.2298254921305025,
+ "gap": 13.691591814926234
+ },
+ "endBinding": {
+ "elementId": "Z9cJSNSjDvW2uPNthdOW9",
+ "focus": 0.3950527937625778,
+ "gap": 3.582883834838867
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -144,
+ 266
+ ],
+ [
+ -317.33331298828125,
+ 370
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 219,
+ "versionNonce": 687403659,
+ "isDeleted": false,
+ "id": "swt6lb3ztkUJAvM41XHBK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2033.7493724822998,
+ "y": 1348.4170532226562,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 177857187,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Bnf72M4RGMZjNgBlzk90B",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 203,
+ "versionNonce": 892178341,
+ "isDeleted": false,
+ "id": "MlaoCVMw-5S2Yi8P1HjDR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2057.7493724823,
+ "y": 1356.0837097167969,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1852132621,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 238,
+ "versionNonce": 703621419,
+ "isDeleted": false,
+ "id": "TiGonLf-juzwJEoH9VSZD",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2033.4159984588623,
+ "y": 1381.5836791992188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 254514755,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 224,
+ "versionNonce": 2055623429,
+ "isDeleted": false,
+ "id": "3YRJV9k9ywr0i4pEZkHkN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2057.4159984588623,
+ "y": 1389.2503356933594,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 2075272045,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 227,
+ "versionNonce": 369101771,
+ "isDeleted": false,
+ "id": "33dfOgt2KTLk3Q5NBImFr",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2033.082685470581,
+ "y": 1414.9170227050781,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1787155939,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 237,
+ "versionNonce": 1387244133,
+ "isDeleted": false,
+ "id": "92FFROdmhjPmxEpXFFQ5M",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2031.7493114471436,
+ "y": 1442.5836791992188,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1238707661,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 218,
+ "versionNonce": 826432107,
+ "isDeleted": false,
+ "id": "QULGDwKUKXLejiOFZCB88",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2054.4159984588623,
+ "y": 1450.9170227050781,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1270292867,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 230,
+ "versionNonce": 1047991749,
+ "isDeleted": false,
+ "id": "-dLa28cPs8d1YMU273D-q",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2055.7493724823,
+ "y": 1419.833724975586,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1206381613,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "uC3ZSm-IltHDllxDGLJ9v",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 83,
+ "versionNonce": 1484903691,
+ "isDeleted": false,
+ "id": "diotVPud8Nk4qCzgu2hJi",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2005.416151046753,
+ "y": 1321.0004272460938,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 177.33334350585938,
+ "seed": 2080241955,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 89,
+ "versionNonce": 1224348965,
+ "isDeleted": false,
+ "id": "uC3ZSm-IltHDllxDGLJ9v",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2061.749616622925,
+ "y": 1459.3337860107422,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 103.33331298828125,
+ "height": 104.66668701171875,
+ "seed": 687885357,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "-dLa28cPs8d1YMU273D-q",
+ "focus": 3.424460294999428,
+ "gap": 11.855942213284369
+ },
+ "endBinding": {
+ "elementId": "0kWlc6iPzGzhrfIVEPeOM",
+ "focus": 0.1363752482649436,
+ "gap": 1.5828227996826172
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 103.33331298828125,
+ 64.66668701171875
+ ],
+ [
+ 67.3333740234375,
+ 104.66668701171875
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 107,
+ "versionNonce": 1798896555,
+ "isDeleted": false,
+ "id": "Ba0bmo-eQQnhNNi6zcCzg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2259.0828075408936,
+ "y": 1502.6670684814453,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 177,
+ "height": 40,
+ "seed": 1174246765,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": " uint8 *load_addr;\n uint64 load_size;",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": " uint8 *load_addr;\n uint64 load_size;"
+ },
+ {
+ "type": "rectangle",
+ "version": 43,
+ "versionNonce": 1034299525,
+ "isDeleted": false,
+ "id": "SOEOh6pxx-gC9L5EGGFZb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2247.082929611206,
+ "y": 1502.6670684814453,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 256,
+ "height": 38,
+ "seed": 1478394307,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 17,
+ "versionNonce": 1972522571,
+ "isDeleted": false,
+ "id": "KcLwCwuZF-_XQTvbSOePf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2267.7495555877686,
+ "y": 1506.6670684814453,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 17.3333740234375,
+ "height": 13.333343505859375,
+ "seed": 1278561005,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 58,
+ "versionNonce": 507039717,
+ "isDeleted": false,
+ "id": "f7JIg_N3m3yBHDkQvlpUn",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2275.7495555877686,
+ "y": 1510.6670684814453,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 63.33331298828125,
+ "height": 94.00003051757812,
+ "seed": 646153155,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -63.33331298828125,
+ 70
+ ],
+ [
+ -19.33331298828125,
+ 94.00003051757812
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 331,
+ "versionNonce": 443043051,
+ "isDeleted": false,
+ "id": "epVvbDyPF40MaERFnDDJy",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1858.9132976531982,
+ "y": 1828.5115061442057,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 238,
+ "height": 20,
+ "seed": 2133258755,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "CUEfVWpVIuIHc_5h3VskN",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMFunction (second module)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMFunction (second module)"
+ },
+ {
+ "type": "text",
+ "version": 36,
+ "versionNonce": 1488948037,
+ "isDeleted": false,
+ "id": "iSNS4LqcpEqsBWT3JrhTG",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1985.4163494110107,
+ "y": 1302.0003509521484,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 176,
+ "height": 20,
+ "seed": 895067437,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::functions",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::functions"
+ },
+ {
+ "type": "text",
+ "version": 58,
+ "versionNonce": 1027962763,
+ "isDeleted": false,
+ "id": "zzptLpjImiiG1vPCDIGPS",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2788.5657176971436,
+ "y": 1386.4003204345704,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 185,
+ "height": 20,
+ "seed": 510558371,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::func_ptrs",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::func_ptrs"
+ },
+ {
+ "type": "text",
+ "version": 84,
+ "versionNonce": 1033362085,
+ "isDeleted": false,
+ "id": "QPiZaCnPYGIz7ApGqrktI",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2629.160482406616,
+ "y": 1451.7336334228517,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 160,
+ "height": 40,
+ "seed": 1301033645,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModule::\nfast_jit_func_ptrs",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModule::\nfast_jit_func_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 444,
+ "versionNonce": 1818512939,
+ "isDeleted": false,
+ "id": "bGS26pMiud1SV_QZasA4k",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 753.6687545776367,
+ "y": 1354.399984741211,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 140.66668701171875,
+ "height": 32.33331298828126,
+ "seed": 1104978987,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "E9Lf0GGwiMXE7OEKmLBD0"
+ }
+ ],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 223,
+ "versionNonce": 498422861,
+ "isDeleted": false,
+ "id": "E9Lf0GGwiMXE7OEKmLBD0",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 784.0020980834961,
+ "y": 1360.0666412353517,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 80,
+ "height": 20,
+ "seed": 1389316101,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679537247214,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "func_ptrs",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "bGS26pMiud1SV_QZasA4k",
+ "originalText": "func_ptrs"
+ },
+ {
+ "type": "diamond",
+ "version": 480,
+ "versionNonce": 179261643,
+ "isDeleted": false,
+ "id": "3V5jOnV9GBHrydrWDjdlN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 764.3353805541992,
+ "y": 1366.7332977294923,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 2058151627,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 64,
+ "versionNonce": 927151461,
+ "isDeleted": false,
+ "id": "Ej1XTEhuVY9wBpKERi-1L",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 772.668815612793,
+ "y": 1274.0665191650392,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 140,
+ "height": 20,
+ "seed": 1144833349,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "import_func_ptrs",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "import_func_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 521,
+ "versionNonce": 50715531,
+ "isDeleted": false,
+ "id": "OFyAqRR6a69cDApnQUNYF",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 735.2243474324545,
+ "y": 1412.3998321533204,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 185.3334045410156,
+ "height": 34.99996948242188,
+ "seed": 1243189643,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533960843,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 511,
+ "versionNonce": 2105521829,
+ "isDeleted": false,
+ "id": "Nv_mYV9MitkgQQoVIZJ9H",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 737.8910039265951,
+ "y": 1424.3998321533204,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1000679467,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533960843,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 85,
+ "versionNonce": 1685598763,
+ "isDeleted": false,
+ "id": "sB-lDN4LgjZtFuvGEHopU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 753.8910039265951,
+ "y": 1421.2331756591798,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 160,
+ "height": 20,
+ "seed": 967892165,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "WmAyzG_eOk5gu9ag2e4NN",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533960843,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "fast_jit_func_ptrs",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "fast_jit_func_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 247,
+ "versionNonce": 1175609515,
+ "isDeleted": false,
+ "id": "bEyCLX9k_ShKiQzS-ZFKc",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 871.6685104370117,
+ "y": 1862.1498245239259,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1755598347,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929334,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 231,
+ "versionNonce": 591500165,
+ "isDeleted": false,
+ "id": "mz6MyUFqd-cTtlX0HmAqX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 895.6685104370117,
+ "y": 1869.8164810180665,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 488090661,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 266,
+ "versionNonce": 1509364555,
+ "isDeleted": false,
+ "id": "i6UWgN6SrSs9asopho9X_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 871.3351364135742,
+ "y": 1895.3164505004884,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 581194923,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 252,
+ "versionNonce": 858708709,
+ "isDeleted": false,
+ "id": "OxO-Lw3MtI3B3_yxI_9BQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 895.3351364135742,
+ "y": 1902.983106994629,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 133750661,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 255,
+ "versionNonce": 2146202091,
+ "isDeleted": false,
+ "id": "Av0IXtuoDwPzsT4d4ZD9r",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 871.001823425293,
+ "y": 1928.6497940063477,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 942311243,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 265,
+ "versionNonce": 414987845,
+ "isDeleted": false,
+ "id": "zsHPiP1O3kL8Jo_YTK1SB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 869.6684494018555,
+ "y": 1956.3164505004884,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 454862565,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 246,
+ "versionNonce": 150797451,
+ "isDeleted": false,
+ "id": "QkKoENHz9noDS00xsmwGp",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 892.3351364135742,
+ "y": 1964.6497940063477,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 798057963,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 258,
+ "versionNonce": 1321674149,
+ "isDeleted": false,
+ "id": "8h3LnYKSejC6NlmCDjN_T",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 893.6685104370117,
+ "y": 1933.5664962768556,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1494254149,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 127,
+ "versionNonce": 1469009605,
+ "isDeleted": false,
+ "id": "8FJ9nE4COwUuKYB0Fjze2",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 843.3352890014648,
+ "y": 1851.0666336059571,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 160.99990844726562,
+ "seed": 1608741003,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "WmAyzG_eOk5gu9ag2e4NN",
+ "type": "arrow"
+ },
+ {
+ "id": "Xr0h90XMpFNQFRcVNp-Qb",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679534054366,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 103,
+ "versionNonce": 410855685,
+ "isDeleted": false,
+ "id": "xkXUNjzkhjNlrNaWU9GPX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 826.6688613891602,
+ "y": 1811.3999618530274,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174,
+ "height": 40,
+ "seed": 380760485,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstance::\nfast_jit_func_ptrs",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance::\nfast_jit_func_ptrs"
+ },
+ {
+ "type": "arrow",
+ "version": 98,
+ "versionNonce": 1677433349,
+ "isDeleted": false,
+ "id": "WmAyzG_eOk5gu9ag2e4NN",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 742.8910344441732,
+ "y": 1433.2344728128833,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 187.33331298828125,
+ "height": 431.9987943990309,
+ "seed": 471597803,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533960844,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "sB-lDN4LgjZtFuvGEHopU",
+ "focus": 1.017117824752581,
+ "gap": 10.999969482421875
+ },
+ "endBinding": {
+ "elementId": "8FJ9nE4COwUuKYB0Fjze2",
+ "focus": 0.09986159259017957,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -87.5555318196615,
+ 110.66535934043713
+ ],
+ [
+ -41.555531819661496,
+ 281.99876388145276
+ ],
+ [
+ 99.77778116861975,
+ 431.9987943990309
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 261,
+ "versionNonce": 227189867,
+ "isDeleted": false,
+ "id": "AXS2auzqFNZS35F2ixu8Z",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1039.001808166504,
+ "y": 1963.98309173584,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1019623493,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 245,
+ "versionNonce": 1630563269,
+ "isDeleted": false,
+ "id": "cjLfuQX8dFdgByjdkn0sY",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1063.001808166504,
+ "y": 1971.6497482299806,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 67902091,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 280,
+ "versionNonce": 1496375051,
+ "isDeleted": false,
+ "id": "O8ko0NdUbnEnqQSXbDcTn",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1038.6684341430664,
+ "y": 1997.1497177124024,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 641787813,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 266,
+ "versionNonce": 907586341,
+ "isDeleted": false,
+ "id": "MK_yFDygTjEm7c4A1RI_A",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1062.6684341430664,
+ "y": 2004.816374206543,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 140415275,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 269,
+ "versionNonce": 1433847211,
+ "isDeleted": false,
+ "id": "IpQhaQLL8LX1JsLCZTqHR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1038.3351211547852,
+ "y": 2030.4830612182618,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 527346437,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 279,
+ "versionNonce": 1988230789,
+ "isDeleted": false,
+ "id": "G_B8CuUKKojKnmDg-blQS",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1037.0017471313477,
+ "y": 2058.1497177124024,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 48,
+ "height": 29,
+ "seed": 1416180683,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 261,
+ "versionNonce": 696703051,
+ "isDeleted": false,
+ "id": "bubXHX2zzv6QsRGmmBlvp",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1059.6684341430664,
+ "y": 2066.483061218262,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 1758265957,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "kjpM2qWJqDrV-jr9XK8QR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 272,
+ "versionNonce": 959047141,
+ "isDeleted": false,
+ "id": "p2Ps7ouZR4NFea5dxTpPY",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1061.001808166504,
+ "y": 2035.3997634887696,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 10.66668701171875,
+ "height": 17.666656494140625,
+ "seed": 407274091,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 142,
+ "versionNonce": 161780453,
+ "isDeleted": false,
+ "id": "PZQU4Sc5stYlZLaGSiYZg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1010.668586730957,
+ "y": 1952.8999008178712,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98.66668701171875,
+ "height": 160.99990844726562,
+ "seed": 1462332869,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "eXEUtswyqJzZHgjz8P_J5",
+ "type": "arrow"
+ },
+ {
+ "id": "BcRoQEkrTOTzUxX-Uw8S8",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679534050516,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 119,
+ "versionNonce": 1629348165,
+ "isDeleted": false,
+ "id": "RolknO7AhmdfdQTNiXJ8F",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 994.0021591186523,
+ "y": 1913.2332290649415,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 174,
+ "height": 40,
+ "seed": 482409739,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "eXEUtswyqJzZHgjz8P_J5",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstance::\nfunc_ptrs",
+ "baseline": 34,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance::\nfunc_ptrs"
+ },
+ {
+ "type": "rectangle",
+ "version": 222,
+ "versionNonce": 824148363,
+ "isDeleted": false,
+ "id": "p5TPteQC3PraRMJtt4XsT",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 897.2243372599283,
+ "y": 1585.9554707845052,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 74.666748046875,
+ "height": 160.99990844726562,
+ "seed": 727269189,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "yu3un9i0kAGrZ8bAnVMa3",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 444,
+ "versionNonce": 841297547,
+ "isDeleted": false,
+ "id": "eXEUtswyqJzZHgjz8P_J5",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 771.3355026245117,
+ "y": 1374.8998474121095,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 384.88897705078125,
+ "height": 633.6667022705078,
+ "seed": 539008875,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533948630,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "PZQU4Sc5stYlZLaGSiYZg",
+ "focus": 0.2318272147781851,
+ "gap": 3.3330230712890625
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -148.888916015625,
+ 184.1111602783203
+ ],
+ [
+ 15.555613199869754,
+ 612.4444732666016
+ ],
+ [
+ 236.00006103515625,
+ 633.6667022705078
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 83,
+ "versionNonce": 745347115,
+ "isDeleted": false,
+ "id": "kjpM2qWJqDrV-jr9XK8QR",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1063.3354822794595,
+ "y": 2044.0108703613284,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 1343.333333333333,
+ "height": 143.33333333333326,
+ "seed": 738327429,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "bubXHX2zzv6QsRGmmBlvp",
+ "focus": -3.5383188444895577,
+ "gap": 13.041657453315548
+ },
+ "endBinding": {
+ "elementId": "bu6GnR96DeCSFWu3DhMIJ",
+ "focus": -0.1414139865892621,
+ "gap": 14.399755859375318
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 790,
+ 23.888905843098883
+ ],
+ [
+ 1343.333333333333,
+ -119.44442749023438
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 258,
+ "versionNonce": 1857033221,
+ "isDeleted": false,
+ "id": "VCjoZw1mwV4c94ES2JChm",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 708.2243372599285,
+ "y": 1804.0109212239581,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 68,
+ "height": 20,
+ "seed": 1329151115,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "(void **)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "(void **)"
+ },
+ {
+ "type": "text",
+ "version": 317,
+ "versionNonce": 588176075,
+ "isDeleted": false,
+ "id": "8pDOO3W9GlOqpH8OfM3H_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1274.502098083496,
+ "y": 1674.5109720865876,
+ "strokeColor": "#e67700",
+ "backgroundColor": "transparent",
+ "width": 246,
+ "height": 19,
+ "seed": 73971563,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModuleInstance(second)",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance(second)"
+ },
+ {
+ "type": "rectangle",
+ "version": 271,
+ "versionNonce": 2113489765,
+ "isDeleted": false,
+ "id": "Rcref7JZ-AhlcXLLdwY5D",
+ "fillStyle": "solid",
+ "strokeWidth": 4,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1264.668805440267,
+ "y": 1697.4554453531891,
+ "strokeColor": "#d9480f",
+ "backgroundColor": "transparent",
+ "width": 270.66663614908845,
+ "height": 194.22224934895837,
+ "seed": 635278027,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "MLVyGZQLa4jU554J6bsmJ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679533929335,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 226,
+ "versionNonce": 1289066309,
+ "isDeleted": false,
+ "id": "CZNopRssr82fjSim4TRBD",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 601.1133956909175,
+ "y": 2080.3445597330715,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 335,
+ "height": 20,
+ "seed": 556524395,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679534038146,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "function pointer arrays for faster access",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "function pointer arrays for faster access"
+ },
+ {
+ "type": "rectangle",
+ "version": 45,
+ "versionNonce": 815465317,
+ "isDeleted": false,
+ "id": "J2L3EeElp1XhI1X3IbanK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 578.8910547892249,
+ "y": 2055.122269694009,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 364.4444274902344,
+ "height": 58.33338419596339,
+ "seed": 1181100939,
+ "groupIds": [],
+ "roundness": {
+ "type": 3
+ },
+ "boundElements": [
+ {
+ "id": "BcRoQEkrTOTzUxX-Uw8S8",
+ "type": "arrow"
+ },
+ {
+ "id": "Xr0h90XMpFNQFRcVNp-Qb",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679534054366,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 33,
+ "versionNonce": 57793355,
+ "isDeleted": false,
+ "id": "BcRoQEkrTOTzUxX-Uw8S8",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 944.4466272989905,
+ "y": 2095.1223205566394,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 63.33333333333326,
+ "height": 19.444478352864735,
+ "seed": 132937093,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679534050516,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "J2L3EeElp1XhI1X3IbanK",
+ "focus": 0.788606211312463,
+ "gap": 1.11114501953125
+ },
+ "endBinding": {
+ "elementId": "PZQU4Sc5stYlZLaGSiYZg",
+ "focus": -0.2743956700481259,
+ "gap": 2.8886260986332672
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 63.33333333333326,
+ -19.444478352864735
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 24,
+ "versionNonce": 2098532715,
+ "isDeleted": false,
+ "id": "Xr0h90XMpFNQFRcVNp-Qb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 786.6688156127926,
+ "y": 2054.011175537108,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 55.555572509765625,
+ "height": 45.00000000000023,
+ "seed": 1053702635,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679534054366,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "J2L3EeElp1XhI1X3IbanK",
+ "focus": -0.054183297415777855,
+ "gap": 1.1110941569011175
+ },
+ "endBinding": {
+ "elementId": "8FJ9nE4COwUuKYB0Fjze2",
+ "focus": -0.3037089268567984,
+ "gap": 1.110900878906591
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 55.555572509765625,
+ -45.00000000000023
+ ]
+ ]
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.svg b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.svg
new file mode 100644
index 000000000..86fdf78ad
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_function.svg
@@ -0,0 +1,16 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2414.674662907919 1314.9250816685449" width="2414.674662907919" height="1314.9250816685449">
+ <!-- svg-source:excalidraw -->
+
+ <defs>
+ <style class="style-fonts">
+ @font-face {
+ font-family: "Virgil";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Virgil.woff2");
+ }
+ @font-face {
+ font-family: "Cascadia";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Cascadia.woff2");
+ }
+ </style>
+ </defs>
+ <rect x="0" y="0" width="2414.674662907919" height="1314.9250816685449" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(1685.6091130574548 849.1942151387533) rotate(0 75.33334350585938 21.500015258789062)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.33 6.06 C1.78 4.49, 3.35 3.97, 5 -0.22 M-0.58 6.42 C0.75 4.96, 2.47 3.26, 4.64 0.31 M0.81 13.46 C4.57 8.36, 6.51 5.17, 9.49 0.32 M-0.25 11.3 C2.42 9.07, 4.32 6, 11.33 0.03 M-1.05 17.97 C4.01 10.05, 12.67 3.76, 14.57 -1.47 M-0.01 18.54 C4.35 13.74, 8.32 7.95, 16.26 1.3 M0.68 24.55 C10.46 13.13, 17.8 3.77, 21.51 0.31 M0 24.15 C6.38 16.93, 14.23 8.61, 21.42 -0.48 M-1.44 30.99 C10.18 19.68, 19.6 6.91, 25.18 2.22 M-0.26 29.8 C7.31 22.39, 15.08 14.01, 25.31 -0.59 M0.32 38.86 C11.43 23.31, 22.87 9.41, 30.2 -1.41 M-0.78 37.25 C9.06 26.28, 19.27 15.74, 32.1 -0.38 M0.56 42.62 C9.97 31.48, 20.08 21.83, 34.92 2.15 M-0.37 43.2 C10.61 30.66, 20.03 18.23, 37.77 -0.54 M3.53 46.6 C20.38 28.87, 35.38 8.7, 42.19 0.51 M3.92 44.52 C16.58 28.13, 30.33 13.65, 42.63 -0.31 M8.74 44.07 C16.49 32.16, 28.41 23.07, 47.57 0.7 M8.11 45.52 C23.69 26.86, 38.82 9.36, 47.3 -0.77 M14.39 45.41 C21.28 36.79, 30.77 24.84, 54.14 1.6 M14.51 44.46 C26.6 30.2, 37.4 16.08, 53.21 -0.07 M19.53 43.9 C34.67 26.77, 50.73 12.05, 56.68 -1.48 M19.63 45.51 C26.57 34.6, 35.27 26.25, 58.64 -0.65 M23.56 43.97 C34.89 34.14, 44.77 20.9, 64.47 -0.37 M23.38 45.27 C32.13 35.64, 41.44 26.66, 63.16 -0.56 M29.72 45.91 C41.51 31.78, 55.59 13.39, 69.54 -1.49 M30.38 45.76 C39.96 32.36, 50.07 21.38, 69.68 -0.65 M32.66 46.67 C48.12 32.32, 57 18.99, 73.36 -1.39 M35.23 45.46 C49.09 28.39, 65.25 11.44, 74.93 0.16 M40.48 45.1 C52.65 31.99, 65.64 17.58, 79.18 1.8 M40.32 44.74 C53.76 29.28, 66.28 15.01, 79.44 -0.37 M43.06 46.42 C52.02 34.87, 60.11 27.89, 86.72 0.82 M45.9 46.68 C55.75 33.72, 66.08 23.14, 84.08 -1.06 M50.73 46.75 C62.65 34.22, 71.15 18.19, 88.42 -0.2 M50.52 45.78 C61.02 32.62, 71.55 21.57, 90.04 -0.54 M54.56 45.61 C68.97 28.59, 82.37 12.15, 96.21 -1.23 M55.04 46.72 C69.15 29.24, 83.23 14.97, 95.32 -0.52 M61.12 46.38 C68.75 33.18, 77.51 23.55, 101.78 -1.85 M61.16 45.09 C70.55 34.38, 78.59 25.2, 100.75 0.98 M64.71 44.88 C77.32 33.28, 84.54 22.24, 107.26 -0.77 M65.4 46.2 C76.22 35.08, 87.41 22.71, 106.47 0.37 M70.09 45.76 C85.98 29.92, 100.32 15.25, 109.56 0.73 M71.59 45.76 C82.41 32.96, 92.98 21.53, 111.95 -0.78 M76.79 47.12 C87.88 32.78, 100.18 22.8, 114.38 -0.01 M76.87 44.66 C87.86 33.28, 98.63 20.57, 115.82 -0.19 M81.8 44.91 C92.46 30.95, 103.06 22.4, 123.8 1.71 M82.23 45.73 C95.58 30.41, 108.77 14.93, 121.15 0.07 M87.85 45.49 C101.76 29.82, 118.09 11.31, 127.8 -1.21 M88.46 46.49 C101.54 28.22, 117.42 10.97, 126.75 0.64 M94.16 46.09 C109.87 26.67, 124.86 9.77, 134.31 1.47 M92.67 45.86 C102.53 35.17, 111.04 25.27, 132.99 0.31 M96.68 47.37 C113.56 28.52, 128.76 11.05, 137.52 1.91 M98.3 44.96 C106.44 34.29, 117.25 22.99, 137.81 0.82 M102.85 45.83 C120.91 29.29, 134.77 11.04, 144.61 -1.35 M103.61 45.84 C114.21 34.92, 122.59 23.58, 143.22 -0.42 M107.83 46.41 C115.86 35.96, 125.19 26.96, 147.97 1.12 M109.66 46.22 C117.53 35.46, 124.68 27.96, 147.32 0.43 M113.28 46.9 C125.6 33.43, 135.11 20.59, 150.69 -0.34 M114.85 44.26 C122.65 35.83, 130.82 26.91, 153.43 1.9 M119.59 46.51 C129.31 33.2, 142.37 17.43, 150.76 6 M118.91 45.29 C130.15 34.73, 140.22 22.76, 152.15 7.98 M124.62 46.31 C135.75 34.02, 145.66 21.97, 151.73 12.7 M125.36 44.58 C130.87 39.43, 136.17 32.08, 151.73 13.75 M132 45.8 C136.26 35.88, 145.12 28.07, 152.43 21.78 M129.57 46.07 C135.96 38.14, 143.7 29.71, 151.52 20.28 M133.14 44.1 C139.99 39.87, 144.66 37.73, 153.03 25.36 M134.55 45.89 C141.88 39.09, 147.86 30.61, 151.81 25.56 M139.03 44.77 C143.79 41.47, 148.89 36.93, 150.76 30.6 M140.31 45.34 C144.49 41.39, 149.65 35.4, 153 31.55 M146.24 45.03 C148.54 44.42, 149.67 40.89, 151.35 39.01 M145.3 45.85 C147.36 44.32, 148.19 42.53, 152.73 38.63" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M1.51 0.92 C61.47 2.18, 121.27 -1.04, 151.55 -0.05 M0.83 -0.95 C41.62 0.34, 84.98 0.8, 150.53 -0.84 M148.78 -0.67 C149.41 9.37, 149.71 18.05, 148.69 41.19 M149.97 0.08 C150.01 16.18, 150.58 31.78, 151.14 42.6 M150.73 42.52 C118.82 42.52, 89.82 42.2, 1.43 44.87 M149.93 42.77 C112.18 40.59, 74.17 40.78, -0.01 43.02 M0.41 42.59 C-0.81 26.06, 1.05 11.07, 1.91 1.1 M0.67 42.13 C-0.6 33.11, 0.64 22.32, -0.83 -0.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(728.3035558064782 941.6942507425946) rotate(0 107.16666666666674 61.333343505859375)"><path d="M1.27 -1.29 C50.59 1.05, 101.95 1.14, 213.27 1.22 M215.96 1.82 C215.75 46.27, 212.92 97.65, 215.59 121.37 M214.12 121 C162.75 121.14, 111.32 122.97, 1.45 124.37 M-0.08 123.98 C0.21 97.45, 1.23 74.02, 1.46 1.59" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g stroke-linecap="round" transform="translate(1657.5254433949792 187.3609174092611) rotate(0 139.33331298828125 122.00001525878906)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.27 5.94 C0.31 5.34, 2.51 3.45, 4.37 0.21 M-0.33 6.38 C1.36 4.07, 3.37 2.35, 5.29 0.17 M-0.1 13.1 C3.34 9.15, 4.56 5.89, 9.32 -1.19 M-0.22 11.96 C2.01 9.77, 5.42 6.47, 11.32 0.4 M-0.84 16.98 C3.67 14.88, 8.25 9.94, 16.58 -0.92 M0.31 18.14 C4.88 12.48, 11.07 4.69, 14.94 -0.01 M-0.79 23.58 C4.07 17.59, 10.25 11.64, 22.15 1.89 M1.26 23.9 C5.63 18.22, 11.03 11.43, 20.48 -0.55 M-1.04 31.03 C8.4 21.11, 16.72 9.7, 25.49 2.04 M0.84 30.67 C8.6 21.29, 16.11 11.38, 26.26 -0.32 M0.28 36.26 C7.27 30.67, 16.15 19.79, 30.41 -0.45 M0.48 37.56 C9.84 24.87, 20.35 13.56, 32.49 0.6 M0.99 41.64 C11.21 30.77, 21.82 13.95, 36.48 -0.57 M-0.2 43.05 C10.03 30.92, 18.02 19.51, 36.24 -0.22 M1.78 47.31 C12 35.02, 21.61 24.2, 43.14 1.75 M0.66 49.79 C11.1 36.22, 21.78 24.69, 41.68 -0.17 M1.75 53.94 C10.26 40.54, 22.63 26.68, 49.45 1.7 M0.79 54.69 C9.49 43.55, 19.81 32.47, 46.89 0.93 M-1.91 62.83 C16.3 42.04, 34.7 22.74, 54.26 -0.34 M0.59 61.53 C12.34 45.75, 24.93 32.4, 54.14 0.27 M1.64 66.73 C19.44 45.72, 42.6 20.2, 59.9 1.25 M0.7 67.06 C21.73 42.12, 44.02 17.22, 58.67 0.54 M-0.18 74.09 C19.03 53.68, 34.02 34.62, 64.34 -0.63 M0.15 73.78 C17.11 50.78, 37.03 29.85, 62.95 -0.63 M1.64 79.45 C22.75 53.68, 42.81 31.77, 68.92 -1.67 M-0.67 79.65 C24.14 52.77, 48.56 24.77, 69.49 -0.17 M-0.81 84.21 C26.28 53.95, 57.17 22.48, 74.51 -0.16 M0.7 85.3 C21.74 57.94, 45.02 31.81, 75.11 -0.13 M1.36 90.71 C21.15 68.55, 43.77 40.5, 81.19 -0.86 M0.49 91.51 C24.34 65.33, 47.03 39.56, 79.72 0.82 M-0.64 99.03 C19.54 77.46, 40.42 54.6, 84.49 -1.02 M-0.61 98.43 C30.07 64.23, 59.62 27.54, 84.59 -1.19 M-0.34 105.28 C32.2 66.83, 66.22 27.01, 90.99 1.76 M-0.43 103.26 C29.34 69.79, 59.45 36.88, 89.17 -0.7 M-0.97 109.99 C36.55 67.9, 70.06 28.23, 94.6 -0.44 M0.78 109.03 C37.52 67.53, 75.39 24.32, 95.31 0.51 M-0.01 116.82 C34.72 78.62, 65.81 39.47, 100.19 -1.8 M-0.07 114.77 C23.04 88.84, 44.2 64.12, 100.12 -0.11 M-1.45 120.72 C27.37 89.86, 57.18 57.72, 107.78 -0.7 M-0.07 122.02 C34.51 83.81, 69.69 44.3, 106.15 -0.39 M-0.28 126.66 C28.39 96.2, 54.9 65.5, 112.25 0.35 M-0.76 129.01 C28.34 95.51, 56.53 63.84, 112.29 1 M0.5 134 C40.47 85.86, 79.72 38.41, 114.87 1.54 M0 133.38 C41.79 84.15, 84.86 35.64, 115.28 0.79 M-1.19 138.78 C33.42 99.95, 66.34 61.99, 122.23 -1.97 M-0.94 139.95 C39.64 94.22, 79.06 51.17, 121.86 -0.18 M-0.93 146.52 C25.24 115.22, 52.79 82.86, 127.28 2.3 M0.6 145.86 C38.85 99.89, 79.5 53.94, 127.78 0.77 M1.65 154.11 C34.76 111.92, 72.08 70.76, 130.97 0.84 M-0.04 152.16 C36.02 111.63, 70.08 70.59, 132.47 -0.58 M1.19 159.51 C50.3 103.45, 97.61 47.32, 138.89 0.7 M0.11 158.79 C31.11 121.58, 64.47 85.03, 136.83 -0.12 M-1.18 162.79 C57.75 98.45, 116.12 35.97, 142.3 0.62 M0.97 164.62 C54.23 103.51, 106.89 43.36, 144.05 -0.54 M0.08 170.35 C37.56 126.33, 76.48 84.52, 147.61 1.93 M-0.45 170.12 C54.72 109.79, 110.38 46.21, 148.74 -0.16 M1.38 175.82 C42.49 127.55, 88.08 77.49, 154.14 0.74 M0.55 176.8 C32.27 138.4, 66.79 99.73, 154.43 -0.41 M-0.35 181.86 C48.17 129.48, 95.15 73.93, 158.57 0.8 M0.78 183.32 C37.79 139.24, 77.58 93.61, 158.72 -0.2 M-0.81 187.92 C49.34 131.3, 98.35 76.54, 164.34 -0.94 M-0.13 190.04 C41.54 142.62, 81.59 96.23, 163.72 0.1 M0.3 194.23 C44.56 144.37, 89.05 92.78, 168.73 1.64 M-0.05 194.96 C60.2 122.93, 121.88 50.83, 169.85 0.9 M-0.03 200.91 C47.43 148.1, 91.72 97.08, 175.46 -0.01 M-0.55 202 C35.61 159.69, 72.01 116.41, 174.74 -0.47 M0.47 207.55 C41.82 161.66, 83.96 112.87, 179 -0.35 M1.05 206.54 C55.75 142.05, 113.32 75.94, 180.1 0.48 M-0.06 213.04 C59.41 145.22, 120.44 75.88, 186.34 -0.36 M-0.59 213.67 C56.89 150.43, 112.09 85.94, 185.73 0.25 M0.87 221.07 C48.64 162.19, 99.44 102.42, 192.12 -1.18 M-0.26 219.24 C52.35 159.47, 105.36 98.97, 189.94 -0.57 M1.23 224.25 C59.48 157.49, 116.97 88.83, 197.17 0.47 M-0.33 225.52 C44.58 173.19, 89.42 120.77, 196.2 -0.22 M-0.64 231.9 C68.16 155.54, 134.99 78.57, 202.2 0.38 M-0.47 231.75 C56.3 167.06, 110.39 104.38, 201.18 -0.52 M0.43 238.01 C71.29 157.32, 139.43 78.74, 207.82 0.26 M0.13 237.43 C74.37 153.41, 147.5 69.86, 207.49 -0.67 M0.36 243.74 C43.23 194.89, 85.88 143.87, 211.55 -0.96 M0.57 244.18 C72.08 160.34, 144.15 76.85, 211.87 -0.44 M1.73 245.3 C51.17 191.66, 98.92 135.66, 216.51 -0.23 M2.59 246.48 C77.28 163.11, 150.01 79.39, 217.63 -0.13 M9.2 247.34 C77.6 167.57, 147.96 85.53, 222.55 -1.12 M8.4 246.76 C87.53 155.2, 169.2 62.06, 222.99 -0.44 M14.84 246.08 C79.3 169.28, 145.18 91.16, 229.47 1 M14.23 246.25 C78.21 171.99, 143.72 97.14, 227.85 0.08 M17.99 247.17 C93.43 160.74, 166.33 75.92, 233.81 0.24 M18.59 246.72 C75.82 179.29, 135.53 111.62, 233.37 -0.35 M24.43 246.26 C104.68 152.62, 185.98 61.17, 239.54 1.08 M24.27 247.02 C81.89 178.38, 140.87 109.48, 238.3 0.72 M28.02 247.4 C77.88 189.75, 126.67 136.46, 244.39 -1.35 M28.93 246.76 C112.96 151.89, 197.13 54.91, 243.21 -0.53 M34.47 246.09 C114.32 156.59, 191.58 65.85, 249.53 -1.03 M35.25 246.76 C105.25 167.06, 175.22 87.63, 248.62 0.8 M40.22 247.71 C99.82 177.13, 162.02 106.41, 255.14 -0.11 M40.15 247.11 C96.34 178.65, 154.82 111.48, 254.72 0.26 M45.2 245.05 C97.13 188.05, 149.33 125.6, 258.62 1.35 M46.25 246.38 C97.88 186.13, 150.28 125.36, 258.91 0.08 M51.05 247.75 C131.31 151.44, 214.81 57.61, 264.56 -0.66 M51.2 246.47 C123.68 160.96, 196.85 77.1, 264.56 0 M57.28 246.03 C129.16 163.69, 202.99 81.94, 269.15 -1.1 M56.31 246.33 C112.53 181.34, 168.64 115.38, 270.21 0.87 M62.25 245.7 C135.48 163.67, 207.19 79.36, 275.69 -0.12 M61.38 246.86 C104.18 196.02, 147.95 146.19, 275.58 -0.36 M67.64 245.62 C114.4 193.3, 157.82 140.92, 281.12 2.33 M66.5 245.9 C138.35 162.7, 210.91 80.4, 279.79 0.59 M71.1 247.98 C132.7 178.55, 191.73 108.74, 279.92 7.07 M72.36 245.99 C142.47 166.15, 211.69 85.37, 279.9 7.2 M76.31 246.59 C154.56 154.21, 232.54 63.68, 280.21 14.16 M77.88 246.64 C127.84 187.53, 178.22 129.35, 280.84 12.52 M82.97 245.61 C150.98 167.26, 218.89 88.01, 279.57 20.75 M81.91 246.32 C123.13 201.32, 163.25 155.02, 279.44 18.94 M87.43 246.06 C128.44 199.42, 169.13 154.35, 279.87 26.68 M87.3 246.85 C149.47 178.19, 209.16 108.19, 280.37 25.98 M93.1 246.5 C154.65 173.99, 219.57 100.56, 278.65 31.24 M93.14 245.93 C159.03 170.74, 224.22 96.15, 280.3 32.01 M99.05 248.27 C171.53 164.15, 243.29 78.1, 279.82 36.93 M97.8 246.31 C145.93 189.29, 196.95 131.73, 279.09 38.41 M105.11 245.51 C153.79 191.98, 202.91 133.94, 279.31 44.33 M103.71 246.41 C156.34 187.05, 208.41 127.64, 279.43 43.87 M108.82 246.93 C159.98 190.43, 210.88 131.05, 278.82 50.3 M108.26 247.46 C144.4 207, 179.98 166.42, 280 49.23 M114.7 246.41 C159.24 195.4, 203.58 141.7, 280.55 55.15 M113.73 246.15 C154.86 201.35, 194.06 156.02, 279.16 56.64 M118.62 247.93 C180.86 175.95, 241.41 102.95, 279.21 60.49 M119.78 246.72 C154.01 207.95, 187.38 169.14, 279.42 62.51 M123.36 245.05 C160.21 206.52, 193.59 166.17, 278.75 68.3 M125.38 245.65 C183.08 181.22, 239.67 116.13, 279.96 68.98 M129.42 246.86 C161.44 207.08, 193.99 169.64, 281.57 73.84 M129.29 247.05 C179.67 189.86, 227.4 133.76, 279.47 74.17 M134.16 247.03 C183.64 191.9, 232.93 133.29, 278.59 81.84 M135.49 247.05 C183.91 192.11, 232.97 135.06, 280.16 81.2 M139.27 246.5 C178.92 202.64, 220.23 157.84, 278.52 85.92 M140.31 245.96 C170.28 211.45, 200.39 178.57, 278.83 86.34 M146.64 246.06 C173.44 214.08, 200 183.67, 281.27 91.73 M146.2 246.34 C197.45 187.24, 248.62 127.49, 279.49 93.06 M152.06 245.26 C188.68 201.21, 229.88 158.58, 279.7 100.31 M150.36 246.26 C184.85 208.72, 218.17 169.02, 279.29 98.88 M158.14 246.01 C193.82 203.54, 236.03 157.49, 281.41 105.41 M157.67 246.15 C188.06 212.58, 217.87 178.02, 279.35 103.61 M161.14 246.52 C201.96 197.33, 243.59 150.73, 278.47 109.62 M162.59 246.96 C196.76 207.66, 232.58 167.63, 279.48 111.07 M168.74 245.52 C207.97 200.08, 247.86 153.26, 278.07 115.37 M168.4 246.47 C212.22 194.6, 257.91 143.06, 280 116.82 M173.79 248.35 C209.13 203.08, 247.59 156.52, 281.59 121.22 M173.03 246.84 C202.34 212.35, 230.13 179.09, 279.78 122.98 M176.5 246.91 C211.29 208.9, 243.15 172.07, 281.65 128.17 M178.31 246.99 C200.52 218.57, 226.43 191.47, 279.28 129.93 M182.09 245.81 C222.53 205.2, 256.27 163.69, 279.55 136.47 M183.74 246.13 C217.01 204.55, 254.13 164.22, 281.16 135.54 M187.04 246.4 C219.96 208.49, 253.38 170.58, 279.03 139.66 M187.81 246.18 C217.39 212.61, 247.74 178.19, 280.09 140.63 M192.71 244.85 C224.17 212.73, 250.28 180.17, 279.78 149.41 M193.72 247.32 C218.77 216.37, 245.43 188.5, 279.36 148.21 M199.58 248.17 C229.87 213.02, 258.94 180.67, 278.37 153.8 M198.74 246.33 C222.05 220.16, 242.88 194.23, 279.95 153.15 M204.91 248.32 C226.39 224.42, 245.08 200.78, 279.27 161.71 M203.92 246.21 C234.86 211.4, 264.15 177.78, 280.58 158.99 M208.28 247.01 C236.91 216.81, 264.6 183.1, 278.38 165.5 M208.75 247.27 C232.61 220.26, 257.37 192.24, 279.33 166.04 M216.55 245.99 C233.33 225.09, 256.75 201.67, 278.66 173.21 M214.23 246.92 C237.25 221.27, 257.99 195.88, 280.46 171.96 M218.84 247.39 C231.09 232.64, 244.19 217.45, 277.73 179.29 M220.91 246.36 C244.65 220.35, 266.5 193.26, 279.99 177.89 M226.07 244.52 C241.43 227.52, 256.71 210.53, 278.8 184.92 M226.53 246.82 C238.1 232.14, 249.82 218.58, 279.79 183.21 M230.61 245.93 C250.91 225.33, 267.71 204.07, 279.65 188.37 M230.78 246.02 C246.13 229, 262.05 210.72, 280.62 189.3 M234.51 245.48 C249.3 232.7, 260.77 218.51, 282.16 197.74 M235.62 245.63 C247.82 231.94, 261.74 218.21, 280.78 196.66 M241.17 246.41 C252.25 232.81, 268.3 216.71, 278 201.09 M242.01 247.73 C251.4 235.01, 262.75 221.43, 279.89 202.47 M247.52 247.37 C256.25 232.7, 268.48 221.66, 278.15 207.22 M246.26 246.32 C258.8 231.6, 270.97 218.29, 279.47 207.76 M251.71 246.52 C261.2 233.2, 272.03 223.8, 281.88 215.97 M252.72 247.74 C258.3 240.15, 263.7 232.19, 280.07 215.13 M257.32 247.56 C267.14 237.55, 273.43 226.2, 279.73 222.58 M258.17 246.18 C265.04 239.69, 270.98 230.64, 279.28 221.5 M261.01 247.83 C269.59 239.44, 275.83 233.79, 281 224.44 M262.49 246.12 C268.11 239.88, 274.55 233.25, 279.4 226.28 M268.67 248.15 C271.13 240.96, 276.5 237.79, 281.33 233.15 M268.93 245.85 C271.46 242.86, 274.9 238.43, 280.14 232 M272.28 246.29 C275.82 245.42, 276.07 241.89, 279.34 238.36 M273.23 246.21 C274.58 244.66, 276.64 243.55, 280.05 239.59" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M-0.29 -0.56 C86.45 1.82, 172.55 -0.1, 277.7 -0.76 M-0.01 -0.1 C98.23 -1.12, 196.64 -1.51, 279.15 0.69 M278.52 0.05 C281 71.39, 281.69 141.37, 278.26 242.57 M278.86 -0.28 C278.03 88.08, 278.49 177.58, 279.48 243.78 M277.51 243.91 C177.6 244.06, 78.96 243.32, 0.12 242.52 M279.36 244.25 C195.56 242.27, 111.25 242.53, 0.25 244.26 M-0.23 244.14 C1.31 150.86, -0.4 55.49, 0.84 -0.23 M0.29 243.26 C-2.81 156.47, -2.58 70.08, 0.15 0.8" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(720.2756169637048 471.86093266805017) rotate(0 89 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunctionInstance</text></g><g stroke-linecap="round" transform="translate(722.2755559285486 495.1942456563314) rotate(0 129.66665649414062 105.16667175292969)"><path d="M-0.14 -0.57 C71.43 -0.22, 144.86 -2.21, 260.54 -0.81 M0.58 -0.14 C66.89 -0.59, 134.62 0.08, 259.74 0.29 M259.87 1.53 C261.42 41.92, 261.29 85.57, 261.06 209.48 M259.12 0.01 C258.71 67.62, 258.74 134.4, 259.6 210.37 M258.19 211.42 C178.42 208.62, 95.62 210.42, -1 209.63 M260.08 210.35 C204.28 209.84, 147.69 208.94, 0.16 210.74 M-1.16 210.02 C-1.91 168.44, -0.06 123.88, -0.55 0.43 M-0.7 210.44 C-1.19 151.61, -1.59 92.37, 0.21 -0.18" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(794.2756169637048 521.5275891621908) rotate(0 5 6.1666717529296875)"><path d="M5.31 -0.75 C6.95 3.24, 8.8 5.42, 10.59 6.39 M5.62 0.34 C7.03 1.54, 8.03 3.55, 10.28 7.34 M9.88 7.29 C9.38 8.02, 7.76 9.8, 6.45 11.75 M10.13 6.97 C8.59 8.98, 7.07 11.3, 6.12 12.27 M5.59 11.69 C4.16 10.25, 1.41 7.63, -0.36 6.38 M6.05 12.11 C4.57 11.26, 2.87 9.72, -0.28 6.83 M0.58 6.88 C1.42 4.56, 3.78 3.5, 6.56 0.39 M0.25 7.31 C1.23 5.7, 3.15 3.91, 5.69 0.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(826.9422429402673 518.8609326680502) rotate(0 47 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_import</text></g><g transform="translate(1179.608929951986 328.5274976094564) rotate(0 82 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunctionImport:</text></g><g stroke-linecap="round" transform="translate(1169.608929951986 347.1942456563314) rotate(0 88 100.16670227050781)"><path d="M1.27 0.11 C65.5 -1.65, 129.17 -1.53, 177.22 1.46 M-0.22 0.98 C48.88 0.62, 98.6 1.15, 176.96 0.69 M174.67 -1.44 C176.48 63.54, 175.11 125.5, 175.9 199.48 M176.34 -0.6 C175.55 43.49, 176.78 86.4, 175.87 200.13 M175.86 201.23 C120.82 201.18, 65.86 199.36, -0.83 200.67 M175.83 200.68 C112.98 201.64, 50.62 200.61, -0.14 199.51 M0.56 201 C0.58 133.04, -0.08 64.01, 0.85 -1.63 M0.8 199.84 C-1.83 128.36, -2.24 55.58, 0.77 0.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(933.3889939005801 518.5988232952503) rotate(0 117.5490202437453 -84.86385017725433)"><path d="M-1.06 0.23 C25.2 -23.84, 118.26 -115.44, 157.4 -143.81 C196.55 -172.17, 221.09 -165.64, 233.81 -169.96 M0.58 -0.69 C26.69 -24.67, 117.16 -114.6, 156.42 -142.57 C195.68 -170.54, 223.34 -164.22, 236.16 -168.53" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(933.3889939005801 518.5988232952503) rotate(0 117.5490202437453 -84.86385017725433)"><path d="M210.09 -154.48 C216.29 -159.93, 225.21 -164.19, 236.92 -169.85 M210.57 -154.51 C215.01 -157.37, 220.82 -160.45, 236.09 -168.07" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(933.3889939005801 518.5988232952503) rotate(0 117.5490202437453 -84.86385017725433)"><path d="M207.18 -174.79 C214.32 -174.38, 224.09 -172.79, 236.92 -169.85 M207.65 -174.82 C212.87 -173.38, 219.3 -172.13, 236.09 -168.07" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(827.2756169637048 541.5276196797689) rotate(0 17 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func</text></g><g stroke-linecap="round" transform="translate(795.9422429402673 546.3609174092611) rotate(0 5 6.1666717529296875)"><path d="M6.36 0.26 C6.92 3.37, 8.65 5.87, 10.13 6.45 M6.19 -0.01 C6.54 1.72, 7.9 2.65, 9.91 7.37 M10.22 6.43 C8.6 8.99, 7.17 10.27, 5.76 11.72 M9.85 6.75 C8.62 8.76, 7.8 9.64, 6.28 12.58 M6.68 12.85 C3.75 9.81, 1.15 8.64, -0.56 7.51 M5.71 11.96 C4.21 10.88, 2.06 9.04, -0.39 7.4 M0.16 6.63 C2.82 5.64, 4.21 2.15, 5.93 -0.91 M-0.4 6.81 C1.51 5.4, 2.08 4.61, 6.39 -0.02" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1331.9422429402673 716.1943066914877) rotate(0 105.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunction (per module)</text></g><g stroke-linecap="round" transform="translate(1333.2757390340173 745.6942914326986) rotate(0 112.66668701171875 100.49996948242188)"><path d="M1.35 -0.61 C74.79 2.5, 153.11 0.72, 223.8 1.51 M-0.22 0.09 C67.22 -1.55, 132 -1.01, 225.64 -0.76 M226.07 1.09 C223.84 77.91, 225.2 157.34, 226.99 200.14 M225.68 -0.44 C225.07 59.42, 225.43 119.02, 226.08 201.12 M225.7 199.75 C141.76 200.81, 56.83 201.04, -0.94 201.81 M225.9 200.55 C179.58 200.86, 132.62 200.93, -0.59 201.11 M-0.31 201.68 C0.65 154.78, -1.16 107.92, 1.48 -1.62 M0.68 200.91 C-1.41 126.76, -0.98 52.03, -0.12 0.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1697.9423650105798 859.860902150472) rotate(0 64.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">internal function</text></g><g stroke-linecap="round"><g transform="translate(865.642102355105 563.5563333692677) rotate(0 229.28624552502595 93.2191536104234)"><path d="M-0.76 -0.8 C29.97 8.78, 107.54 26.17, 184.23 57.51 C260.91 88.85, 413.49 165.75, 459.33 187.24 M1.04 1.39 C31.59 11.08, 106.75 27.83, 183.06 58.45 C259.38 89.07, 412.8 163.63, 458.94 185.12" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(865.642102355105 563.5563333692677) rotate(0 229.28624552502595 93.2191536104234)"><path d="M427.74 181.64 C435.74 184.49, 446.87 185.21, 458.31 186.6 M429.23 181.66 C439.92 182.82, 450.71 185.35, 458.02 184.16" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(865.642102355105 563.5563333692677) rotate(0 229.28624552502595 93.2191536104234)"><path d="M436.52 163.09 C442.01 171.19, 450.62 177.23, 458.31 186.6 M438.02 163.12 C445.42 170.94, 453.03 180.18, 458.02 184.16" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(772.2756169637048 507.5275891621908) rotate(0 93.00003051757812 32.5)"><path d="M16.25 0 M16.25 0 C66.67 0.42, 120.72 1.29, 169.75 0 M16.25 0 C49.08 -1.36, 80.53 -0.65, 169.75 0 M169.75 0 C180.34 0.8, 187.63 6.29, 186 16.25 M169.75 0 C180.06 -0.06, 184.14 3.29, 186 16.25 M186 16.25 C185.26 21.71, 185.59 29.32, 186 48.75 M186 16.25 C184.91 26.86, 185.84 39.58, 186 48.75 M186 48.75 C185.86 60.99, 180.83 63.66, 169.75 65 M186 48.75 C185.74 60.9, 181.77 65.63, 169.75 65 M169.75 65 C129.87 64.95, 91.11 62.54, 16.25 65 M169.75 65 C121.2 64.58, 72.07 65.45, 16.25 65 M16.25 65 C3.69 65.05, 0.47 58.21, 0 48.75 M16.25 65 C3.3 66.36, 0.13 57.8, 0 48.75 M0 48.75 C-0.07 39.01, -0.39 23.77, 0 16.25 M0 48.75 C0.75 38.56, -0.35 28.35, 0 16.25 M0 16.25 C1.74 5.55, 3.55 -1.66, 16.25 0 M0 16.25 C1.26 3.46, 3.22 1.46, 16.25 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1173.608929951986 352.8608716328939) rotate(0 79.33334350585938 22.66668701171875)"><path d="M-0.18 1.75 C34.95 -1.06, 69.85 1.15, 158.8 -1.86 M-0.95 0.63 C34.56 1.69, 68.23 2.15, 159.31 0.1 M158.65 -0.34 C159.29 14.35, 159.98 30.86, 157.11 45.26 M159.33 -0.84 C158.62 14.13, 159.15 28.3, 158.69 45.25 M159.36 45.16 C97.89 47.38, 33.97 45.51, -0.33 46.22 M159.42 45.98 C125.19 46.58, 90.16 47.16, -0.91 45.12 M2 45.25 C0.3 31, -2.07 17.07, -1.12 1.92 M0.6 44.73 C-1.05 31.44, -0.65 17.31, -0.01 -0.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1146.608929951986 355.1942151387533) rotate(0 93.5 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> char *module_name;</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> char *field_name;</text></g><g stroke-linecap="round" transform="translate(1175.608929951986 420.52755864461267) rotate(0 77.66668701171875 17.833328247070312)"><path d="M1.29 -0.43 C41 1.83, 81.83 -0.24, 155.42 0.67 M-0.43 0.39 C38.21 1.57, 75.33 0.62, 155.37 0.87 M157.31 0.99 C154.73 9.7, 154.83 19.88, 154.27 36.92 M155.57 0.86 C154.61 9.97, 154.67 17.66, 154.52 35.99 M155.18 35.91 C124.67 33.69, 91.62 34.21, -1.19 36.37 M154.63 35.72 C100.53 34.53, 46.18 35.18, 0.11 35.44 M-0.76 34.1 C-1.51 22.27, 1.3 9.01, 0.25 1.61 M-0.54 34.77 C-1.33 23.36, -0.99 13.41, -0.98 -0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1199.6088689168298 429.52755864461267) rotate(0 62.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_ptr_linked</text></g><g stroke-linecap="round" transform="translate(1166.9423039754236 118.52752812703454) rotate(0 77.66665649414062 45.16667175292969)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.07 6.34 C2 4.62, 3.62 2.22, 4.32 0.71 M-0.05 6.26 C1.07 4.6, 2.6 3.01, 4.94 0.14 M0.2 11.73 C2.48 9.17, 7.43 5.34, 11.26 0.69 M-0.55 12.31 C3.23 8, 7.7 2.98, 9.9 -0.36 M-1.84 19.54 C5.64 13.41, 10.56 5.83, 16.44 -1.11 M-0.97 18.03 C3.47 14.15, 6.95 8.88, 16.13 -0.53 M1.83 25.37 C7.67 17.32, 12.37 10.28, 22.36 0.25 M-0.51 23.69 C4.93 17.88, 10.1 13.09, 21.58 -0.16 M-0.78 32.46 C11.86 19.11, 21.61 6.4, 26.92 0.31 M-0.81 30.01 C7.55 21.01, 16.99 11.86, 25.34 -0.3 M0.66 37.31 C7.68 28.42, 16.41 19.72, 32.33 1.3 M-0.92 37.07 C7.08 27.25, 16.96 16.25, 31.04 -0.54 M-1.67 42.28 C11.42 30.55, 21.98 20.15, 37.55 0.87 M-0.18 43.34 C14.27 27.59, 26.68 10.69, 36.61 -0.25 M1.81 48.38 C11 39.75, 18.75 30.08, 41 0.53 M-0.98 48.78 C13.13 32.41, 27.84 15.61, 42.81 0.12 M0.16 56.51 C15.12 39.01, 28.73 24.9, 48.86 2.21 M1.12 54.22 C10.45 42.95, 19.2 32.76, 47.21 -0.21 M-1.83 59.97 C19.21 38.8, 34.92 19.81, 53.79 0.7 M-0.6 60.22 C13.71 45.19, 26.15 30.53, 52.71 0.41 M-1.54 65.69 C23.42 43.58, 42.28 17.58, 59.17 0.23 M-0.23 66.49 C14.35 52.79, 26.86 35.95, 57.52 0.82 M1.02 74.97 C13.67 55.94, 28.98 37.57, 61.87 -1.15 M0.1 72.92 C18.45 50.69, 38.88 29.74, 63.68 -0.22 M-1.28 80.31 C13.08 63.22, 28.81 44.96, 68.5 1.07 M-0.49 78.6 C15.17 62.07, 30.59 44.35, 69.05 0.74 M-0.58 86.54 C16.31 67.08, 33.85 43.81, 74.15 -1.76 M0.14 85.28 C21.09 61.62, 41.25 39.26, 73.8 0.57 M-1.14 90.65 C30.9 57.04, 59.21 26.42, 78.64 1.13 M-0.08 91.39 C28.42 57.73, 57.11 26.28, 78.43 0.33 M5.4 92.01 C31.98 61.92, 60.73 27.33, 85.3 0.39 M4.91 90.52 C22.95 71.19, 39.94 51.71, 84.26 0 M11.73 90.67 C33.61 60.97, 58.02 33.9, 89.15 -0.94 M10.88 89.99 C39.88 58.46, 69.46 25.89, 89.42 -0.77 M15.51 89.05 C40.65 59.76, 64.09 33.96, 95.74 1.07 M15.65 90.79 C39.56 62.32, 62.75 36.85, 95.38 0.13 M20.9 90.45 C41.43 65.68, 62.03 44.78, 101.32 -0.25 M22.37 90.31 C40.98 68.78, 58.53 48.95, 100.92 -0.03 M26.78 91.58 C43.91 72.69, 61.93 52.5, 107.64 -1.7 M27.51 91.15 C53.82 59.78, 80.94 27.8, 106.62 -0.06 M33.54 91.01 C59.01 62.2, 83.46 31.22, 110.18 -1.67 M33.35 89.81 C51.52 67.25, 72.12 43.68, 110.92 -0.07 M39.28 89.75 C68.86 55.66, 101.05 19.84, 116.26 1.1 M37.99 91.5 C60.93 64.02, 85.42 37.2, 115.89 0.01 M42.58 91.63 C68.97 57.83, 97.86 27.63, 120.54 0.22 M43.87 90.83 C76.25 52.91, 106.37 17.08, 122.57 -0.6 M46.77 91.94 C73.95 60.28, 101.97 25.61, 128.58 -1.52 M47.74 90.61 C76.12 57.58, 104.49 24.87, 126.2 -0.46 M54.67 89.82 C69.94 69.36, 89.62 47.75, 130.92 1.04 M53.15 90.56 C79.97 61.32, 104.88 32.92, 132.12 -0.48 M56.82 92.82 C79.74 65.8, 103.07 38.94, 139.36 -0.03 M58.5 90.12 C76.7 69.52, 95.49 48.44, 137.72 0.87 M66.25 89.35 C83.52 65.02, 106.74 44.48, 141.64 -1.3 M63.5 91.11 C93.36 56.35, 121.24 23.1, 142.96 0.3 M70.71 89.26 C93.37 66.18, 114.57 39.48, 149.77 0.59 M69.18 90.56 C94.67 60.29, 120.75 32.39, 148.38 0.46 M75.47 92.24 C106.02 58.07, 137.29 21.74, 154.73 1.35 M74.37 91.42 C104.26 57.23, 133.89 23.22, 153.6 0.65 M79.49 92.42 C107.58 56.4, 140.85 20.37, 157.42 3.11 M79.76 91.33 C102.01 64.93, 124.17 40.73, 157.96 1.15 M85.59 91.52 C105.15 70.38, 128.23 44.23, 158.76 7.67 M85.68 92.09 C103.75 70.51, 121.68 48.22, 156.45 8.64 M91.94 91.69 C113.19 67.22, 132.1 42.52, 159.09 12.12 M91.4 90.69 C110.15 68.93, 131.42 44.14, 156.78 14.2 M95.61 92.2 C117.96 67.9, 137.61 42.36, 159.22 21.78 M96.43 90.31 C110.08 74.84, 124.18 59.81, 158.21 20.38 M102.62 90.71 C120.89 68.43, 135.53 49.92, 158.4 26.81 M100.34 89.79 C113.84 78.35, 126.06 63.89, 157.34 26.14 M108.27 91.79 C118.01 74.16, 130.74 60.75, 158.67 30.8 M106.79 90.42 C124.23 68.32, 143.66 47.23, 158.06 31.64 M111.81 91.38 C127.21 70.89, 141.82 53.93, 158.86 39.96 M111.98 90.66 C129.06 72.76, 144.31 53.5, 157.43 37.68 M116.75 89.32 C126.05 80.49, 136.05 67.08, 158.17 43.89 M116.71 90.89 C129.42 76.51, 140.34 63.48, 156.98 44.79 M121.56 89.84 C133.32 79.63, 141.71 68.76, 155.69 52.33 M122.83 90.18 C135.52 75.92, 149.3 61.37, 157.95 50.15 M127.97 90.06 C136.75 84.53, 142.06 75.86, 155.85 57.18 M127.26 91.04 C135.81 83.97, 141.44 74.73, 156.48 57.87 M131.66 92.49 C140.05 84.01, 146.07 74.66, 155.91 61.2 M132.51 90.14 C142.37 80.88, 150.75 69.96, 156.92 62 M138.58 89.53 C143.92 84.07, 150.23 79.09, 157.56 70.82 M138.64 91.09 C146.21 82.79, 153.62 73.9, 157.11 69.52 M143.65 91.97 C148.98 88.14, 151.07 83.72, 156.94 73.33 M143.79 91.17 C148.18 85.07, 153.57 79.26, 158.18 73.82 M147.66 90.01 C150.69 87.07, 152.75 85.47, 157.09 81.34 M148.41 90.41 C152 87, 154.84 83.14, 156.87 81.38 M154.15 90.69 C154.77 89.96, 156.04 89.11, 157.14 87.33 M154.49 90.61 C154.97 89.79, 155.51 89.3, 157.29 87.6" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-0.83 1.28 C61.9 -1.8, 122.94 1.45, 154.96 1.18 M-0.25 -0.16 C36.35 -0.33, 73.14 -0.46, 156.29 0.69 M154.69 -1.6 C156.84 36, 155.7 69.3, 154.3 88.7 M156.17 0.84 C155.74 35.22, 154.55 70.09, 154.79 91.33 M155.63 88.71 C101.58 90.27, 48.59 88.63, -0.65 90.56 M155.57 89.37 C102.27 89.1, 46.97 89.85, 0.29 90.84 M0.65 89.54 C-0.66 67.26, 2.52 48.88, 0.14 1.76 M-0.63 89.59 C1.27 62.13, 1.36 32.74, 0.15 -0.1" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1173.6089909871423 126.86087163289392) rotate(0 61.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">native function:</text></g><g stroke-linecap="round"><g transform="translate(1182.7423860343185 433.8608716328939) rotate(0 -61.36229210598776 -153.9228490938421)"><path d="M-0.94 -1.01 C-21.2 -32.85, -119.89 -140.05, -122.28 -191.03 C-124.66 -242.01, -32.81 -287.54, -15.25 -306.92 M0.77 1.07 C-19.63 -30.54, -120.68 -137.76, -123.43 -189.42 C-126.18 -241.08, -33.42 -289.48, -15.72 -308.92" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1182.7423860343185 433.8608716328939) rotate(0 -61.36229210598776 -153.9228490938421)"><path d="M-33.34 -284.15 C-27.57 -288.58, -22.85 -297.5, -15.26 -310.84 M-30.69 -283.2 C-25.21 -293.59, -20.62 -301.69, -15.4 -309.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1182.7423860343185 433.8608716328939) rotate(0 -61.36229210598776 -153.9228490938421)"><path d="M-45.95 -300.33 C-37.14 -300.76, -29.38 -305.77, -15.26 -310.84 M-43.31 -299.39 C-33.05 -303.61, -23.73 -305.62, -15.4 -309.31" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1173.7755254109704 465.1942151387533) rotate(0 82.58338928222656 36.8333740234375)"><path d="M1.07 1.11 C34.85 1.06, 67.49 1.02, 165.01 1.72 M-0.33 0.58 C63.01 -0.11, 127.81 1.04, 165.84 -0.48 M165.36 0.42 C166.48 18.16, 165.41 37.52, 165.85 72.66 M165.76 0.36 C165.77 28.91, 164.51 58.48, 165.2 73.7 M163.85 73.93 C108.49 74.54, 54.81 71.97, 0.04 72.85 M164.62 74.2 C102.51 73.77, 39.12 73.8, 0.53 74.57 M-1.26 74.06 C1.28 54.74, -1.19 38.01, 1.62 -1.19 M-0.17 74.64 C-0.08 48.87, 1.04 22.1, -0.63 -0.75" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1188.9422429402673 475.5276196797689) rotate(0 76 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">import_module;</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">import_func_linked;</text></g><g stroke-linecap="round"><g transform="translate(1173.072430669456 508.52302623209096) rotate(0 33.584429830642534 119.16617001496195)"><path d="M0.04 0.75 C-14.6 15.42, -114.6 49, -87.91 88.43 C-61.22 127.87, 118.85 212.23, 160.15 237.35 M-1.4 0.09 C-16.12 14.95, -115.26 50.33, -88.39 90.02 C-61.52 129.71, 118.33 213.73, 159.81 238.24" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1173.072430669456 508.52302623209096) rotate(0 33.584429830642534 119.16617001496195)"><path d="M131.34 235.62 C138.98 236.67, 146.18 237.5, 161.43 236.52 M129.99 233.65 C140.48 235.93, 151.73 237.35, 159.67 237.74" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1173.072430669456 508.52302623209096) rotate(0 33.584429830642534 119.16617001496195)"><path d="M140.93 217.47 C145.81 223.85, 150.2 230, 161.43 236.52 M139.59 215.5 C146.66 224.3, 154.46 232.24, 159.67 237.74" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1070.323237464542 696.4323568798246) rotate(0 68.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(WASMFunction *)</text></g><g stroke-linecap="round" transform="translate(1346.9423650105798 763.1942761739095) rotate(0 8.666656494140625 7.8333282470703125)"><path d="M0.35 8.25 C0.35 8.25, 0.35 8.25, 0.35 8.25 M0.35 8.25 C0.35 8.25, 0.35 8.25, 0.35 8.25 M3.36 10.87 C4.88 10.13, 6.71 8.11, 10.58 2.57 M3.36 10.87 C5.31 8.86, 6.73 7.08, 10.58 2.57 M6.38 13.5 C9.52 11.71, 12.26 7.88, 14.26 4.44 M6.38 13.5 C8 11.57, 10.43 9.73, 14.26 4.44 M9.4 16.12 C11.68 13.58, 13.29 9.94, 16.62 7.82 M9.4 16.12 C11.12 13.72, 13.54 11.19, 16.62 7.82" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M11.25 2 M11.25 2 C13 2.95, 14.05 4.74, 15.08 6 M11.25 2 C12.13 3.02, 12.86 3.81, 15.08 6 M15.08 6 C17.86 6.71, 18.99 7.6, 15.08 10 M15.08 6 C17.28 5.79, 17.75 7.11, 15.08 10 M15.08 10 C13.34 11.07, 11.89 12.3, 11.25 13.67 M15.08 10 C13.32 11.43, 12 12.98, 11.25 13.67 M11.25 13.67 C9.55 17.38, 10.98 17.56, 6.75 13.67 M11.25 13.67 C7.13 13.62, 7.12 17.16, 6.75 13.67 M6.75 13.67 C4.99 12.5, 3.36 11.31, 2.25 10 M6.75 13.67 C5.78 12.95, 4.24 12.11, 2.25 10 M2.25 10 C0.39 9.21, 0.99 6.27, 2.25 6 M2.25 10 C1.82 8.6, -1.16 7.6, 2.25 6 M2.25 6 C3.48 5.52, 3.71 4.33, 6.75 2 M2.25 6 C3.51 5.25, 4.5 4.03, 6.75 2 M6.75 2 C8.99 -1.58, 10.71 -1.9, 11.25 2 M6.75 2 C10.34 1.21, 8.91 -0.57, 11.25 2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1378.9423650105798 763.5275891621908) rotate(0 18.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">code</text></g><g stroke-linecap="round" transform="translate(1686.942426045736 789.1942151387533) rotate(0 74.66668701171875 57.16670227050781)"><path d="M0.94 0.49 C44.12 1.78, 86.99 0.77, 149.21 -1.94 M0.82 0.13 C52.83 -0.18, 103.52 0.38, 149.13 -0.02 M150.24 -1.24 C150.8 21.83, 148.72 44.63, 148.37 116.23 M149.33 -0.22 C149.34 36.29, 149.85 73.03, 150.28 113.52 M150.53 113.24 C119.06 114.74, 86.77 114.73, 0.88 113.4 M149.95 113.61 C96.11 115.53, 41.67 115.83, -0.87 115.12 M-1.82 113.29 C1.28 77.91, 1.81 38.25, 0.05 -0.89 M0.87 114.13 C0.5 82.74, -0.51 52.01, -0.95 0.58" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1708.2757390340173 762.1941846211752) rotate(0 35 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">bytecode</text></g><g stroke-linecap="round"><g transform="translate(1421.6090215047204 775.1942456563314) rotate(0 133.2041164211479 35.44410214257459)"><path d="M-0.34 0.26 C24.7 3.92, 117.73 14.47, 149.57 22.69 C181.41 30.92, 171.29 41.44, 190.69 49.58 C210.09 57.72, 253.47 68.16, 265.97 71.53 M1.68 -0.65 C26.59 2.59, 117.12 12.8, 148.44 20.85 C179.77 28.9, 169.91 39.54, 189.63 47.63 C209.35 55.73, 254.25 65.71, 266.75 69.4" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1421.6090215047204 775.1942456563314) rotate(0 133.2041164211479 35.44410214257459)"><path d="M237.32 71.65 C245.07 70.69, 252.76 72.61, 268.09 70.64 M237.49 72.72 C242.78 72.32, 250.71 70.38, 266.57 68.49" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1421.6090215047204 775.1942456563314) rotate(0 133.2041164211479 35.44410214257459)"><path d="M242.49 51.79 C249.09 55.68, 255.52 62.48, 268.09 70.64 M242.66 52.87 C246.96 56.98, 253.7 59.56, 266.57 68.49" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1347.6090520222986 815.8609631856283) rotate(0 9.33331298828125 7.5)"><path d="M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M2.13 10.8 C6.33 7.24, 10.24 2.52, 11.97 0.13 M3.23 10.37 C5.52 7.55, 7.87 4.92, 11.69 1.04 M7.72 12.33 C8.23 10.06, 11.46 7.64, 13.67 4.05 M7 12.01 C8.27 10.05, 10.15 8.59, 14.01 4.54 M9.08 15.12 C11.61 14.42, 12.6 11.63, 16.56 6.63 M9.27 14.79 C11.06 13.52, 12.84 11.36, 17.5 6.6" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M10.78 -0.25 C12.84 2.07, 14.88 4.67, 19.45 9.08 M9.92 -0.17 C13.87 2.71, 16.51 6.55, 19.01 7.8 M18.16 8.35 C17.09 10.06, 15.14 11.94, 10.71 15.73 M19.18 8.12 C15.98 10.67, 12.91 12.77, 10.18 15.49 M8.9 16.03 C6.42 12.04, 4.02 9.74, 1.21 9.21 M9.89 14.93 C6.55 12.88, 3.48 10.88, 0.05 7.91 M-1.13 6.94 C2.7 7.45, 5.51 4.18, 10.51 -0.38 M-0.46 8.62 C1.96 5.66, 4.48 4.24, 9.6 -0.52" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1385.9423039754236 814.8609631856283) rotate(0 55 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">code_compiled</text></g><g stroke-linecap="round" transform="translate(1893.6090520222986 825.5277112325033) rotate(0 57.3333740234375 59.66667175292969)"><path d="M-0.9 1.61 C43.56 -1.35, 87.06 -2.31, 115.5 -0.88 M0.49 -0.56 C28.49 0.21, 56.73 0.58, 114.04 -0.04 M113.26 0.32 C116.25 43.97, 117.48 85.73, 115.28 118.33 M114.96 -0.35 C114.62 37.38, 114.15 75.35, 114.85 119.73 M116.49 119.09 C77.04 120.85, 42.59 121.2, -0.47 119.13 M115.18 118.5 C86.1 118.52, 57.98 119.57, 0.13 120.01 M-1.19 119.38 C1.62 96.74, 0.71 70.2, -0.71 -0.29 M-0.85 118.8 C0.26 93.99, 0.67 67.6, 0.98 -0.34" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1874.2757390340173 802.8610547383627) rotate(0 80.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">precompiled-bytecode</text></g><g stroke-linecap="round" transform="translate(1894.2757390340173 885.5277112325033) rotate(0 57.000030517578125 21.500015258789062)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.11 6.98 C2.46 4.71, 4.33 1.39, 4.85 0.62 M0.04 6.15 C1.38 3.95, 3.14 2.46, 5.03 0.29 M0.61 10.89 C1.42 7.6, 5.49 6.62, 10.68 0.35 M0.11 12.06 C4.62 6.61, 8.58 1.98, 10.46 -0.83 M0.48 18.74 C2.18 15.59, 6.73 9.34, 16.61 2.1 M0.6 17.79 C5.48 11.99, 8.86 6.41, 15.68 0.43 M1.03 22.52 C9.15 13.68, 18.1 7.16, 19.8 -1.73 M1.12 24.12 C4 17.9, 8.66 14.2, 21.76 -0.91 M-0.19 28.62 C7.52 22.84, 13.8 13.72, 26.94 0.13 M-0.37 29.92 C5.44 23.71, 11.89 18.04, 25.63 -0.06 M0.06 37.35 C9.41 26.08, 21.04 10.5, 32.66 -1.75 M0.72 37.2 C8.34 26.06, 16.49 17.34, 32.81 -0.9 M-1.6 43.4 C12.89 30.21, 20.78 18.03, 35.83 -0.89 M0.97 42.18 C13.61 26.56, 28.53 11.05, 37.4 0.66 M3.61 44.84 C15.78 31.73, 28.76 17.32, 42.31 1.55 M3.45 44.48 C16.88 29.02, 29.4 14.75, 42.56 -0.62 M6.18 46.17 C15.01 34.77, 22.96 27.95, 49.19 1.32 M9.02 46.43 C18.71 33.64, 28.87 23.25, 46.55 -0.56 M13.85 46.5 C25.77 33.97, 34.27 17.93, 51.54 -0.46 M13.64 45.52 C24.15 32.36, 34.67 21.32, 53.17 -0.8 M17.68 45.35 C31.86 28.6, 45.02 12.43, 58.68 -0.73 M18.16 46.46 C32.04 29.24, 45.9 15.23, 57.79 -0.02 M23.59 46.88 C31.36 33.51, 40.28 23.69, 64.9 -2.11 M23.63 45.59 C33.16 34.7, 41.35 25.35, 63.88 0.73 M27.83 44.62 C40.29 33.21, 47.35 22.35, 69.73 -0.27 M28.52 45.94 C39.17 35.01, 50.2 22.83, 68.94 0.86 M32.56 46.26 C48.67 30.17, 63.23 15.23, 72.68 0.48 M34.05 46.25 C45.05 33.26, 55.79 21.62, 75.08 -1.04 M39.91 46.87 C51.01 32.52, 63.3 22.54, 77.5 -0.27 M40 44.4 C50.98 33.03, 61.75 20.32, 78.94 -0.45 M44.26 45.41 C55.11 31.24, 65.89 22.48, 86.93 1.45 M44.7 46.23 C58.27 30.66, 71.67 14.94, 84.28 -0.18 M50.97 45.23 C64.88 29.56, 81.21 11.06, 90.92 -1.47 M51.58 46.23 C64.67 27.96, 80.54 10.71, 89.88 0.38 M56.63 46.59 C72.6 26.88, 87.84 9.69, 97.43 1.21 M55.14 46.36 C65.14 35.5, 73.79 25.44, 96.11 0.05 M59.8 47.11 C76.69 28.26, 91.88 10.79, 100.64 1.65 M61.43 44.71 C69.56 34.03, 80.37 22.73, 100.93 0.56 M65.32 46.33 C83.63 29.49, 97.74 10.96, 107.73 -1.61 M66.07 46.34 C76.83 35.23, 85.38 23.71, 106.35 -0.68 M70.95 46.16 C78.98 35.71, 88.32 26.7, 111.1 0.87 M72.78 45.97 C80.66 35.2, 87.8 27.7, 110.44 0.17 M75.75 47.4 C88.24 33.72, 97.93 20.68, 113.81 -0.6 M77.32 44.76 C85.27 36.17, 93.58 27.08, 116.55 1.65 M82.71 46.25 C92.43 32.95, 105.5 17.17, 113.88 5.74 M82.03 45.04 C93.28 34.47, 103.35 22.5, 115.28 7.72 M87.09 46.81 C98.45 34.26, 108.58 21.95, 114.85 12.44 M87.83 45.08 C93.46 39.77, 98.9 32.27, 114.85 13.49 M95.12 45.55 C99.38 35.63, 108.24 27.81, 115.55 21.52 M92.69 45.81 C99.08 37.89, 106.83 29.45, 114.65 20.02 M96.26 43.84 C103.12 39.62, 107.78 37.48, 116.15 25.1 M97.67 45.63 C105.01 38.83, 110.98 30.35, 114.93 25.31 M102.16 44.51 C106.92 41.21, 112.01 36.68, 113.89 30.34 M103.43 45.08 C107.61 41.13, 112.78 35.14, 116.12 31.29 M109.37 44.78 C111.67 44.16, 112.8 40.63, 114.47 38.76 M108.42 45.59 C110.48 44.06, 111.32 42.28, 115.85 38.37" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-0.92 -0.47 C41.15 -2.34, 86.89 -1.79, 112.95 -1.8 M0.12 0.1 C33.14 1.12, 65.69 0.59, 114.65 0.98 M114.41 0.47 C115.35 15.87, 114.31 33.3, 114.25 43.38 M113.73 0.07 C113.38 14.93, 114.31 28.77, 114.15 42.59 M112.55 43.51 C70.1 43.72, 25.16 42.66, -1.06 44.93 M113.74 42.32 C81.12 42.43, 48.54 42.73, -0.94 42.12 M0.58 44.98 C-0.09 27.23, -0.45 11.12, -1.69 -1.31 M-0.52 43.38 C0.25 30.52, 1.35 18.28, 0.21 -0.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1373.608899434408 853.8610547383627) rotate(0 87.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">fast_jit_jitted_code</text></g><g stroke-linecap="round" transform="translate(1343.608929951986 858.3609631856283) rotate(0 9.33331298828125 7.5)"><path d="M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M2.74 10.9 C5.18 7.18, 8.75 2.66, 11.66 0.28 M3.46 10.38 C6.28 7.29, 8.64 3.45, 11.89 0.85 M7.22 13.56 C9.98 9.49, 11.68 6.52, 13.74 3.59 M6.37 12.11 C8.63 9.3, 11.34 7.35, 14.04 4.28 M9.9 14.06 C12.12 11.62, 14.3 10.26, 16.77 6.83 M9.9 15.56 C11.35 13.35, 12.95 10.78, 17.09 6.38" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M9.71 -1.15 C11.71 1.76, 15.92 5.09, 18.9 7.67 M9.57 0.41 C12.89 2.95, 16.9 6.3, 19.04 7.62 M19.77 7.23 C14.97 10.82, 11.28 13.78, 9.02 15.16 M18.6 7.61 C16.93 8.95, 15.29 10.56, 10.12 14.48 M9.32 14.07 C8.17 12.29, 5.33 11.81, -0.34 8.93 M9.73 15.08 C5.91 11.87, 2.42 10.04, -0.03 8.5 M-0.66 7.59 C2.55 4.34, 5.69 3.82, 9.52 0.41 M-0.39 7.55 C1.78 5.55, 5.21 3.9, 10 0.34" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1344.608929951986 903.6943066914877) rotate(0 9.33331298828125 7.5)"><path d="M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M0.02 7.97 C0.02 7.97, 0.02 7.97, 0.02 7.97 M3.35 9.59 C5.01 7.97, 5.88 6.4, 11.07 1.44 M2.83 10.83 C5.61 7.35, 7.64 5.26, 11.64 1.36 M7.81 12.89 C8.79 9.65, 10.87 8.04, 13.36 4.37 M6.36 11.99 C7.67 10.75, 9.84 9.22, 14.05 4.1 M8.71 15.4 C10.92 12.89, 14.21 9.7, 17 6.12 M10.2 14.99 C12.24 12.23, 13.92 10, 16.55 7.09" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M8.85 -1.17 C11.84 2.78, 15.32 5.39, 18.34 8.82 M10.41 -0.27 C12.03 2.56, 14.54 4.34, 18.29 8.39 M17.9 7.49 C16.35 9.13, 14.16 11.26, 10.16 13.9 M18.28 8.07 C16.46 9.58, 14.9 10.95, 9.48 14.56 M9.07 15.43 C5.11 12.2, 2.54 9.5, 0.93 9.02 M10.08 14.72 C6.84 13.23, 5.13 11.33, 0.5 8 M-0.41 7.55 C1.76 5.32, 6.66 2.74, 10.41 -0.77 M-0.45 7.43 C3.05 5.66, 6.9 2.31, 10.34 -0.17" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1377.608929951986 899.1943372090658) rotate(0 71.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">llvm_jit_func_ptr</text></g><g transform="translate(1814.1090215047204 974.860886891683) rotate(0 71 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">fast jitted coode</text></g><g stroke-linecap="round" transform="translate(1836.7755254109704 1013.5275128682455) rotate(0 51.66668701171875 14.600000000000023)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.38 6.41 C0.72 5.35, 2.13 2.37, 5.12 -0.05 M-0.31 6.2 C1.03 5.05, 2.21 3.13, 4.66 0.07 M-0.26 11.23 C3.32 8.51, 4.19 4.82, 11.66 0.34 M0.31 12.27 C4.38 8.53, 7.75 3.6, 11.08 -0.23 M1.26 19.28 C4.62 15.95, 6.2 11.59, 14.18 0.24 M-0.33 19.13 C3.34 14.08, 7.5 11.29, 15.07 1.17 M-1.45 24.47 C7.73 16.51, 16.52 6.14, 21.39 -0.74 M0.73 23.51 C7.98 16.57, 13.54 9.72, 21.83 -0.77 M2.18 28 C8.43 24.96, 10.52 17.47, 25.05 0.39 M0.88 30.66 C8.12 20.48, 16.56 10.75, 25.8 1.1 M4.94 28.6 C15.84 22.36, 23.47 11.54, 30.72 0.36 M5.68 30.67 C16.45 17.68, 26.95 5.71, 31.6 -0.86 M10.52 31.69 C19.42 18.27, 29.99 6.21, 35.19 1.3 M11.81 29.63 C17.13 23.31, 22.04 17.42, 37.68 0.19 M15.09 29.99 C24 22.21, 33.04 14.17, 42.29 -1.84 M17.04 30.07 C22.55 23.13, 28.16 15.39, 42.27 0.76 M21.85 29.09 C31.34 19.96, 40.27 6.76, 48.12 -1.73 M22.91 30.18 C27.99 21.52, 35.75 13.43, 46.92 0.33 M26.26 30.95 C34.36 23.37, 43.53 15.1, 52.77 0.82 M26.27 29.13 C34.05 20.68, 42.45 12.16, 52.48 0.54 M31.81 29.37 C39.06 21.61, 43.51 17.46, 57.61 0.35 M33.3 30.26 C39.78 21.39, 48.44 12.96, 58.61 0.52 M39.23 29.53 C47.29 21.4, 51.74 11.31, 65.03 -1.74 M36.96 30.37 C43.64 24.44, 48.29 16.48, 63.77 0.06 M42.29 31.45 C52.45 19.01, 61.3 6.5, 67.68 -1.67 M43.03 28.94 C50.63 19.72, 58.77 11.36, 68.71 0.9 M49.01 29.53 C55.34 21.28, 63.65 12.6, 76.22 -1.84 M47.57 29.41 C55.89 21.44, 61.49 14.24, 74.52 0 M53.44 28 C58.21 21.19, 67.64 16.05, 80.6 0.74 M52.97 30.41 C64.38 18.85, 74 8.27, 80.05 0.74 M56.88 28.48 C67.86 22.89, 72.39 13.04, 85.75 -2.08 M59.42 29.02 C69.21 19.7, 78.18 7.02, 86 0.19 M63.65 29.42 C69.99 20.76, 75.29 15.85, 88.89 1.89 M64.91 30 C72.14 21.42, 79.3 12.04, 90.34 0.41 M70.35 29.68 C78.38 20.43, 89.55 10.38, 95.24 0.71 M68.73 29.08 C74.31 22.77, 81.2 16.57, 96.37 -0.41 M73.57 27.9 C83.42 21.4, 93.86 9.79, 99.32 1.82 M75.49 30.16 C84.51 18.34, 92.44 8.22, 100.16 -0.58 M79.19 30.17 C86.39 21.11, 96.07 13.24, 103.3 0.98 M80.58 30.61 C87.43 22, 94.5 13.39, 105.32 1.76 M86.09 29.36 C92.94 23.33, 98.49 12.39, 106.34 5.86 M86.23 28.46 C93.07 21.67, 101.1 12.86, 104.42 7.96 M91.42 28.74 C98.36 21.41, 101.56 16.43, 104.18 14.42 M90.93 29.73 C96.69 23.68, 100.09 18.61, 104.9 12.97 M95.05 29.43 C99.75 27.43, 99.87 25.65, 104.21 18.91 M95.81 29.53 C99.4 25.52, 102.39 23.02, 104.34 19.06 M101.32 29.82 C101.79 28.85, 103.22 28.55, 104.15 26.42 M101.14 29.76 C102.64 28.62, 103.55 27.29, 104.55 25.93" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-0.34 0.08 C19.98 0.28, 44.12 0.59, 105.03 -0.36 M0.25 -0.73 C37.33 -0.24, 73.07 0.94, 104.04 -0.91 M101.7 -1.62 C102.59 8.46, 105.06 21.01, 103.38 30.51 M103.6 -0.85 C103.28 10.09, 102.84 19.09, 102.46 29.15 M102.18 30.21 C72.98 28.44, 40.48 28.82, 0.84 29.87 M104.09 29.86 C75.59 30.18, 49.48 29.98, -0.79 29.36 M-0.42 29.14 C1.39 19.79, -1.74 6.82, 1.08 1.44 M-0.09 30 C0.99 17.59, -0.27 7.21, 0.27 0.49" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1850.608899434408 1076.1942609151206) rotate(0 66.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">llvm jitted coode</text></g><g stroke-linecap="round" transform="translate(1837.2755864461267 1102.1942609151206) rotate(0 75.33334350585938 21.500015258789062)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.16 5.77 C0.46 5.39, 1.16 3.34, 5.07 0.16 M-0.07 6.39 C1.2 5.5, 2.34 3.74, 5.19 0.28 M-1.28 11.69 C1.73 9.97, 4.64 4.03, 11.78 -1.17 M0.03 12.38 C3.47 7.43, 8.35 3.01, 10.7 -0.02 M1.14 17.89 C6.7 12.98, 13.4 5.86, 16.29 0.36 M-0.35 19.22 C3.37 13.6, 6.13 11.44, 14.85 -0.57 M1.04 25.82 C10.4 14.53, 15.59 4.88, 21.79 1.69 M1.2 23.67 C5.94 17.22, 10.62 11.61, 20.35 0.08 M-1.3 29.4 C7.2 19.96, 17.41 11.07, 27.75 0.27 M-0.21 30.11 C7.29 21.88, 14.72 14.59, 25.45 -0.07 M-1.33 38.72 C9.63 23.61, 22.18 11.95, 32.37 -1.32 M-1.04 35.97 C7.44 27.79, 16.99 17.76, 32.2 0.69 M1.85 43.76 C9.09 34.62, 18.32 25.61, 38.12 -0.12 M-0.58 43.39 C12.56 28.83, 23.61 16.25, 35.97 1.03 M1.37 46.31 C18.08 29.67, 28.13 17.73, 43.46 -1.32 M3.11 44.95 C17.03 27.76, 32.82 10.9, 43.42 -0.23 M9.12 46.08 C21.36 31.16, 32.02 17.65, 48.15 1.24 M8.04 45.44 C21.97 30.75, 35.71 14.13, 48.02 -0.77 M12.2 43.86 C20.64 37.16, 29.26 26.39, 52.95 0.59 M13 44.85 C23.98 35.59, 32.24 23.83, 54.03 0.39 M20.13 46.32 C30.61 28.65, 44.49 14.08, 56.88 0.14 M18.94 44.88 C29.22 34.18, 39.98 20.79, 58.04 0.19 M25.29 45.21 C34.55 33.54, 43.8 24.97, 64.98 1.1 M23.71 45.88 C33.62 35.2, 40.76 26.76, 62.93 0.74 M27.43 45.17 C43.11 32.22, 54.75 17.07, 69.56 2.11 M28.87 46.42 C41.41 30.49, 54.83 15.81, 69.38 0.64 M34.23 47.41 C42.03 34.57, 51.7 26.36, 73.95 -1.38 M34.41 46.77 C43.51 35.76, 52.58 25.9, 73.88 0.15 M40.4 46.04 C51.45 31.63, 67.03 14.1, 77.72 -1.54 M40.12 44.88 C49.66 34.89, 60.63 21.64, 80.23 0.49 M44.89 47.5 C57.81 32.43, 69.3 18.17, 84.5 1.31 M45.12 45.67 C53.48 35.41, 63.03 24.87, 85.53 -0.93 M50.68 46.1 C58.54 34.63, 67.6 24.77, 91.13 -1.77 M49.83 46.22 C63.52 30.46, 76.36 15.41, 89.69 0.74 M54.03 47.52 C69.15 30.48, 84.81 13.79, 95.52 -0.9 M55.46 45.08 C70.83 27.6, 85.27 11.58, 95.41 -0.95 M60.18 44.28 C68.24 34.67, 78.84 24.33, 101.81 0.2 M62.02 45.5 C73.85 31.43, 85.15 19.45, 99.71 -0.48 M64.67 47.26 C77.76 31.05, 88.4 21.52, 108.17 -0.35 M65.86 46.65 C76.77 33.67, 88.85 20.29, 105.91 -1.18 M73.03 45.23 C84.56 28.73, 99 13.7, 112.03 0.93 M71.59 44.91 C82.47 34.96, 91.36 22.91, 111.13 0.09 M78.08 44.28 C90.99 32.1, 103.18 16.31, 117.18 1.14 M77.66 45.13 C87.31 33.48, 98.44 21.15, 115.64 0.93 M83.63 43.38 C94.23 32.59, 100.72 22.75, 122.3 -1.29 M82.31 45.8 C96.83 27.39, 113.41 10.99, 121.65 0.85 M85.78 45.85 C102.34 28.25, 118.51 11.45, 125.5 1.22 M87.08 46.4 C95.97 35.73, 105.35 24.96, 126.07 0.83 M92.63 46.89 C102.61 33.84, 110.36 22.05, 131.4 1.57 M92.83 44.59 C101.8 36.46, 110.08 27.41, 131.87 -0.71 M97.55 45.03 C103.97 37.23, 113.44 29.03, 136.38 1.56 M97.2 45.48 C108.42 34.17, 120.78 21.97, 137.56 -0.65 M102.92 45.68 C119.2 27.68, 134.11 7.89, 144.34 -0.68 M104.66 44.86 C117.6 29.03, 131.31 14.69, 143.23 0.06 M109.39 44.61 C120.6 33.23, 134.88 16.27, 147.96 0.85 M107.98 46.5 C120.96 31.29, 133.47 17.97, 148.01 -0.32 M115.63 43.43 C124.07 37.41, 128.29 28.21, 151.09 1 M114.21 45.32 C126.44 31.11, 137.8 18.16, 152.76 0.41 M119.58 45.13 C128.72 34.96, 135.92 28.05, 154.07 7.03 M120.24 44.72 C129.21 33.16, 139.84 21.62, 151.62 7.69 M126.18 45.54 C133.38 35.71, 141.69 25.87, 153.29 12.96 M124.74 45.78 C135.28 33.98, 146.29 21.34, 151.8 14.31 M128.65 44.88 C135.78 38.27, 141.55 31.17, 151.98 19.25 M129.71 44.52 C138.56 35.08, 147.95 26.01, 152.67 19.81 M135.55 43.95 C141.58 40.66, 145.93 33.27, 151.23 24.44 M135.76 45.94 C140.16 41.45, 144.45 35.97, 152.96 25.93 M139.48 44.06 C144.96 41.24, 148.16 36.91, 150.72 32.82 M140.93 45.43 C145.82 40.87, 148.76 34.63, 151.7 32.06 M145.31 45.93 C148.97 42.16, 150.45 40.71, 152.25 38.49 M145.63 46.09 C147.9 43.77, 149.47 41.92, 152.38 38.59" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-1.15 1.9 C38.2 -0.99, 78.12 0.45, 149.27 -1.4 M-0.86 0.96 C48.91 -2.07, 96.54 -1.74, 150.71 0.12 M152.54 -1.25 C151.45 11.06, 150.36 21.93, 152.29 43.24 M149.93 0.93 C152.01 11.46, 151.31 21.02, 150.9 43.9 M151.83 43.56 C118.87 44.16, 88.18 42.46, -1.51 44.79 M151.67 42.19 C94.7 41.91, 38.43 41.58, 0.52 42.14 M-0.12 44.16 C-0.16 27.14, 0.64 12.78, -0.13 -0.17 M-0.03 43.06 C0.58 29.99, 0.96 15.35, -0.85 -0.57" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(766.2755711873376 580.0276196797689) rotate(0 93.66671752929688 36.8333740234375)"><path d="M1.49 0.84 C42.82 1.62, 84.83 -0.62, 186.41 -1.68 M0.53 0.94 C72.92 -0.04, 144.35 -0.47, 187.46 -0.96 M186.21 0.15 C188.68 15, 189.51 34.04, 185.68 74.91 M186.99 -0.35 C188.72 16, 187.17 31.8, 187.31 73.27 M186.08 74.16 C130.87 73.91, 76.51 72.35, -1.36 74.6 M187.33 73.15 C122.35 74.55, 57.24 74.65, 0.66 74.13 M1.83 75.53 C-0.38 53.34, -1.93 29.46, 1.74 -1.4 M0.98 72.74 C1.16 57.31, 0.84 40.47, -0.52 -0.75" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(791.6088841756189 590.6942761739095) rotate(0 78.5 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">import_module_inst;</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">import_func_inst;</text></g><g stroke-linecap="round" transform="translate(772.6087621053064 594.6942303975424) rotate(0 5 6.1666717529296875)"><path d="M5.31 0.77 C6.93 1.51, 8.26 2.46, 9.89 7.68 M6.16 0.39 C7.48 2.07, 8.9 4.53, 10.4 6.62 M10.41 7.33 C8.28 8.08, 7.99 9.82, 6.54 12.06 M9.92 6.81 C8.87 7.96, 7.96 9.3, 6.32 12.42 M5.57 12.65 C4.73 10.63, 2.35 9.82, 0.26 6.26 M5.66 12 C3.71 10.56, 1.83 8.63, -0.21 6.93 M0.77 7.34 C2.27 4.68, 4 1.5, 6.8 0.48 M-0.13 7.37 C1.49 4.82, 3.37 2.78, 5.96 -0.4" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(773.9421361287439 617.6942303975424) rotate(0 5 6.1666717529296875)"><path d="M6.77 0.03 C6.91 2.13, 7.17 3.27, 10.68 7.31 M6.39 0.08 C7.14 2.71, 8.7 5.53, 9.62 6.88 M10.33 6.37 C8.48 8.71, 7.63 10.61, 5.73 11.77 M9.81 6.72 C8.48 8.43, 7.33 10.86, 6.09 12.16 M6.32 12.59 C3.42 9.66, 1.68 8.57, -0.74 7.37 M5.67 12.14 C4.16 10.5, 2.06 8.5, -0.07 7.37 M0.34 6.98 C2.75 3.61, 4.62 2.36, 6.48 0.05 M0.37 6.68 C1.94 4.43, 4.03 2.35, 5.6 0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(451.60889943440793 480.5278638203939) rotate(0 66.33334350585938 17.16668701171875)"><path d="M-1.36 1.62 C30.16 -2.34, 60.91 -0.86, 131.1 -0.3 M-0.25 -0.36 C45.3 -0.49, 90.32 -1.74, 133.35 -0.59 M131.35 -0.56 C130.83 6.18, 131.64 14.2, 131.56 35.85 M132.08 0.66 C132.23 11.01, 132.24 21.11, 131.8 34.03 M133.53 33.33 C100.61 35.35, 69.11 35.09, 1.31 36.11 M131.87 33.47 C91.11 36.05, 48.41 34.81, -0.92 34.08 M0.56 36.21 C1.08 26.73, -0.37 18.14, 0.58 0.8 M0.61 33.88 C-0.01 19.96, -0.22 7.44, 0.62 0.29" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(481.9422429402673 488.09455083211276) rotate(0 36 10)"><text x="36" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">functions</text></g><g stroke-linecap="round" transform="translate(460.9422429402673 488.8612073262533) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.12 10.41 C3.13 9.88, 4.82 7.5, 8.17 4.34 M1.74 11.32 C3.64 8.78, 6.27 5.83, 7.41 4.45 M4.79 14.3 C6.5 13.02, 8.39 9.7, 10 6.86 M4.56 14.21 C5.96 12.36, 7.43 11, 9.96 7.46" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.33 0.24 C7.08 2.99, 8.65 6.58, 10.11 9.51 M6.12 0.13 C8 3.12, 9.52 6.54, 10.74 9.44 M10.75 9.7 C7.89 11.7, 6.17 15.24, 5.1 17.62 M10.93 8.89 C9.21 11.15, 8.07 14.38, 6.48 18.04 M6.26 16.91 C4.53 15.96, 3.68 13.72, -0.84 8.55 M6.1 18.02 C3.89 14.79, 2.89 13.23, -0.19 8.72 M0.31 10.02 C2.5 5.51, 4.18 2.88, 5.9 -0.39 M-0.07 8.67 C1.7 5.91, 3.36 3.59, 6.42 0.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(583.1472276731299 493.42127561960376) rotate(0 70.40993975187826 -0.5172233363575742)"><path d="M0.28 1.73 C45.47 -3.1, 86.17 -1.58, 141.74 -2.76 M-0.92 -0.05 C34.62 0.43, 70.23 0.48, 140.1 -1.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(583.1472276731299 493.42127561960376) rotate(0 70.40993975187826 -0.5172233363575742)"><path d="M112.37 11.47 C122.32 4.52, 127.84 2.93, 141.51 -2.95 M111.17 9.69 C119.07 7.43, 126.96 5.03, 139.87 -1.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(583.1472276731299 493.42127561960376) rotate(0 70.40993975187826 -0.5172233363575742)"><path d="M112.01 -9.05 C122.21 -9.57, 127.84 -4.74, 141.51 -2.95 M110.81 -10.83 C118.61 -8.02, 126.59 -5.36, 139.87 -1.2" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(451.94215138753293 525.0278027852377) rotate(0 65 15.5)"><path d="M0.08 -1 C29.05 0.23, 56.38 -0.16, 128.73 -1.23 M0.74 0.64 C41.59 -1.17, 80.94 -0.55, 129.4 -0.91 M131.36 0.97 C130.02 12.02, 131.91 23.09, 131.8 31.44 M129.09 0.89 C129.57 11.03, 129.49 23.78, 130.44 31.62 M130.93 30.9 C100.53 30.91, 70.05 30.25, 1.34 32.48 M130.14 30.53 C99.55 32.72, 69.36 32.52, 1 31.49 M-0.91 29.64 C0.95 24.3, -0.17 15.37, -0.61 0.75 M0.23 30.18 C0.72 20.77, -0.27 9.97, 0.17 -0.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(489.44215138753293 530.9278027852378) rotate(0 27.5 10)"><text x="27.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">globals</text></g><g stroke-linecap="round" transform="translate(461.27552541097043 530.0278027852377) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.09 10.93 C4.55 8.7, 5.75 5.62, 8.34 4.66 M1.5 10.97 C3.2 8.86, 5.3 7.25, 7.31 3.96 M4.17 14.69 C5.76 11.52, 8 10.4, 10.01 7.6 M4.36 14.45 C6.23 11.68, 8.59 9.07, 10.26 7.4" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.49 0.13 C7.2 1.99, 8.36 4.58, 10.05 9.13 M6.32 0.47 C7.6 3.18, 9.68 6.47, 10.2 9.45 M11.14 8.87 C8.86 13.23, 6.53 16.72, 6.22 18.47 M11.11 8.78 C8.92 11.34, 7.95 14.46, 6.31 17.36 M5.95 18.45 C3.66 15.73, 1.23 12.4, 0.78 8.3 M5.75 17.61 C4.92 15.75, 3.46 14.29, 0.26 8.82 M-0.74 9.49 C2.64 6.32, 4.01 3.51, 6.4 0.54 M-0.45 9.33 C1.92 6.4, 3.53 4.3, 5.83 0.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(182.27552541097043 497.6944592793783) rotate(0 79 16)"><path d="M1.97 -1.11 C47.95 1.84, 91.88 -1.13, 159.64 0.28 M0.05 0.45 C40.89 -0.54, 79.46 -1.15, 157.33 -0.45 M157.79 0.91 C157.54 8.16, 159.14 14.14, 157.98 32.46 M157.63 0.64 C158.36 6.66, 159.14 14.41, 158.26 32.26 M158.41 33.07 C115.15 30.92, 73.16 30.36, -1.82 32.32 M158.42 32.34 C108.73 31.16, 57.8 31.72, 0.78 31.87 M0.01 32.34 C-2.01 26.39, 1.27 17.8, -1.86 0.82 M-0.15 32.13 C0.45 23.85, -0.33 18.17, -0.92 -0.67" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(255.77552541097043 503.1944592793783) rotate(0 5.5 10)"><text x="5.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">e</text></g><g stroke-linecap="round" transform="translate(200.94215138753293 509.69442876180017) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.62 10.06 C3.71 9.38, 4.93 7.22, 7.59 3.45 M1.59 11.22 C4.07 9.02, 5.65 6.24, 7.94 3.65 M4.32 14.73 C5.91 12.42, 9.26 9.29, 9.83 8.07 M3.97 14.57 C5.35 11.99, 7.42 10.13, 9.72 7.49" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.44 0.68 C8.48 2.65, 8.72 7.53, 10.81 8.52 M6.23 0.5 C7.66 2.43, 8.7 4.86, 10.44 8.65 M11.11 8.7 C9.49 12.48, 7.17 14.98, 6.23 16.86 M10.98 9.08 C8.88 12.58, 7.58 15.37, 6.13 17.52 M6.57 17.59 C4.19 16.14, 2.62 13.03, 0.17 9.18 M6.18 18.07 C3.68 14.49, 1.81 11.84, -0.07 8.56 M0.18 7.92 C2.46 6.94, 3.39 2.49, 6.44 -0.82 M0.07 9.28 C1.47 5.98, 4.21 2.74, 5.64 -0.02" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(448.27552541097043 616.6944897969564) rotate(0 65.66668701171875 16.166656494140625)"><path d="M-0.61 0.75 C50.7 -1.29, 99.4 -0.13, 129.69 1.23 M0.17 -0.31 C48.34 -0.37, 95.04 -0.58, 131.04 -0.87 M131.19 -1.02 C131.98 8, 129.58 19.48, 131.67 33.56 M132.09 -0.33 C131.33 8.89, 132.25 17.22, 130.5 32.39 M129.34 33.65 C80.7 32.21, 25.65 33.37, -1.52 32.75 M131.85 31.36 C102.72 33.03, 73.72 31.83, -0.04 32.82 M1.95 32.11 C0.44 25.96, -0.2 18.02, 0.66 0.84 M-0.61 32.66 C-0.07 24.38, -0.91 14.51, -0.22 0.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(472.27552541097043 624.361146291097) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.24 11.71 C4.33 8.84, 5.66 6.73, 7.54 4.83 M1.42 10.5 C3.76 8.31, 5.25 6.53, 7.63 4.2 M4.24 13.85 C5.16 11.69, 7.61 10.6, 9.81 8.04 M4.19 14.2 C5.64 12.75, 7.26 10.54, 9.81 7.84" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.38 0.5 C7.04 2.61, 8.98 4.39, 11.29 9.62 M5.84 0.48 C7.52 2.49, 8.64 4.57, 10.22 8.98 M10.16 9.29 C8.44 10.88, 7.88 14.71, 6.6 17.35 M10.5 8.93 C9.21 12.39, 7.44 14.55, 6.03 18.14 M6.69 18.34 C4 14.02, 2.81 11.6, 0.22 8.11 M5.49 17.53 C4.55 14.75, 2.22 12.74, 0.25 8.65 M-0.12 9.16 C2.23 6.45, 3.58 4.68, 6.46 -0.26 M0.18 8.92 C2.15 6.02, 3.28 3.96, 6.17 -0.04" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(432.77543385823606 439.9444592793783) rotate(0 107 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstanceExtra</text></g><g stroke-linecap="round" transform="translate(440.3587926228845 465.9444821675619) rotate(0 77.5 100.20833969116211)"><path d="M-0.19 -0.8 C38.62 -0.25, 76.29 -3.46, 154.75 -0.21 M-0.67 0.3 C53.97 1.63, 107.04 0.82, 154.59 0.27 M155.68 1.5 C155.35 42.87, 156.26 83.33, 153.89 201.04 M154.45 -0.02 C155.46 72.45, 155.88 144.5, 155.69 200.32 M155.87 199.91 C100.73 197.79, 44.61 199.15, 1.5 199.08 M155.8 199.54 C105.21 200.66, 55.91 201.44, -0.07 199.57 M-1 199.19 C-2.02 149.9, -1.34 101.62, -0.25 0.84 M0.02 199.85 C-1.14 130.24, 0.34 59.44, -0.55 0.62" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(770.6921208699548 217.02776082356775) rotate(0 87 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#d9480f" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance::</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#d9480f" text-anchor="start" style="white-space: pre;" direction="ltr">import_func_ptrs</text></g><g stroke-linecap="round" transform="translate(821.2756322224939 293.65286000569665) rotate(0 24 14.5)"><path d="M-0.78 -1.07 C13.49 -0.87, 30.18 1.01, 46.44 1.34 M0.23 0.12 C17.18 -1.34, 35.09 -1.16, 48 -0.77 M47.19 -0.89 C49.56 6.89, 46.89 18.09, 46.38 30.65 M48.99 -0.22 C46.91 9.14, 48.57 18.99, 47.47 29.28 M46.28 28.97 C29.37 27.62, 14.23 27.56, 0.76 29.15 M47.3 29.62 C38.18 28.36, 27.79 27.66, 0.13 28.52 M0.31 28.07 C-1.42 19.11, 0.65 11.68, 1.63 -0.08 M0.14 28.54 C-0.2 19.51, -0.54 11.34, 0.44 -0.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(845.2756322224939 301.3195164998373) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.42 11.11 C3.29 8.48, 5.76 5.77, 7.36 4.59 M2.12 11.1 C2.93 9.38, 4.93 7.55, 8.1 3.88 M5.1 13.36 C5.41 13.11, 6.92 10.1, 9.97 7.72 M4.3 14.36 C6.16 11.94, 7.73 9.79, 10.35 7.2" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.46 -0.4 C7.17 3.89, 9.7 5.32, 11.35 9.63 M6.06 -0.11 C7.24 3.27, 8.95 6.25, 10.28 8.99 M10.23 9.64 C8 11.66, 7.46 14.89, 6.81 18.08 M10.56 8.6 C9.32 11.26, 8.32 12.39, 6.14 18 M5.98 17.16 C3.97 16.49, 2.59 14.11, 0.08 7.99 M6.33 17.67 C3.95 14.4, 1.55 11.84, -0.25 8.98 M-0.5 8.37 C1.66 5.96, 4.63 2.82, 5.96 0.09 M-0.25 8.89 C1.49 6, 3.71 3.82, 5.72 0.33" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(820.9422581990564 326.81948598225915) rotate(0 24 14.5)"><path d="M-0.79 -0.82 C16.48 1.31, 28.15 1.6, 49.25 0.96 M-0.22 -0.92 C18.88 -0.8, 37.19 -0.83, 47.97 0.87 M49.3 -1.73 C46.52 9.08, 46.27 18.13, 48.83 27.16 M47.18 -0.76 C49.12 7.71, 47.76 17.35, 48.68 28.25 M47.05 27.69 C35.85 27.62, 21.31 29.14, -1.91 29.76 M48 28.8 C37.39 28.39, 28.06 28.82, -0.04 29.92 M-1.16 27.7 C0.88 20.59, 1.58 12.42, 0.17 0.01 M-0.2 28.45 C-0.58 20.03, 0.4 10.08, 0.62 0.41" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(844.9422581990564 334.4861424763998) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.33 10.68 C3.72 8.01, 5.11 7.1, 7.06 3.84 M1.59 10.93 C4.29 8.22, 6.25 5.93, 7.53 4.33 M3.97 14.76 C5.16 12.09, 6.46 11.74, 10.4 7.74 M4.22 14.25 C6.1 11.71, 9.01 8.71, 10.5 7.5" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.58 0.83 C7.7 1.58, 9.07 5.35, 11.15 9.89 M5.53 0.15 C7.14 2.92, 8.64 5.82, 11.11 8.92 M9.81 8.33 C9.83 10.49, 9.02 13.94, 5.09 17.61 M10.29 9.41 C8.38 12.16, 7.06 16.21, 5.63 17.6 M5.31 18.5 C3.99 16.18, 3.51 12.92, 0.4 8.04 M5.89 17.37 C4.09 15.74, 2.93 13.65, 0.48 8.92 M-0.71 9.5 C1.85 7.08, 3.79 3.45, 6 0.19 M-0.3 8.71 C2.05 6.42, 3.53 3.69, 6.22 0.11" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(820.6089452107751 360.1528294881185) rotate(0 24 14.5)"><path d="M1.63 1.05 C10.28 1.54, 24.93 1.16, 49.75 0.47 M0.29 -0.74 C14.99 -0.33, 29.95 1.31, 47.84 -0.4 M46.64 0.84 C46.57 9.06, 49.02 12.98, 47.89 30.98 M48.83 -0.82 C47.24 8.34, 48.44 15.38, 47.86 28.14 M49.58 27.63 C34.44 28.83, 17.46 29.44, -1.82 27.61 M47.43 28.09 C30.75 28.43, 13.2 29.82, -0.15 29.15 M0.92 28.84 C1.8 21.57, 0.33 14.3, 0.35 0.28 M-0.54 29.23 C0.5 21.12, 0.68 14.67, 0.2 -0.02" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(819.2755711873376 387.81948598225915) rotate(0 24 14.5)"><path d="M-1.56 1.34 C13.67 0.71, 26.59 0.21, 48.24 -0.44 M0 -0.77 C9.95 1.22, 19.8 -0.05, 47.55 0.65 M46.38 1.65 C48.64 4.35, 47.69 14.36, 47.56 27.36 M47.47 0.28 C48.92 5.74, 48.1 12.11, 47.98 28.52 M48.76 29.15 C34.83 29.43, 23.66 27.28, 1.24 29 M48.13 28.52 C34.52 29.48, 20.97 28.72, -0.46 28.42 M1.63 28.92 C0.03 22.2, 0.21 15.67, -0.92 -0.41 M0.44 28.49 C0.78 22.29, 0.35 14.74, -0.55 -0.77" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(841.9422581990564 396.1528294881185) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.45 11.38 C2.79 8.79, 5.55 7.7, 8.2 3.58 M2.19 10.67 C3.39 9.05, 5.03 7.14, 7.3 3.97 M4.06 14.51 C6.61 12.17, 9.21 9.66, 10.33 7.49 M4.44 13.99 C6.41 12.26, 8.2 10.46, 10.06 7.81" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.68 0.63 C8.31 4.36, 9.84 7.03, 10.44 8.07 M5.61 -0.01 C7.91 2.88, 8.8 5.69, 11 8.56 M11.48 9.41 C8.72 10.92, 9.51 12.77, 5.19 16.91 M10.8 9.34 C8.44 12.23, 6.59 15.61, 5.77 17.34 M6.08 16.66 C4.19 13.45, 0.78 11.78, 0 8.79 M5.75 17.65 C5.1 15.49, 3.25 13.22, -0.3 8.66 M-0.04 9.09 C2.09 6.02, 4.31 2.23, 5.78 -0.59 M-0.28 9.33 C1.68 6.87, 2.92 4.25, 5.58 0.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(854.4355731342787 302.6860074500122) rotate(0 155.1115315463511 -89.18647089833189)"><path d="M-0.82 0.46 C20.28 -9.23, 73.87 -27.26, 125.84 -57.14 C177.82 -87.02, 280.39 -158.85, 311.05 -178.83 M0.95 -0.35 C21.97 -10.01, 73.35 -26.58, 124.94 -56.2 C176.54 -85.82, 279.75 -157.59, 310.52 -178.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(854.4355731342787 302.6860074500122) rotate(0 155.1115315463511 -89.18647089833189)"><path d="M293.7 -153.62 C294.97 -158.6, 299.18 -166.45, 311.76 -178.08 M293.07 -154.25 C297.96 -159.5, 302.77 -167.07, 310.05 -178.66" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(854.4355731342787 302.6860074500122) rotate(0 155.1115315463511 -89.18647089833189)"><path d="M282.19 -170.61 C286.29 -171.52, 293.2 -175.39, 311.76 -178.08 M281.56 -171.23 C289.57 -171.63, 297.6 -174.44, 310.05 -178.66" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1179.1925938924157 475.8611501057943) rotate(0 4.1666412353515625 6.875)"><path d="M4.8 0.43 C5.58 0.79, 6.34 3.17, 8.58 7.24 M5.01 -0.01 C5.98 2.79, 7.8 5.19, 8.67 7.03 M8.92 6.47 C7.02 9.41, 6.03 12.69, 4.41 14.17 M8.24 7.11 C7.04 8.9, 6.03 11.31, 4.65 13.56 M4.28 14.08 C2.94 10.97, 1.43 9.63, -0.62 6.35 M5.3 13.92 C3.35 12.2, 2.23 10.45, -0.08 6.77 M-0.1 6.93 C1.7 4.69, 4.12 1.09, 4.59 -0.42 M-0.05 7.27 C1.6 4.29, 2.99 1.88, 5.2 0.32" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1176.6925938924157 505.8611501057943) rotate(0 5.4166412353515625 4.791660308837891)"><path d="M5.98 -0.58 C7.71 1.97, 8.7 3.8, 10.89 5.66 M5.76 -0.02 C7.6 1.88, 9.61 3.25, 11.03 5.04 M11.02 4.52 C8.91 6.05, 7.87 7.35, 5.67 9.77 M10.97 4.86 C8.74 6.64, 7.22 8.26, 5.74 9.46 M6.3 8.97 C4.73 8.07, 3.09 6.88, -0.41 5.64 M5.97 9.49 C4.29 8.26, 2.02 6.53, -0.19 5.13 M0.49 4.96 C1.52 2.64, 3.58 1.73, 6.58 0.23 M0.14 4.64 C2.1 3.21, 4.09 1.53, 5.91 -0.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(778.9421361287439 601.2292964185075) rotate(0 -90.98788933388869 151.80961648821892)"><path d="M0.14 0.31 C-29.78 28.4, -165.6 118.68, -180.48 169.18 C-195.36 219.68, -104.22 280.94, -89.14 303.3" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(778.9421361287439 601.2292964185075) rotate(0 -90.98788933388869 151.80961648821892)"><path d="M-115.79 288.8 C-110.7 293.93, -105.65 295.26, -90.44 304" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(778.9421361287439 601.2292964185075) rotate(0 -90.98788933388869 151.80961648821892)"><path d="M-101.25 274.32 C-99.3 282.67, -97.47 287.2, -90.44 304" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g transform="translate(298.938463846843 10) rotate(0 336 80)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">this is the one actually referred during executing opcode</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"></text><text x="0" y="54" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">during model load, if import can be solved through the native api registeration,</text><text x="0" y="74" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">the pointer of native function will be filled.</text><text x="0" y="94" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"></text><text x="0" y="114" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">c-api could change the pointer later, then it will point to a different native function</text><text x="0" y="134" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"></text><text x="0" y="154" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">NULL: means multi-module import, go to "import_func_inst" field for target function</text></g><g stroke-linecap="round" transform="translate(286.7322362264001 10.440431867326993) rotate(0 345.59522356305797 85.02977371215815)"><path d="M-0.27 0.08 C158.33 -2.61, 317.92 -2.89, 691.86 -0.52 M692.86 -0.06 C691.59 64.53, 692.04 124.25, 689.86 170.88 M690.75 169.52 C519.14 170.97, 345.87 171.32, 0.55 170.5 M1.97 171.39 C-2.01 110.89, 0.48 49.66, -0.22 -0.28" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g stroke-linecap="round"><g transform="translate(563.3673013845143 183.65911670203138) rotate(0 95.01727766716022 26.27372288522156)"><path d="M1.13 -1.06 C62.37 17.19, 126.86 38.9, 188.91 53.61" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(563.3673013845143 183.65911670203138) rotate(0 95.01727766716022 26.27372288522156)"><path d="M160.16 55.29 C168.04 54.03, 179.09 56.45, 188.88 52.54" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(563.3673013845143 183.65911670203138) rotate(0 95.01727766716022 26.27372288522156)"><path d="M165.39 35.44 C171.49 40.84, 180.79 49.93, 188.88 52.54" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g transform="translate(465.44261678059934 866.4445775349935) rotate(0 88 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance*</text></g><g transform="translate(681.1368522644048 791.2780380249025) rotate(0 99 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(WASMFunctionInstance*)</text></g><g stroke-linecap="round"><g transform="translate(778.4752089766343 623.8987867002398) rotate(0 -56.26639954603991 154.5365026932369)"><path d="M-0.76 0.86 C-19.33 23.37, -102.69 84.7, -110.98 135.93 C-119.26 187.16, -60.18 279.58, -50.46 308.21" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(778.4752089766343 623.8987867002398) rotate(0 -56.26639954603991 154.5365026932369)"><path d="M-70.32 285.19 C-63.57 296, -56.63 299.46, -50.55 310.15" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(778.4752089766343 623.8987867002398) rotate(0 -56.26639954603991 154.5365026932369)"><path d="M-51.76 276.44 C-51.15 290.06, -50.4 296.43, -50.55 310.15" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(785.4704132080083 965.4446398417157) rotate(0 5 6.1666717529296875)"><path d="M6.26 0.47 C7.89 1.84, 8.2 3.93, 10.16 7.59 M6.16 0.28 C7.77 2.44, 9.14 4.92, 9.93 6.72 M10.05 6.37 C7.98 9.31, 6.36 10.39, 6.06 11.79 M10 6.96 C8.84 8.8, 7.64 10.3, 5.96 12.15 M6.32 12.42 C3.31 10.15, 2.1 8.66, -0.37 7.71 M6.04 12.5 C4.02 10.17, 1.38 8.61, 0.2 7.11 M-0.55 6.62 C0.92 4.72, 2.38 4.34, 5.34 -0.04 M-0.35 7.19 C2.02 4.64, 4.65 2.34, 5.63 0.02" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(818.1370391845708 962.7779833475751) rotate(0 47 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_import</text></g><g transform="translate(829.8037261962895 992.7779833475751) rotate(0 17 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func</text></g><g stroke-linecap="round" transform="translate(787.1370391845708 997.6112810770672) rotate(0 5 6.1666717529296875)"><path d="M5.61 -0.42 C6.84 2.46, 9.29 5.13, 9.92 6.25 M5.87 0.26 C7.22 2.27, 8.48 5.01, 9.94 6.89 M10.33 6.35 C8.14 8.67, 6.94 10.28, 5.74 12.2 M10.19 7.09 C8.86 8.57, 7.41 10.35, 5.84 12.54 M5.62 12.55 C3.92 10.1, 2.63 9.26, -0.14 6.74 M5.85 12.2 C4.41 10.92, 2.36 8.76, 0.02 7.24 M-0.67 6.68 C2 4.68, 2.88 4.14, 5.28 0.23 M0.12 7.37 C1.59 5.08, 2.67 3.66, 5.65 0.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(763.4704132080083 951.4446398417157) rotate(0 77.00003051757812 39.5)"><path d="M19.75 0 M19.75 0 C59.79 -0.76, 102.31 2.02, 134.25 0 M19.75 0 C61.57 1.76, 103.44 0.75, 134.25 0 M134.25 0 C148.69 -0.93, 153.66 5.19, 154 19.75 M134.25 0 C149.09 -0.35, 153.39 6.77, 154 19.75 M154 19.75 C151.75 26.16, 153.88 34.37, 154 59.25 M154 19.75 C153.84 31.64, 154.07 44.33, 154 59.25 M154 59.25 C154.54 72.82, 147.2 77.89, 134.25 79 M154 59.25 C155.03 71.28, 148.82 79.93, 134.25 79 M134.25 79 C99.13 78.38, 62.02 80.23, 19.75 79 M134.25 79 C91.42 79.06, 49.02 78.26, 19.75 79 M19.75 79 C5.94 80.49, 1.02 72.98, 0 59.25 M19.75 79 C4.86 79.11, 1.4 71.06, 0 59.25 M0 59.25 C-0.52 50.18, -1.25 38.72, 0 19.75 M0 59.25 C-0.46 45.76, -0.02 31.7, 0 19.75 M0 19.75 C1.61 7.8, 4.97 0.08, 19.75 0 M0 19.75 C-1.16 4.81, 6.97 -1.97, 19.75 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(754.8035202026372 925.2224718729657) rotate(0 58.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunction </text></g><g stroke-linecap="round"><g transform="translate(890.9805898853024 1015.1655927022294) rotate(0 196.40673779968859 41.03543176646508)"><path d="M-0.69 0.31 C25.03 13.88, 88.22 76.94, 153.92 81.47 C219.62 85.99, 353.49 36.54, 393.5 27.45" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(890.9805898853024 1015.1655927022294) rotate(0 196.40673779968859 41.03543176646508)"><path d="M369.81 46.33 C374.52 39.3, 381.28 35.4, 391.77 26.29" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(890.9805898853024 1015.1655927022294) rotate(0 196.40673779968859 41.03543176646508)"><path d="M364.09 26.63 C370.33 24.87, 378.62 26.23, 391.77 26.29" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g transform="translate(729.5256932576501 529.3609326680502) rotate(0 19 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">union</text></g><g stroke-linecap="round" transform="translate(720.8589452107751 703.360902150472) rotate(0 130.33334350585938 30.666671752929688)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.17 5.85 C2.05 4.31, 4.5 1.23, 4.91 0.06 M-0.6 6.11 C0.66 5.13, 1.78 4, 4.69 0.09 M-0.84 13.15 C4.76 7.87, 5.48 6.35, 12.09 1.51 M0.64 11.52 C1.9 9.54, 4.41 6.81, 9.87 -0.13 M1.53 20.38 C1.67 13.23, 8.99 9.75, 16.93 0 M0.6 19.24 C4.15 13.35, 9.69 8.82, 16.6 -0.41 M-0.86 24.6 C5.18 16.64, 11.82 11.98, 21.97 -0.71 M0.8 23.09 C6.87 15.73, 15.69 7.11, 20.98 -0.09 M-1.48 29.11 C5.87 20.1, 13.83 11.62, 25.16 2.06 M-0.74 30.31 C9.87 19.04, 19.97 8.17, 25.58 0.51 M-0.62 38.03 C12.77 22.21, 26.07 8.07, 30.16 1.51 M0.01 36.9 C7.22 28.52, 15.07 18.65, 32.2 -0.78 M-0.67 42.94 C6.79 34.16, 14.99 24.77, 38.3 1.86 M0.26 43.26 C10.7 31.53, 22.07 19.91, 36.5 0.51 M0.87 47.15 C8.39 37.33, 20.04 26.89, 40.87 0.34 M0.46 48.94 C14.88 31.96, 30.43 13.62, 42.24 -1.11 M-1.08 56.52 C17.5 34.46, 39.57 12.52, 46.74 -0.65 M-0.06 54.77 C16.97 36.29, 32.99 17.23, 48.12 -0.54 M0.49 59.55 C21.78 37.99, 42.04 14.62, 54.57 0.43 M-0.32 61.41 C13.86 46.99, 27.03 30.1, 53.97 -0.69 M3.5 62.37 C20.97 44.88, 33.97 27.02, 56.48 0.41 M3.22 63.76 C20.1 45.4, 36.3 25.47, 57.64 0.03 M7.22 62.92 C22.75 49.99, 36.23 31.55, 62.28 1.37 M8.19 63.48 C21.56 48.43, 37.61 31.54, 63.19 -0.83 M12.48 64.91 C30.36 46.49, 43.73 31.2, 67.11 -1.18 M14.59 64.45 C29.59 47.41, 43.17 29.11, 69.73 0.69 M18.55 63.95 C34.47 43.7, 51.11 22.78, 75.65 -0.36 M18.84 63.22 C41.88 39.7, 62.09 12.73, 73.67 0.46 M24.75 64.54 C45.77 39.53, 64.72 16.61, 77.81 -1.75 M23.39 63.46 C42.1 43.22, 60.67 21.13, 79.51 0.7 M30.14 64.22 C45.31 46.77, 57.53 28.18, 84.9 -1.39 M29.56 64.47 C42.63 46.89, 56.32 30.88, 84.12 -0.53 M33.67 63.53 C53.94 38.13, 73.79 17.79, 89.36 -1.69 M35.77 62.62 C55.21 40.51, 74.69 20.07, 89.54 -0.87 M41.9 62.19 C58.01 42.08, 76.3 23.21, 96.87 -1.4 M40.35 63.86 C57.48 44.94, 73.89 24.93, 95.22 -0.21 M45.18 65.05 C62.56 46.99, 76.78 24.97, 102.12 0.49 M45.83 63.1 C56.03 50.64, 67.8 38.74, 100.84 -0.18 M49.32 62.24 C63.19 47.67, 78.58 31.48, 104.96 -1.22 M49.68 64.8 C63.1 51.43, 73.2 37.53, 106.59 -0.71 M55.17 63.93 C70.99 44.24, 86.87 25.68, 110.07 -1.82 M55.99 65.08 C71.21 45.76, 86.94 27.45, 111.9 0.44 M61.51 64.65 C75.9 44.7, 92.35 27.15, 114.53 0.04 M61.46 64.51 C76.16 45.5, 93.82 28.01, 117.14 -0.09 M66.09 65.63 C79.78 52.15, 88.76 35.49, 122.77 -1.3 M66.56 63.81 C79.45 49.68, 93.63 32.21, 121.63 -0.57 M71.13 63.59 C94.17 38.65, 115.55 13.04, 127.51 -0.14 M72.05 63.02 C85.95 46.28, 101.44 31.34, 126.72 -0.4 M77.01 64.81 C97.1 42.25, 117.17 17.03, 131.35 1.27 M76.86 65.05 C90.15 49.13, 103.37 34.07, 132.42 -0.95 M80.47 65.16 C94.98 48.09, 111.92 31.2, 136.42 -1.08 M83.27 64.11 C100.28 42.7, 117.86 22.75, 137.16 -0.09 M88.26 64.24 C97.79 51.3, 110.6 36.2, 142.58 -0.99 M86.8 63.17 C102.91 48.45, 115.74 31.34, 143.1 0.33 M91.39 65.36 C109.34 48.69, 125.13 29.82, 149.07 0.05 M93.4 64.41 C106.34 48.2, 118.77 32.98, 147.89 -0.11 M98.76 65.64 C109.9 47.37, 124.09 34.18, 152.78 0.94 M97.27 64.77 C110.9 49.46, 123.49 34.77, 153.96 0.12 M103.36 64.08 C118.83 46.75, 138.65 26.73, 157.84 -1.02 M104.15 64.32 C117.71 47.6, 132.12 30.24, 158.3 -0.08 M108.01 63.61 C124.16 45.69, 143.81 24.29, 165.89 -2.01 M109.09 63.8 C125.84 44.55, 142.21 25.47, 163.74 0.05 M115.45 63.14 C136.82 37.39, 159.52 11.22, 169.71 -1.65 M113.71 63.03 C125.91 50.41, 138.21 36.55, 168.73 0.64 M118.12 63.66 C135.44 46.75, 151.64 25.19, 175.45 1.02 M120.03 64.47 C139.9 39.52, 160.37 15.78, 174.63 -0.43 M124.29 64.26 C142.34 43.93, 160.58 23.08, 180.26 1.69 M125.71 63.55 C136.9 50.17, 150.62 34.77, 179.48 0.03 M131.79 64.21 C144.62 46.84, 156.54 33.06, 186.56 -1.24 M129.84 64.3 C148.79 41.57, 169.14 20.06, 185.29 -1.1 M134.14 63.04 C156.21 37.85, 178.36 15.5, 191.65 -0.54 M136.23 63.68 C156.3 40.65, 177.03 17.77, 189.8 0.33 M142.31 62.59 C154.02 51.52, 164.45 37.41, 197.94 -0.13 M141.19 63.12 C156.8 47.41, 170.99 30.34, 195.81 0.08 M146.84 63.03 C157.61 48.13, 173.82 30.89, 202.64 -0.99 M146.8 62.99 C157.86 48.41, 172.05 34.65, 200.89 -0.9 M151.57 65.02 C164.63 48.12, 181.93 28.03, 207.91 -1.1 M150.72 64.04 C163.21 51.2, 174.56 36.7, 206.74 -0.07 M155.81 61.66 C177.07 41.48, 196.18 17.91, 210.59 -1.39 M157.43 63.88 C176.67 40.99, 195.11 19.95, 212.9 0.19 M160.04 64.64 C174.64 50.06, 189.11 33.73, 216.36 -1.67 M162.03 64.47 C181.19 41.01, 203.07 17.32, 218.08 -0.94 M168.09 64.26 C181.91 49.69, 194.55 34.72, 221.44 1.43 M167.55 62.54 C186.26 42.11, 206.9 19.19, 221.94 0.75 M172.81 63.5 C192.47 38.85, 212.61 16.27, 226.79 -1.48 M172.67 63.12 C192.67 39.52, 214.25 16.07, 228.31 -1.09 M177.64 62.84 C200.18 36.93, 222.87 11.41, 231.75 1.53 M178.4 64.7 C191.06 47.77, 205.55 30.4, 233.07 0.21 M181.54 62.54 C201.23 44.65, 215.6 24.85, 239.63 0.5 M183.12 63 C204.27 38.87, 227.26 13.11, 238.68 -0.55 M189.99 63.03 C201.14 44.96, 219.59 29.72, 242.64 1.91 M188.64 63.64 C208.1 42.51, 228.31 19.47, 243.3 -0.68 M194.49 63.63 C210.07 48.62, 223.35 30.98, 248.87 0.96 M193.85 64.4 C205.4 48.16, 219.8 34.76, 248.85 1.17 M200.28 62.67 C214.42 46.8, 232.4 25.31, 253.84 0.44 M199.43 63.68 C214.66 45.02, 232.24 25.91, 254.61 -0.88 M202.51 63.52 C217.89 46.36, 234.53 26.34, 260.15 -1.27 M204.25 63.93 C225.81 39.12, 246.88 15.07, 260 0.64 M209.93 62.7 C229.19 40.43, 248.51 19.25, 263.72 2.18 M210.02 64.19 C222.23 48.01, 236.17 33.78, 262.94 2.2 M213.06 63.88 C233.09 40.38, 252.76 22.89, 264.11 10.12 M215.68 63.48 C223.93 51.41, 233.94 40.24, 263.18 8.77 M219.92 66.01 C234.77 45.64, 250.23 27.67, 264.63 12.39 M220.12 63.35 C234.15 48.15, 248.95 31.47, 262.6 14.74 M224.17 65.29 C241.4 45.09, 255.67 28.48, 264.15 22.5 M226.46 63.25 C240.18 46.51, 256.17 29.53, 262.06 21.44 M228.84 63.36 C243.55 49.46, 251.71 39.54, 264.6 27.86 M230.89 63.12 C242.3 51.22, 255.1 37.17, 262.96 26.86 M234.49 65.23 C245.2 52.93, 253.24 43.72, 262.61 33.9 M236.85 62.73 C242.77 54.57, 250.56 48.51, 264.08 32.08 M242.89 63.45 C248.67 57.78, 253.95 52.92, 261.09 38.85 M241.94 64.26 C248.62 55.68, 254.07 49.51, 263.14 39.53 M245.24 64.09 C250.69 58.67, 255.81 50.4, 264.15 46.04 M246.07 63.7 C251.25 59.34, 253.16 55.64, 262.88 45.67 M253.53 63.02 C253.79 62.64, 255.32 57.54, 262.24 50.39 M252.27 63.43 C254.91 61.4, 256.87 56.84, 262.29 50.81 M257.83 63.35 C259.93 60.88, 260.02 59.22, 264.12 57.54 M257.4 63.39 C259.38 61.53, 261.29 58.88, 263.02 56.41" stroke="#fab005" stroke-width="0.5" fill="none"></path><path d="M0.86 0.23 C103.01 0.78, 208.51 1.08, 261.92 0.54 M-0.54 0.04 C64.29 -1.92, 128.5 -2.31, 260.51 0.48 M259.69 -0.22 C261.29 17.06, 261.5 29.12, 262.46 60.04 M260.7 0.84 C260.1 12.98, 260.32 27.97, 260.47 60.44 M261.33 60.89 C157.92 63.28, 55.55 61.82, -0.3 60.61 M261.17 61.75 C187.33 62.35, 113.54 62.5, -0.31 60.98 M-1.59 63.23 C-1.17 38.91, 0.94 19.87, 1.17 -1.66 M-0.92 61.56 C-0.51 49.16, 0.57 36.04, -0.66 -0.91" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(835.6922887166345 724.4275739034018) rotate(0 15.5 10)"><text x="15.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round"><g transform="translate(1038.8590062459316 97.26073430379154) rotate(0 -0.9296336643662926 603.828422179073)"><path d="M0.61 -0.01 C-3.91 268.54, -2.72 535.69, -0.46 1207.66" stroke="#000000" stroke-width="4.5" fill="none" stroke-dasharray="1.5 10"></path></g></g><mask></mask><g transform="translate(835.5257237752282 678.694154103597) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g transform="translate(160.38889567057322 395.983039601644) rotate(0 85.5 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#e67700" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance</text></g><g stroke-linecap="round" transform="translate(154.192410786947 427.0274670918783) rotate(0 105.33334350585938 152.6666717529297)"><path d="M-1.25 0.37 C41.71 -0.65, 85.67 0.2, 210.75 0.21 M-0.83 0.14 C51 1.88, 103.94 1.64, 209.99 0.23 M210.55 -0.58 C210.66 110.95, 213.07 219.42, 209.78 305.77 M210.78 0.38 C210.63 99.37, 210.08 199.81, 210.51 305.31 M211.46 305.57 C146.03 303.94, 78.67 305.29, -0.61 306.79 M209.99 305.8 C167.52 305.26, 123.11 305.43, 0.73 304.89 M-0.92 306.57 C-0.13 218.44, -2.58 134.44, 1.33 -1.18 M0.32 305.95 C-1.97 206.35, -1.27 106.16, 0.15 0.03" stroke="#d9480f" stroke-width="4" fill="none"></path></g><g stroke-linecap="round" transform="translate(1289.7476170857751 1043.1386833190918) rotate(0 114.66668701171875 35.666656494140625)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0 6.83 C1.56 3.74, 3.73 2.39, 4.9 1.02 M-0.33 6.3 C1.04 4.62, 2.87 2.74, 4.73 0.37 M0.91 11.02 C4.78 8.08, 7.95 5.74, 10.54 0.01 M0.77 12.14 C4.38 8.04, 7.02 4.44, 10.89 0.54 M-1.75 19.24 C2.32 15.43, 6.24 11.1, 15.96 1.97 M-0.71 19.04 C4 14.58, 8.4 9.61, 16.51 0.86 M0.67 25.16 C3.81 20.21, 8.93 14.05, 21.54 0.94 M-0.04 24.14 C4.97 19.75, 10.12 14.53, 22.01 0.13 M1.77 28.79 C9.51 18.09, 20.25 6.79, 24.77 -1.55 M0.16 31 C5.45 23.15, 12.18 17.72, 25.6 0.15 M-1.84 36 C8.93 28.02, 15.96 19.01, 33.64 -0.64 M0.05 37.08 C12.17 23.65, 24.24 10, 31.23 -0.97 M-0.24 41.55 C12.41 30.17, 23.86 13.91, 35.35 0.83 M0.26 42.04 C10.49 30.24, 21.84 18.17, 35.91 0.39 M-2.1 50.23 C13.07 32.82, 26.64 17.02, 41.67 -0.78 M0.36 49.07 C15.53 31.92, 30.95 12.73, 42.4 -0.62 M1.96 56.55 C17.68 34.34, 34.34 15.24, 45.75 -0.94 M0.94 53.61 C10.47 42.47, 21.25 30.44, 48.49 -0.31 M0.18 61.7 C10.07 49.58, 19.87 35.61, 51.4 -0.02 M0.85 60.42 C22.06 37.42, 43.25 12.77, 53.64 -0.37 M0.34 69.18 C11.42 53.69, 24.56 36.74, 57.94 1.67 M-0.78 68.35 C18.39 45.73, 37.92 22, 58.23 1.12 M2.48 73.3 C15.41 55.29, 27.01 37.37, 65.49 -1.25 M0.64 72.86 C19.87 50.98, 36.84 31.11, 64.32 -0.29 M8.32 70.58 C20.2 56.38, 33.64 39.59, 67.79 1.8 M5.92 72.56 C28.97 45.88, 51.58 22.02, 68.8 -0.32 M12.75 70.74 C26.05 54.5, 41.21 35.5, 73.52 0.22 M12.12 72.29 C33.51 47.43, 54.23 22.45, 74.15 -0.02 M19.07 72.34 C40.8 43.01, 62.39 19.65, 79.09 -0.81 M17.02 71.82 C39.99 45.06, 65.46 16.5, 79.66 -0.66 M23.79 72.2 C36.41 56.96, 47.43 41.58, 85.97 -1.36 M22.49 71.43 C37.68 54.33, 54.79 34.04, 84.12 0.25 M26.01 72.38 C40.21 56.43, 56.68 40.45, 89.51 -1.84 M27.14 71.9 C51.66 45.83, 73.89 18.37, 89.07 0.03 M32.17 73.12 C50.89 50.28, 70.38 28.44, 96.22 -0.09 M33.58 71.63 C47.23 54.9, 63.74 36.92, 95.51 -1.19 M37.4 71.71 C54.65 52.71, 72.59 29.66, 100.64 1.62 M39.13 72.53 C61.67 44.36, 84.93 16.78, 101.1 0.61 M42.34 71.54 C56.52 58.69, 68.47 39.89, 106.58 -0.53 M43.01 71.2 C61.47 50.72, 80.42 28.85, 106.91 -0.64 M49.76 73.67 C68.53 45.77, 90.87 22.01, 111.98 1.08 M48.47 71.61 C71.48 44.92, 95.5 19.26, 110.6 -0.08 M52.69 70.1 C73.96 51.29, 94.51 24.94, 117.57 1.15 M53.2 72.42 C71.98 49.63, 92.13 27.13, 116.54 0.85 M60.47 70.93 C80.97 44.89, 102.36 19.67, 122.94 -1.35 M58.92 73.25 C83.19 43.24, 108.02 14.71, 122.23 -0.27 M65.48 74.03 C78.91 55.57, 95.49 35.04, 128.63 0.08 M64.36 72.49 C86.93 47.42, 110.13 21.71, 127.89 -0.6 M69.86 72.02 C84.01 58.04, 97.06 41.31, 130.82 1.04 M69.56 73.28 C93.82 44.38, 119.34 17.2, 133.44 -0.23 M76.9 73.15 C97.2 43.31, 120.64 19.03, 136.1 1.27 M75.52 72.59 C90.18 55.15, 104.27 39.89, 136.77 -0.15 M81.81 72.31 C97.93 49.72, 118.27 28.56, 144.84 1.52 M80.44 73.22 C93.07 58.51, 105.82 43.63, 143.47 0.74 M87.05 71.89 C102.79 53.72, 118.47 33.24, 149.92 -1.45 M85.47 72.84 C104.02 50.74, 122.6 30.4, 148.97 -0.28 M89.12 72.78 C111.54 44.98, 133.73 21.59, 152.11 -2 M90.88 72.04 C114.29 45.26, 136.6 19.12, 154.37 -0.74 M97.91 71.25 C109.84 58.14, 122.18 42.84, 158.89 1.37 M95.82 71.32 C111.89 55.58, 124.93 39.46, 158.55 1.03 M99.48 73.96 C115.15 54.94, 132.71 37.81, 163.68 -1.06 M100.52 73.16 C122.46 49.8, 140.52 26.27, 163.98 -1.06 M107.4 70.84 C132.21 47.26, 153.03 17.5, 168.75 0.74 M107.99 71.05 C126.27 51.38, 145.71 28.46, 168.88 1.2 M113.51 74.03 C133.34 48.33, 154.27 19.27, 176.47 1.42 M112.28 71.48 C136.47 46.03, 158.05 18.61, 174.94 -0.69 M119.31 70.85 C131.54 56.26, 145.29 40.5, 180.14 -0.72 M118.17 71.02 C135.28 53, 152.05 33.6, 179.6 0.13 M122.71 70.72 C135.01 55.11, 150.82 40.94, 187.32 1.11 M123.39 72.33 C146.05 45.9, 168.41 18.22, 185.69 -1.12 M129.37 70.08 C142.83 54.61, 161.77 36.56, 190.6 1.22 M128.36 71.17 C145.33 50.74, 164.52 29.67, 189.69 -0.82 M131.51 71.37 C151.11 51.16, 169.49 29.71, 194.97 -1.72 M132.37 72.48 C145.36 57.07, 158.58 41.07, 195.46 0.09 M139.2 71.92 C156.58 51.31, 177.99 26.99, 200.59 -1.65 M139.35 71.38 C153.49 55.39, 167.84 39.33, 200.41 0.15 M143.22 70.92 C165.12 48.36, 183.63 25.65, 206.09 -0.24 M144.04 71.19 C163.51 47.77, 185.32 25.71, 207.27 0.36 M150.33 70.34 C163.73 54.57, 178.78 39.17, 211.45 0.08 M149.73 72.5 C169.42 48.22, 190.46 24.84, 212.29 0.29 M154.09 73.89 C171.43 50.68, 191.79 32.94, 217.23 1.02 M154.51 71.15 C167.58 57.67, 179.76 42.78, 216.95 -0.96 M161.53 72.68 C173.67 56.77, 187.11 41.88, 223.45 -0.59 M160.25 72.07 C180.25 49.61, 201.56 25.02, 222.2 -0.69 M163.24 72.41 C187.64 45.41, 212.31 19.77, 228.86 0.1 M166.19 71.5 C181.72 52.54, 200.09 32.04, 228.13 0.43 M169.45 70.58 C187.96 49.96, 205.5 29.87, 231.79 1.19 M169.39 72.34 C192.89 48.39, 213.93 21.83, 230.3 2.65 M174.72 72.18 C197.67 47.96, 215.79 24.99, 232.13 7.94 M176.79 72.84 C187.68 59.01, 199.66 46.01, 232.01 7.11 M182.7 70.58 C189.98 58.65, 200.5 46.72, 229.99 15.15 M180.48 71.75 C193.91 56.76, 207.51 41.93, 230.49 13.45 M187.48 70.52 C204.87 53.55, 220.84 35.39, 233.25 21.22 M186.33 72.23 C196.37 60.89, 207.77 50.06, 232.74 19.77 M190.41 73.02 C202.94 59.32, 216.24 44.38, 231.55 27.26 M191.3 72.98 C203.03 59.42, 215.25 46.54, 231.03 26.98 M197.37 70.32 C205.99 64.32, 212.33 53.3, 231.03 30.77 M198.09 72.18 C211.07 56.83, 222.53 42.08, 231.96 32.55 M203.65 70.84 C211.22 59.73, 223.42 46.34, 232.37 36.88 M202.42 72.61 C211.03 61.07, 220.27 50.97, 231.96 38.77 M207.17 70.09 C215.3 62.43, 220.6 54.62, 230.88 43.49 M207.69 71.63 C214.26 64.22, 221.93 56.12, 231.79 44.07 M213.38 71.61 C216.07 65.97, 221.25 60.29, 233.22 48.98 M212.23 72.22 C219.6 64.59, 224.15 58.68, 232.61 49.78 M216.53 73.91 C220.3 68.71, 225.26 65.36, 230.14 57.15 M218.01 71.01 C221.5 67.49, 223.94 64.72, 231.18 57.16 M224.04 71.77 C226.71 68.54, 229.05 67.97, 232.4 64.21 M223.68 71.7 C225.85 69.34, 227.02 67.88, 231.67 63.8" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M-1.35 -0.18 C71.83 -0.66, 144.14 0.97, 227.79 -0.66 M0.78 0.01 C52.48 -1.18, 103.49 -1.79, 228.81 0.56 M228.68 1.22 C230.84 20.36, 230.48 42.4, 229.74 72.21 M229.67 0.68 C229.02 18.69, 228.34 39.04, 229.26 71.85 M228.68 69.69 C168.34 72.41, 111.37 72.13, 1.22 72.26 M229.98 71.6 C165.12 71.27, 100.24 69.93, 0.17 71.6 M-1.36 72.63 C1.58 52.26, 0.03 30.61, 0.58 -0.54 M-0.37 71.82 C0.26 49.17, 1.21 24.38, 0.26 -0.91" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1390.9143040974939 1069.2053398132325) rotate(0 13.5 10)"><text x="13.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[..]</text></g><g stroke-linecap="round"><g transform="translate(211.81277262741253 515.8838153584585) rotate(0 113.21284728116416 -24.589759536562838)"><path d="M-1.28 -0.73 C49.99 -12.81, 99.4 -22.86, 227.71 -48.56 M-0.06 0.34 C56.65 -13.37, 112.99 -25.1, 226.97 -49.52" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(211.81277262741253 515.8838153584585) rotate(0 113.21284728116416 -24.589759536562838)"><path d="M200.03 -34.46 C206.84 -38.25, 211.2 -40.56, 227.62 -47.94 M201.48 -33.19 C207.93 -38.08, 213.93 -41.21, 226.75 -49.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(211.81277262741253 515.8838153584585) rotate(0 113.21284728116416 -24.589759536562838)"><path d="M195.74 -54.52 C203.64 -53.87, 208.96 -51.72, 227.62 -47.94 M197.18 -53.25 C204.71 -53.16, 211.78 -51.29, 226.75 -49.08" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(180.52544911702512 451.5275891621908) rotate(0 81.5 19.166671752929688)"><path d="M-0.5 -1.85 C39.76 -0.01, 79.12 -2.38, 162.92 0.15 M0.2 0.82 C64.42 -0.12, 127.25 -1.44, 162.72 0.95 M161.68 -1.32 C161.37 13.65, 163.5 29.41, 163.81 39.84 M163.25 -0.11 C163.7 9.17, 161.9 20.86, 162.35 37.39 M163.63 38.39 C108.09 40.68, 50.48 37.64, -1.72 37.14 M163.15 39.07 C117.72 38.31, 70.51 37.59, -0.23 38.03 M1.8 36.94 C1.72 28.95, 0.8 19.06, -1.81 -1.96 M-0.47 39.27 C-0.68 27.08, 0.41 16.14, -0.29 0.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(191.19207509358762 462.5275891621908) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.25 11.21 C2.53 9.51, 4.1 7.2, 8.03 4.33 M1.96 11.02 C3.39 9.36, 4.76 7.58, 7.62 3.67 M3.44 14.04 C5.7 12.04, 8.58 9.13, 10.05 7.18 M4.55 14.44 C5.22 12.53, 7.07 11.32, 10.25 7.31" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.11 0.25 C7.54 2.06, 9.02 6.07, 11.61 9.8 M6.2 0.19 C7.16 2.46, 8.96 6.4, 11.13 8.54 M10.04 8.32 C9.97 10.62, 8.88 13.66, 5.63 17.02 M11.14 8.57 C8.97 11.78, 7.76 13.37, 6.24 17.3 M7.05 18.45 C4.53 13.78, 0.83 10.92, -0.18 9.23 M6.46 18.18 C4.46 15.78, 3 13.42, -0.28 9.17 M1 9.03 C1.72 6.88, 1.54 4.09, 5.8 0.65 M-0.24 8.74 C2.14 5.97, 3.39 3.74, 6.07 -0.45" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(837.6366348266606 1036.0275484720864) rotate(0 12.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[n]</text></g><g stroke-linecap="round"><g transform="translate(198.19202931722043 464.6941235860189) rotate(0 308.528620719444 -83.63145264608784)"><path d="M0.74 -0.74 C47.95 -15.15, 179.38 -58.21, 282.15 -86.21 C384.92 -114.22, 561.55 -155.32, 617.39 -168.75 M-0.33 1.49 C47.32 -13.31, 181.41 -59.88, 284.24 -88.1 C387.07 -116.32, 561.13 -154.39, 616.65 -167.83" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(198.19202931722043 464.6941235860189) rotate(0 308.528620719444 -83.63145264608784)"><path d="M590.28 -153.44 C597.46 -154.94, 600.69 -158.7, 618.61 -166.58 M591.48 -152.2 C598.73 -156.44, 608 -160.89, 617.5 -168.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(198.19202931722043 464.6941235860189) rotate(0 308.528620719444 -83.63145264608784)"><path d="M585.64 -173.43 C593.84 -170.8, 598.03 -170.39, 618.61 -166.58 M586.85 -172.19 C595.37 -170.06, 606.11 -168.18, 617.5 -168.09" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1059.1920598347986 233.36081059773767) rotate(0 30 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(void *)</text></g><g stroke-linecap="round" transform="translate(1182.6921056111657 430.8191235860189) rotate(0 4.1666412353515625 6.875)"><path d="M4.56 0.43 C5.85 2.16, 6.42 3.57, 8.04 7.4 M4.61 0.04 C6.44 1.86, 7.11 4.26, 8.54 7.11 M7.59 6.57 C6.85 9.32, 6.22 12.41, 5.1 13.39 M7.97 7.29 C7.46 9.13, 6.67 10.58, 5.25 13.72 M4.45 13.63 C4.37 12.17, 1.62 9.41, -0.56 7.12 M4.95 13.91 C3.68 11.79, 2.79 10.6, 0.08 6.94 M0.01 6.91 C1.48 6.25, 1.57 4.63, 5.52 0.72 M0.3 6.83 C1.36 4.89, 2.4 3.89, 5.01 0.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(413.7868245442712 360.4274670918784) rotate(0 34 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(void **)</text></g><g transform="translate(826.8590520222986 364.6941693623861) rotate(0 21.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">NULL</text></g><g stroke-linecap="round" transform="translate(174.1921106974288 662.5276247660319) rotate(0 87.33334350585938 15.83331298828125)"><path d="M0.27 1.85 C63.96 0.76, 132.92 -2.46, 173.64 -0.42 M-0.54 0.67 C61.2 0.45, 121.82 0.99, 175.26 -0.06 M173.58 1.64 C173.91 8.56, 175.87 22.66, 174.5 31.38 M174.95 -0.35 C173.85 7.6, 174.09 13.57, 174.13 31.4 M175.59 31.5 C123.19 32.56, 68.76 34.07, 1.4 32.22 M175.61 32.07 C106.32 33.22, 39.71 32.07, 0.6 30.95 M-0.73 30.29 C0.94 26.21, 2.05 18.18, -0.36 0.66 M-0.39 32.63 C0.83 21.84, 0.54 11.19, 0.66 0.18" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(179.52542368571005 670.1942812601725) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.43 10.45 C2.63 8.36, 4.09 6.77, 6.92 3.31 M2.16 10.51 C2.9 9.04, 4.25 8.31, 7.78 3.73 M3.68 14.96 C6.17 12.16, 8.32 9.91, 9.63 8.29 M4 14.16 C5.51 12.55, 7.89 9.94, 10.32 7.36" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.01 0.97 C8.27 2.6, 8.91 6.34, 11.14 8.96 M6.36 -0.21 C7.54 2.29, 8.6 4.45, 10.82 8.51 M10.44 8.07 C9.64 13.09, 7.1 15.27, 5.16 17.19 M10.34 9.4 C9.42 10.94, 8.32 12.78, 6 17.45 M6.56 17.59 C3.36 15.28, 2.39 11.73, 0.93 8.72 M5.75 17.93 C4.18 14.22, 1.91 11.06, -0.39 8.53 M0.36 9.93 C3.09 6.36, 4.05 3.08, 6.08 -0.31 M0.4 8.96 C1.85 6.06, 3.52 4.35, 6.36 0.19" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(199.52545420328818 667.0276247660319) rotate(0 74.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_type_indexes</text></g><g stroke-linecap="round" transform="translate(338.50791168212925 795.9999148050944) rotate(0 24 14.5)"><path d="M1.58 1.08 C12.29 0.15, 21.93 1.08, 48.68 -0.4 M-0.09 -0.64 C13.48 1.1, 24.44 -0.13, 48.1 0.72 M48 -1.36 C46.16 9.46, 46.33 19.19, 49.15 29.57 M47.96 -0.74 C47.35 6.88, 48.42 14.02, 49 28.04 M46.41 30.88 C36.4 29.69, 23.08 30.51, 0.4 29.83 M48.88 29.01 C35.68 28.59, 22.53 30.38, 0.48 29.47 M-0.51 29.39 C-1.66 19.07, 0.99 11.05, 1.5 0.67 M0.43 28.31 C-0.04 20.06, 0.72 12.64, -0.11 -0.18" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(338.17453765869175 829.1665407816569) rotate(0 24 14.5)"><path d="M0.74 0.12 C12.85 0.79, 28.75 -0.66, 47.22 -1.68 M0.95 0.89 C11.68 -0.04, 24.7 1.02, 48.39 -0.45 M46.29 -0.39 C46.46 6.81, 49.15 15.18, 46.91 27.96 M47.5 -0.24 C48.56 5.68, 48.99 10.85, 47.52 28.7 M48.5 29.51 C31.03 30.78, 15.93 30.28, -0.52 27.44 M48.85 28.17 C30.21 29.96, 11.19 29.47, -0.25 29.15 M-1.62 27.05 C1.11 16.13, 1.58 7.89, -0.33 0.41 M0.02 28.29 C0.65 21.75, -0.24 14.13, -0.48 -0.12" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(337.8412246704105 862.4998842875162) rotate(0 24 14.5)"><path d="M-1.19 1.05 C17.66 -0.43, 33.19 -1.7, 47.12 -0.17 M-0.61 -0.34 C11.43 0.29, 23.04 -0.87, 47.52 0 M46.46 -0.5 C48.9 7.3, 46.66 12.42, 46.07 28.93 M48.57 -0.22 C48.85 5.6, 47.37 12.8, 48.38 28.21 M47.26 30.33 C29.48 29.95, 9.64 27.56, 1.77 30.75 M48.85 29.96 C34.02 29.07, 18.84 28.75, 0.75 28.75 M1.03 27.01 C1.74 20.4, -0.09 10.87, -0.94 0.86 M0.78 29.09 C-0.12 22.11, -0.49 15.47, -0.57 -0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(336.507850646973 890.1665407816569) rotate(0 24 14.5)"><path d="M0.68 -0.4 C13.9 -1.93, 28.49 -0.42, 46.72 1.91 M0.1 0.72 C19.05 -0.28, 36.83 0.16, 47.32 -0.86 M49.15 0.57 C46.69 7.1, 45.85 16.21, 46.52 27.99 M49 -0.96 C47.68 7.71, 48.55 15.24, 48.94 29.25 M48.4 29.83 C31.87 27.76, 18.54 31.07, 0.02 30.69 M48.48 29.47 C37.35 29.61, 27.95 29.21, 0.2 28.19 M1.5 29.67 C-0.47 23.54, -1.09 18.13, -1.37 0.04 M-0.11 28.82 C-0.7 22.25, -0.8 15.7, 0.53 -0.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(184.1921106974288 673.6948118863805) rotate(0 38.378231293739304 78.25943440813717)"><path d="M-1.01 -0.53 C-10.98 3.81, -53.65 7.78, -60.1 25.56 C-66.56 43.35, -60.12 84.95, -39.74 106.17 C-19.37 127.4, 32.15 145.38, 62.15 152.92 C92.16 160.47, 127.21 151.92, 140.29 151.44 M0.67 1.81 C-9.45 6.33, -54.34 9.6, -61.11 26.7 C-67.87 43.79, -60.43 83.21, -39.91 104.39 C-19.39 125.58, 32.21 145.83, 62.01 153.81 C91.81 161.79, 126.12 152.52, 138.89 152.29" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(184.1921106974288 673.6948118863805) rotate(0 38.378231293739304 78.25943440813717)"><path d="M111.2 165.58 C118.35 164.12, 128.9 157.21, 138.2 152.5 M111.6 165.75 C121.31 160.01, 131.76 155.1, 138.64 152.86" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(184.1921106974288 673.6948118863805) rotate(0 38.378231293739304 78.25943440813717)"><path d="M108.82 145.2 C116.55 149.46, 127.77 148.26, 138.2 152.5 M109.21 145.37 C119.89 147.21, 131.23 149.87, 138.64 152.86" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(233.52546437581418 790.8056093851725) rotate(0 35 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">uint32 *</text></g><g transform="translate(1658.192130406698 142.0275433858236) rotate(0 48 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#1864ab" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule</text></g><g stroke-linecap="round" transform="translate(1647.5254433949792 172.02751286824548) rotate(0 154 284)"><path d="M1.2 0.78 C102.72 1.77, 204.13 1.4, 306.76 0.26 M0.23 -0.16 C68.78 -0.49, 136.52 0.22, 308.68 -0.07 M307.94 0.15 C310.49 119.37, 310.59 238.21, 307.73 567.69 M307.85 0.31 C309.47 119.64, 309.54 239.68, 308.01 567.81 M308.91 566.96 C232.95 566.08, 154.17 565.33, -1.42 566.99 M308.16 567.74 C197.74 567.47, 88.4 567.14, -0.24 567.78 M0.28 567.39 C-0.36 355.41, -0.7 143.49, -0.54 -0.02 M0.34 568.1 C-1.08 376.9, -0.79 186.32, -0.35 -0.05" stroke="#1864ab" stroke-width="4" fill="none"></path></g><g transform="translate(1660.1921914418542 189.36088689168298) rotate(0 131.5 112)"><text x="0" y="14.666666666666668" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMImport *import_tables;</text><text x="0" y="33.333333333333336" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMImport *import_memories;</text><text x="0" y="52" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMImport *import_globals;</text><text x="0" y="70.66666666666667" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"></text><text x="0" y="89.33333333333334" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMType **types;</text><text x="0" y="108" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMImport *imports;</text><text x="0" y="126.66666666666669" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMTable *tables;</text><text x="0" y="145.33333333333334" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMMemory *memories;</text><text x="0" y="164" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMGlobal *globals;</text><text x="0" y="182.66666666666669" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMExport *exports;</text><text x="0" y="201.33333333333334" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMTableSeg *table_segments;</text><text x="0" y="220" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> WASMDataSeg **data_segments;</text></g><g stroke-linecap="round" transform="translate(1663.5255044301355 487.36085637410486) rotate(0 136.66668701171875 22)"><path d="M-0.22 0.9 C80.61 -1.25, 158.66 -2.47, 271.83 -0.52 M0.75 -0.03 C63.07 -0.5, 127.02 0.13, 273.6 0.16 M271.41 1.23 C273.18 11.39, 275.13 20.16, 273.85 43.07 M273.57 -0.71 C272.96 12.64, 273.52 25.76, 272.51 44.37 M273.05 44.25 C179.01 43.36, 86.68 42.27, -0.31 42.49 M272.97 43.79 C173.58 45.82, 72.66 46.11, 0.2 44.22 M-1.45 42.94 C-0.76 32.9, -1.02 24.14, -1.89 1.62 M0.54 43.53 C0.25 31.19, -0.54 16.16, -0.05 0.57" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1725.5255044301355 500.6941693623861) rotate(0 99 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunction **functions;</text></g><g stroke-linecap="round" transform="translate(1676.1921914418542 504.02757390340173) rotate(0 13.33331298828125 9.666671752929688)"><path d="M15.07 0.17 C19.06 2.93, 22.08 7.61, 27.01 8.45 M14.7 -0.17 C16.49 2.21, 19.48 4.39, 26.78 9.56 M26.28 8.54 C23.96 12.86, 18.21 16.22, 14.51 17.89 M26.45 9.97 C23.4 12.34, 20.77 14.52, 13.56 19.19 M14.88 18.52 C11.66 17.22, 7.62 14.53, -0.02 9.16 M13.88 18.78 C10.07 16.15, 5.73 14.39, 0.82 9.7 M-0.69 8.65 C4.46 8.86, 5.12 5.44, 12.49 1.67 M-0.3 10.58 C5.34 6, 9.8 3.49, 13.42 -0.86" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1681.525382359823 518.0276044209799) rotate(0 -82.4910862058864 7.278134054565953)"><path d="M-1.86 1.99 C-65.35 5.98, -130.07 12.55, -164.94 13.9 M-0.04 -0.52 C-40.67 3.15, -81.54 6.76, -163.3 15.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1681.525382359823 518.0276044209799) rotate(0 -82.4910862058864 7.278134054565953)"><path d="M-138.12 4.06 C-147.45 7.41, -158.02 13.01, -165.12 13.52 M-136.3 1.55 C-142.73 4.98, -149.39 7.98, -163.48 14.7" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1681.525382359823 518.0276044209799) rotate(0 -82.4910862058864 7.278134054565953)"><path d="M-136.08 24.48 C-146.12 19.7, -157.5 17.17, -165.12 13.52 M-134.27 21.97 C-141.29 20.26, -148.46 18.13, -163.48 14.7" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1708.5255654652917 455.3609174092611) rotate(0 114.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMImport *import_functions;</text></g><g stroke-linecap="round" transform="translate(1662.8589394887292 440.6942914326986) rotate(0 138 21.33331298828125)"><path d="M1.2 -0.66 C98.69 1.08, 193.5 1.03, 276.55 -0.79 M0.57 0.58 C81.9 -0.72, 165.43 -1.85, 275.41 -0.33 M275.49 -1.34 C276.25 13.98, 274.27 30.18, 277.77 43.15 M275.43 -0.1 C276.24 10.46, 276.52 22.78, 275.76 41.96 M276.91 41.13 C168.04 39.73, 58.87 39.37, -0.63 41.14 M275.48 41.99 C212.82 42.35, 148.84 41.14, -0.18 42.91 M0.72 42.18 C0.61 32.38, -0.63 24.21, 0.03 1.04 M0.58 42.08 C-0.79 28.32, -0.63 11.98, 0.22 -0.96" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1677.5256875356042 451.36097844441736) rotate(0 7.666656494140625 11.333343505859375)"><path d="M8.62 -0.89 C11.51 5.04, 12.71 7.4, 16.61 12.17 M7.96 -0.38 C8.93 1.95, 10.75 4.22, 14.85 11.98 M16.48 12.83 C14.29 13.53, 11.12 17.94, 7.09 21.64 M15.42 11.84 C13.12 15.18, 11.49 17.97, 8.38 23.25 M7.46 23.93 C5.59 19.79, 4.18 15.93, 0.14 13.32 M7.77 22.04 C4.99 19.13, 3.06 16.82, 0.36 12.4 M-1.34 13.07 C2.8 8.21, 6.07 4.4, 9.08 -1.13 M0.15 11.43 C2.84 8.16, 5.49 4.08, 7.62 -0.07" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1684.1192735003276 461.96675503544054) rotate(0 -161.28263355896206 -93.6018801530613)"><path d="M-0.11 0.27 C-24.93 -13.65, -94.04 -52.52, -147.74 -83.81 C-201.44 -115.1, -293.05 -170.36, -322.31 -187.47 M-1.63 -0.63 C-26.2 -14.31, -92.17 -51.29, -145.64 -82.21 C-199.11 -113.12, -292.9 -168.4, -322.45 -186.12" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1684.1192735003276 461.96675503544054) rotate(0 -161.28263355896206 -93.6018801530613)"><path d="M-292.52 -182.47 C-304.38 -180.8, -316.12 -184.66, -320.72 -186.81 M-293.03 -179.65 C-298.44 -181.25, -305.11 -183.04, -323.22 -187.05" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1684.1192735003276 461.96675503544054) rotate(0 -161.28263355896206 -93.6018801530613)"><path d="M-303 -164.82 C-310.68 -170.11, -318.28 -180.93, -320.72 -186.81 M-303.51 -162.01 C-306.62 -167.18, -311.14 -172.59, -323.22 -187.05" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1136.8590310414636 272.6941693623861) rotate(0 111.33331298828125 151.66665649414062)"><path d="M-1.11 1.49 C46.39 2.96, 95.02 2.73, 222.62 1.28 M-0.55 0.17 C44.48 -2.21, 90.87 -1.14, 222.55 0.66 M223 -1.18 C223.13 118.46, 222.08 239.08, 222.23 302.56 M222.16 0.66 C223.09 117.56, 223.92 235.02, 223.36 303.48 M222.61 301.74 C135.71 303.05, 45.8 302.74, -0.34 303.66 M222.73 302.53 C159.88 302.82, 97.04 302.67, -0.24 303.72 M-0.52 302.36 C-2.1 236.39, -1.11 167.74, -1.39 -0.62 M0.69 302.67 C-0.64 242.34, -1.13 181.87, -0.34 0.39" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1139.525657018026 248.6941693623861) rotate(0 48.5 9.5)"><text x="0" y="15" font-family="Helvetica, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMImport</text></g><g stroke-linecap="round" transform="translate(1176.858908971151 283.360886891683) rotate(0 84.66668701171875 15.5)"><path d="M-0.25 -0.62 C66.99 -0.36, 134.74 -0.09, 167.47 1.58 M0.04 -0.26 C35.79 -2.08, 71.49 -1.84, 168.49 0.65 M168.65 -0.13 C167.49 9.18, 170.89 22.23, 170.76 31.83 M168.7 0.34 C169.64 7.43, 168.58 14.28, 169.01 30.5 M167.59 31.97 C128.51 30.77, 85.12 29.45, -1.46 29.74 M168.56 31.21 C124.03 30.56, 79.65 29.74, 0.4 31.9 M-0.03 31.29 C0.08 22.97, -1.16 13.02, -1.36 -1.44 M-0.13 30.35 C-0.03 22.51, -0.63 12.04, 0.71 -0.2" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1181.858908971151 288.360886891683) rotate(0 39.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">uint8 kind</text></g><g stroke-linecap="round" transform="translate(1137.8589700063073 576.6941693623861) rotate(0 110.5 15.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.36 6.58 C0.81 5.37, 2.08 3.73, 5.55 -0.34 M-0.57 6.01 C2.15 3.62, 3.82 1.48, 4.76 0.3 M-0.16 12.27 C4.03 7.66, 7.69 1.82, 9.31 0.69 M-0.52 11.36 C4.15 7.79, 8.39 3.28, 10.58 0.28 M-1.53 19.11 C6.56 11.32, 9.91 5.19, 13.69 1.96 M-0.58 18.05 C3.42 13.52, 7.73 9.65, 14.71 0.42 M1.7 25.49 C4.61 17.08, 12.18 10.97, 20.12 -0.26 M-0.46 24.4 C7.42 15.29, 13.9 6.46, 21.13 0.48 M-0.93 31.93 C9.93 19.67, 18.78 8.63, 25.86 -1.18 M0.37 30.12 C6.5 21.83, 13.47 14.14, 25.79 -0.65 M4.58 34.11 C12.87 21.89, 24.21 10.54, 30.67 0.6 M2.93 34.09 C10.74 23.86, 19.89 13.36, 32.66 0.05 M8.97 35.06 C17.23 24.08, 24.61 14.92, 36.13 -0.65 M7.14 33.65 C14.65 26.83, 20.33 19.58, 36.5 0.28 M14 33.18 C23.82 23.98, 32.56 13.66, 41.89 0.29 M13.04 33.08 C21.43 23.88, 29.52 14.31, 43.12 -0.12 M19.31 34.29 C29.1 21.65, 42.22 9.7, 49.3 -0.38 M17.87 33.05 C26.54 25.55, 33.18 15.69, 48.16 -0.7 M26.02 34.69 C31.22 21.94, 38.96 14.41, 53.63 -1.41 M24.72 32.07 C36.59 20.64, 46.86 6.74, 53.4 -0.94 M30.43 35.26 C35.83 27.2, 42.84 16.93, 59.77 -0.42 M28.28 33.99 C39.68 20.3, 50.9 7.46, 57.51 0.26 M33.51 34.24 C43.61 23.2, 47.95 16.42, 62.36 0.15 M33.51 33.23 C45.86 21.15, 58.3 7.84, 64.36 -0.01 M37.91 33.53 C49.73 21.78, 59.09 11.5, 69.54 1.11 M40.66 32.44 C47.9 24.12, 56.61 13.57, 67.77 -0.15 M42.9 35.06 C53.03 27.3, 59.87 19.21, 75.1 0.56 M45.38 33.3 C50.76 27.28, 57.84 19.22, 73.82 -0.63 M51.92 31.53 C61.33 20.87, 69.05 10.71, 78.2 1.99 M50.27 32.65 C59.63 22.42, 68.82 14, 79.6 0.53 M56.25 34.55 C65.35 21.24, 73.29 12.88, 83.5 0.29 M55.76 33.05 C62.17 26.14, 69.41 16.97, 85.53 -0.82 M59.22 32.63 C65.71 27.89, 72.51 18.03, 88.93 1.89 M60.3 34.17 C70.56 23.38, 80.12 12.29, 90.11 -0.45 M67.87 35.29 C73.81 27.44, 79.02 19.93, 93.79 -1.26 M65.21 33.32 C74.69 22.9, 83.57 13.09, 96.22 -0.3 M73.17 35.09 C80.74 23.68, 89.95 14.55, 102.51 0.42 M70.92 32.86 C83.45 20.57, 93.37 7.53, 99.87 -0.01 M77.67 31.74 C86.72 22.91, 92.4 12.82, 104.79 0.19 M77.74 32.72 C84.9 25.13, 92.7 15.76, 106.55 0.54 M83.71 34.08 C94.22 18.69, 103.6 9.04, 111.31 -0.94 M82.21 33.85 C94.77 21.35, 105.77 6.8, 111.91 -0.3 M89.12 32.26 C96.39 23.69, 107.78 10.82, 117.25 0.6 M87.81 32.68 C97.99 20.95, 108.31 9.61, 115.49 0.31 M91.39 31.67 C98.78 23.53, 109.1 14.61, 121.29 -0.77 M93.26 32.59 C102.7 22.48, 111.45 10.76, 122.7 0.34 M99.34 33.13 C103.9 27.3, 108.78 17.64, 126.51 -1.43 M97.32 34.41 C106.82 21.87, 118.36 10.01, 125.93 0.69 M105.34 34.84 C112.89 22.58, 122.43 8.37, 134.01 0.22 M103.06 33.83 C110.25 24.45, 117.73 17.3, 133.16 0.34 M108.99 32.54 C116.6 24.56, 121.08 20.83, 136.52 1.86 M108.64 33.93 C118.35 22.52, 126.96 11.86, 137.75 -0.1 M113.3 33.49 C125.91 21.48, 137.68 8.75, 144.63 1.26 M113.6 32.6 C123.47 22.9, 130.23 13.67, 143.69 -0.03 M120.36 32.58 C128.39 21.76, 137.32 12.35, 148.47 -1.61 M119.6 33.04 C127.24 25.27, 134.08 14.11, 147.42 0.72 M123.58 34.39 C129.06 25.25, 135.98 19.73, 151.88 -0.54 M124.78 33.22 C131.69 24.72, 138.64 17.15, 153.1 0.27 M131.32 33.25 C138.77 26.23, 146.82 14.97, 158.15 -1.01 M130.46 34.36 C140.26 20.29, 152.51 8.07, 158.39 0.22 M135.1 31.26 C146.17 24.55, 154.7 12.51, 164.12 -0.14 M135.48 32.34 C143.73 24.15, 151.16 13.95, 163.7 0.08 M141.32 34.44 C148.69 23.61, 159.66 12.35, 169.95 -0.61 M140.95 34.28 C148.82 22.96, 158.16 12.01, 170.03 0.76 M146.73 35.45 C156.3 20.81, 167.01 8.18, 173.26 1.38 M145.87 34.64 C154.34 24.35, 162.71 13.09, 174.21 -0.97 M149.44 33.97 C161.56 22.08, 169.69 11.09, 178.85 -1.78 M151.24 34.01 C159.38 23.22, 166.19 14.02, 180.7 1 M157.87 34.97 C162.76 25.6, 169.64 17.72, 184.85 -1.12 M157.05 32.82 C162.86 25.53, 169.62 18.26, 184.84 0.56 M160.31 33.55 C171.41 24.22, 177.12 16.06, 192.43 -0.97 M160.97 32.55 C172.53 20.9, 183.96 8.57, 190.69 0.9 M166.57 32.99 C177.4 21.1, 185.6 10.4, 195.99 1.09 M166.09 33.18 C176.52 21.12, 186.84 9.62, 196.23 -1.09 M174.19 32.81 C180.03 24.39, 188.59 16.39, 200.85 0.27 M172.22 33.68 C182.39 22.43, 191.7 11.19, 201.24 0.72 M178.12 34.83 C190.16 22.75, 198.55 9.63, 205.41 0.66 M177.68 33.51 C185.89 23.62, 196.21 11.85, 206.48 0.1 M184.92 35.26 C192.72 22.61, 204.2 9.38, 210.87 1.29 M182.53 33.01 C191.21 24.55, 201.12 14.3, 211.56 0.01 M186.41 34.73 C200.86 20.82, 213.2 8.93, 219.4 0.16 M188.44 32.95 C194.87 25.89, 201.06 19.95, 218.15 -1.03 M193.92 34.36 C205.42 19.61, 213.53 7.12, 223.19 1.12 M193.89 32.92 C199.05 26.37, 206.75 18.66, 221.15 1.37 M199.92 33.82 C205.85 28.28, 209.64 22.58, 223.32 5.61 M197.99 32.89 C203.69 28.09, 208.93 21.94, 220.67 7.67 M204.23 31.43 C208.45 25.63, 214.22 21.43, 222.58 13.47 M203.75 33.6 C210.58 27.43, 216.21 20.21, 222.92 12.52 M207.8 34.12 C212.93 28.77, 217.04 23.45, 223.21 18.39 M209.83 34.03 C214.71 27.65, 219.28 22.25, 221.17 18.64 M214.7 33.47 C218.7 30.84, 219.39 27.15, 222.87 25.01 M214.43 33.64 C216.5 31.75, 217.78 29.08, 221.97 25.25" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M0.61 0.1 C87.04 -2.37, 173.84 -2.12, 222.39 0.96 M-0.75 -0.64 C86.4 -0.39, 172.53 -0.78, 220.76 0.05 M219.76 -1.08 C219.56 10.46, 222.24 19.59, 220.83 31.99 M221.19 0.45 C220.57 6.76, 220.11 12.78, 220.35 31.42 M220.68 30.05 C173.52 32.34, 128.69 31.76, -0.43 31.13 M220.8 30.98 C135.98 31.23, 52.88 30.29, -0.06 31.61 M1.34 31.88 C-0.73 21.08, -1.21 10.58, -2 -1.84 M0.97 30.14 C-0.97 22.76, 0.74 15.49, -0.83 0.86" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1237.3589700063073 582.0941693623862) rotate(0 11 10)"><text x="11" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[1]</text></g><g transform="translate(1238.1924355824792 558.0274213155111) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(1139.3590615590417 608.3607800801595) rotate(0 110.5 15.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.59 7.11 C1.25 4.96, 3.11 2.48, 4.23 0.48 M0.01 6.41 C1.45 5.02, 2.65 2.98, 5.36 0.02 M-0.33 11.91 C1.23 8.78, 3.58 6.15, 11.51 0.6 M0.53 11.36 C3.76 8.86, 7.16 5.33, 10.68 0.53 M-0.61 19.27 C4.36 14.57, 8.04 9.31, 15.29 -0.23 M0.5 18.9 C4.69 14.21, 8.1 7.71, 16.15 0.48 M-0.92 24.28 C7.26 15.79, 17.29 5.58, 19.8 1.3 M0.55 25.07 C7.7 15.36, 15.04 6.87, 21.87 0.09 M-0.33 32.16 C8.63 20.35, 18.02 9.65, 26.12 0.85 M0.29 31.2 C5.33 22.73, 11 17.62, 25.72 -0.16 M3.42 32.47 C12.22 22.7, 20.02 12.53, 30.18 -0.16 M2.14 32.17 C13.11 22.52, 22.52 12.91, 32.11 0.71 M6.27 35.27 C19.06 21.76, 24.58 12.95, 38.61 1.7 M7.95 33.78 C13.31 26.5, 20.32 20.57, 36.81 0.8 M12 31.09 C22.48 24.59, 29.85 18.51, 40.98 -2.1 M14.27 33.2 C24.82 20.1, 34.96 8.29, 43.2 0.76 M19.18 35.02 C27.21 25.96, 34.27 15.39, 49.43 0.04 M19.43 32.45 C25.92 24.6, 33.18 17.2, 47.06 0.34 M24.72 33.78 C31.74 24.06, 37.69 16.28, 54.9 -2.1 M24.13 33.8 C36.28 20.71, 46.38 7.08, 52.87 -0.25 M29.59 31.74 C35.37 26.03, 39.76 19.88, 58.81 -0.5 M29.28 33.33 C34.77 24.89, 42.34 18.59, 58.56 0.26 M32.31 31.79 C41.87 26.96, 51.02 14.82, 65.24 1.16 M34.58 34.08 C46.45 20.54, 56.37 6.46, 63.8 -0.49 M37.93 33.61 C49.35 24.49, 56.46 14.6, 68.61 -0.41 M39.62 33.79 C49.69 20.81, 61.14 9.66, 68.83 0.15 M45.03 34.02 C51.38 25.12, 57.18 17.52, 73.88 -2.09 M43.91 33.66 C54.27 22.06, 63.77 11.29, 74.64 -0.85 M49.21 33.75 C60.84 20.83, 69.54 10.82, 80.24 1.76 M50.54 32.51 C57.99 25.73, 63.5 18.65, 79.86 0.41 M54.79 33.54 C65.32 23.06, 73.31 12.2, 85.3 1.3 M54.9 33.28 C64.39 22.87, 72.66 13.1, 84.97 0.09 M63.02 32.16 C70.6 20.92, 81.32 13.04, 88.75 -0.66 M61.05 32.47 C68.02 24.77, 74.93 17.88, 89.11 -0.79 M67.74 34.55 C71.45 28.07, 77.22 21.8, 96.57 1.35 M66.42 32.66 C75.3 22.9, 82.67 12.63, 96.35 -0.98 M71.58 33.77 C77.45 25.8, 83.63 17.71, 100.74 -0.42 M72.15 33.93 C82.76 21.24, 92.36 8.6, 100.47 -0.46 M77.63 35.18 C87.87 20.87, 97.54 6.7, 107.37 -0.97 M75.81 34.36 C84.56 23.77, 93.37 15.49, 107.26 -1.04 M81.66 34.4 C89.33 23.98, 97.45 15.65, 112.43 1.63 M81.76 33.46 C92 21.95, 101.22 13.09, 111.28 0.18 M87.79 33.46 C93.07 27.28, 99.5 21.02, 117.29 0.95 M87.86 32.71 C95.45 23.32, 103.77 15.53, 115.51 0.97 M92.66 34.78 C104.47 21.76, 111.73 10.92, 123.64 -1.44 M93.79 32.94 C99.91 25.05, 107.27 17.16, 121.36 0.7 M97.16 33.32 C104.7 25.66, 112.24 17.4, 126.51 -1.65 M97.81 32.86 C108.87 21.89, 117.86 9.69, 127.81 0.12 M102.56 34.55 C112.6 24.54, 123.47 10.79, 131.76 -0.68 M103.06 32.51 C110.6 24.71, 117.65 17.49, 131.95 0.49 M110.27 34.6 C120.39 21.01, 128.59 10.53, 137.81 1.66 M108.34 33.74 C119.33 20.33, 130.77 8.51, 136.86 1.09 M113.94 34.25 C123.8 21.29, 132.94 13.65, 141.79 -1.21 M114.38 33.65 C123.69 21.41, 135.33 8.59, 142.77 -0.31 M119.23 35.05 C132.02 22.66, 140.8 10.26, 149.24 -0.54 M118.61 33.09 C125.25 25.17, 132.64 17.2, 148.97 0.05 M123.95 33.33 C133.63 25.17, 138.48 14.23, 152.31 -0.25 M125.49 32.1 C133.16 22.97, 143.63 12.41, 152.98 0.29 M129.76 32.32 C138.73 24.14, 144.11 14.52, 159.43 1.22 M129.22 34.42 C139.17 22.1, 149.08 12.68, 158.41 0.5 M134.36 32.15 C144.88 23.02, 154.79 7.09, 165.52 -1.12 M136.09 32.92 C143.81 22.99, 154.35 12.29, 164.2 -0.95 M139.17 33.97 C150.57 22.33, 161.07 10.44, 169.63 -0.67 M141.22 34.08 C151.39 20.86, 161.02 9.03, 170.4 0.22 M144.87 34.72 C156.31 20.42, 167.62 8.04, 173.18 0.77 M146.19 34.21 C157.57 21.67, 168.33 7.34, 175.48 0.53 M150.36 31.46 C159.73 22.03, 169.07 15.45, 181.64 -0.91 M151.12 34.17 C162.58 22.16, 171.35 8.51, 180.1 0.3 M157.73 35.71 C162.38 26.2, 166.72 19.27, 186.67 -0.08 M155.7 33.11 C165.87 22.77, 175.76 11.3, 186.36 0.08 M161.82 34.18 C169.1 23.59, 178.31 13.82, 191.88 0.7 M161.87 33.62 C171.1 21.43, 181.59 9.26, 191.64 0.12 M167.85 34.93 C172.8 26.42, 180.04 19.2, 194.96 -1.27 M167.53 33.31 C176.58 23.27, 185.07 11.71, 195.81 -1.15 M173.65 31.38 C182.57 24.27, 188.29 15.78, 201.38 1.26 M171.88 33.16 C183.95 21.1, 195.67 6.32, 201.09 0.36 M179.35 32.38 C188.61 20.68, 198.18 6.47, 206.6 1.51 M177.19 33.06 C188.24 21.82, 197.7 10.31, 207.26 -1.19 M181.53 34.27 C188.74 27.1, 196.02 16.54, 213.73 0.78 M184.04 32.28 C193.38 20.43, 203.92 9.31, 211.49 -0.01 M186.96 34.95 C200.29 22.55, 209.66 9.99, 215.73 0.48 M187.15 32.9 C196.63 24.65, 205.7 13.29, 217.59 -0.31 M194.73 33.92 C203.06 24.91, 210.68 14.49, 220.47 0.94 M194.64 32.3 C199.45 27.22, 206.14 20.44, 221.16 0.03 M198 34.41 C206.5 24.16, 216.01 15.11, 221.56 5.29 M197.82 32.65 C206 25.43, 213.63 15.56, 221.57 7.59 M206.13 31.34 C211.22 26.61, 214.16 19.9, 223.21 12.13 M204.47 33.33 C208.76 29.33, 213.17 24.14, 222.84 13.63 M210.35 33.48 C213.13 31.62, 215.52 27.66, 222.03 18.99 M208.63 34.4 C213.11 29.04, 217.24 23.41, 222.57 19.81 M214.54 32.21 C216.68 31.82, 218.36 28.73, 222.74 24.26 M215.39 33.22 C216.48 31.59, 218.67 29.16, 222.24 25.11" stroke="#ced4da" stroke-width="0.5" fill="none"></path><path d="M-1.37 1.11 C59.84 -2.88, 118.37 -1.4, 221.49 -0.35 M0.02 -0.53 C79.19 -2.47, 157.11 -2.59, 220.41 -0.2 M221.41 1.68 C222.43 7.17, 221.56 16.54, 219.51 31.19 M220.66 0.25 C220.79 11.06, 220.33 23.62, 221.34 31.48 M219.63 31.25 C137.63 31.89, 55.7 31.55, -0.22 31.14 M221.73 31.11 C146.72 33.55, 71.59 33.14, 0.7 31.86 M0.64 30.95 C-1.05 21.79, -1.72 11.94, -0.33 -0.79 M0.14 30.27 C-0.95 21.91, -1 13.76, 0.96 0.12" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1234.3590615590417 613.7607800801596) rotate(0 15.5 10)"><text x="15.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round" transform="translate(794.192145665487 262.0277112325033) rotate(0 48 85.33334350585938)"><path d="M24 0 M24 0 C36.45 -1.52, 54.02 -0.76, 72 0 M72 0 C89.59 0.9, 95.62 9.09, 96 24 M96 24 C98.69 57.16, 98.99 92.47, 96 146.67 M96 146.67 C96.55 160.68, 89.72 169.57, 72 170.67 M72 170.67 C58.21 169.42, 46.89 170.65, 24 170.67 M24 170.67 C7.79 171.18, -0.76 162.52, 0 146.67 M0 146.67 C0.07 117.08, 1.83 84.02, 0 24 M0 24 C0.71 9.34, 9.49 -0.34, 24 0" stroke="#d9480f" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(1734.858607610067 604.0277722676595) rotate(0 80 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">fast_jit_func_ptrs</text></g><g stroke-linecap="round" transform="translate(1664.8585465749109 595.6944897969564) rotate(0 136.66668701171875 22)"><path d="M-1.47 1.29 C58.82 -2.13, 120.35 0.48, 273.63 -0.11 M-0.03 -0.18 C69.9 2.36, 139.82 1.56, 273.28 -0.22 M273.39 -1.45 C271.1 13.15, 272.08 26.9, 272.71 44.54 M273.33 0.36 C272.82 10.87, 273.36 21.38, 272.47 44.11 M271.8 43.75 C204.28 43.52, 134.41 42.83, 1.09 43.61 M273.37 44.63 C205.86 45.05, 136.84 46.4, 0.64 43.45 M0.89 42.83 C-1.5 30.48, -1.61 17.25, -1.22 -0.81 M-0.71 43.98 C0.15 32.74, 0.4 18.82, -0.28 0.76" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1677.858607610067 607.0278180440267) rotate(0 13.33331298828125 9.666671752929688)"><path d="M14.58 -1.32 C19.52 3.25, 24.45 6, 26.85 9.3 M13.87 0.52 C18.62 4.11, 22.53 7.42, 26.47 9.58 M27.94 10.85 C21.68 11.34, 20.63 16.91, 12.88 19.6 M26.21 9.34 C23.43 11.82, 20.38 14.49, 13.68 19.16 M13.97 19.67 C11.23 17.08, 4.04 12.96, 1.28 10.71 M13.81 19.18 C9.44 15.74, 4.07 12.61, -0.71 9.17 M-0.91 11.15 C3.88 7.21, 8.94 2.53, 12.31 0.83 M-0.35 9.95 C4.18 5.79, 9.81 3.58, 13.14 0.29" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1524.191859563192 917.3610242207845) rotate(0 156.866929546371 95.29681424172588)"><path d="M-0.52 0.14 C24.43 21.45, 98.29 96.37, 150.75 128.1 C203.22 159.83, 287.02 179.92, 314.26 190.53 M1.41 -0.83 C26.11 20.62, 97.87 97.29, 149.85 129.34 C201.83 161.38, 285.88 180.81, 313.27 191.42" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1524.191859563192 917.3610242207845) rotate(0 156.866929546371 95.29681424172588)"><path d="M283.53 192.73 C294.01 191.58, 305.28 191.02, 313.93 191.68 M284.25 191.86 C295.25 191.99, 306.25 192.15, 312.54 191.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1524.191859563192 917.3610242207845) rotate(0 156.866929546371 95.29681424172588)"><path d="M289.8 173.19 C297.88 179.62, 306.71 186.66, 313.93 191.68 M290.52 172.32 C299.19 179.83, 307.81 187.41, 312.54 191.08" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(1547.5252030690515 878.6943677266439) rotate(0 143.82583264055665 71.41415189071404)"><path d="M0.41 0.59 C21.53 18.96, 77.83 85.58, 125.84 109.07 C173.86 132.57, 261.52 136.23, 288.49 141.56 M-0.84 -0.14 C20.26 17.95, 77.05 83.31, 125.16 107.16 C173.28 131.02, 260.78 137.17, 287.85 142.97" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1547.5252030690515 878.6943677266439) rotate(0 143.82583264055665 71.41415189071404)"><path d="M259.43 149.72 C265.72 147.86, 271.87 145.15, 287.28 141.4 M259.39 148 C265.62 147.03, 275.23 144.96, 286.88 143.84" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1547.5252030690515 878.6943677266439) rotate(0 143.82583264055665 71.41415189071404)"><path d="M262.52 129.43 C267.94 132.1, 273.4 133.91, 287.28 141.4 M262.48 127.72 C267.89 132.34, 276.64 135.88, 286.88 143.84" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(1514.1917680104577 826.0276807149252) rotate(0 189.95971181335858 57.63118275898967)"><path d="M0.68 0.02 C34.62 18.97, 140.14 104.17, 203.42 114.86 C266.7 125.55, 351.02 72.55, 380.34 64.17 M-0.42 -1.02 C33.44 18.05, 139.51 101.74, 202.87 112.84 C266.23 123.94, 350.36 74, 379.75 65.58" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1514.1917680104577 826.0276807149252) rotate(0 189.95971181335858 57.63118275898967)"><path d="M357.57 87 C363.97 80.45, 370.26 72.98, 380.73 64.48 M357.56 85.02 C364.62 79.45, 370.78 73.51, 380.27 66.57" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1514.1917680104577 826.0276807149252) rotate(0 189.95971181335858 57.63118275898967)"><path d="M349.8 68.01 C358.6 66.81, 367.1 64.74, 380.73 64.48 M349.8 66.03 C359.31 66.36, 367.89 66.32, 380.27 66.57" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(2121.191752751669 708.7778180440267) rotate(0 24 14.5)"><path d="M-1.08 -0.52 C20.79 -1.19, 39.89 1.34, 46.48 -0.43 M0.42 -0.38 C18.42 0.96, 36.33 -0.03, 47.6 0.1 M48.97 -0.78 C48.65 8.92, 46.98 18.26, 49.26 30.87 M48.37 -0.78 C48.57 8.13, 48.48 16.89, 47.32 29.55 M49.75 28.86 C30.65 28.01, 11.28 28.33, -1.13 30.81 M47.98 28.53 C36.75 28.3, 24.51 28.25, -0.33 30 M-0.09 30.97 C-0.45 20.1, -0.84 11.65, 1.73 1.28 M0.69 28.63 C1.15 21.77, -0.24 14.57, 0.96 -0.68" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2145.191752751669 716.4444745381674) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.53 10.57 C3.73 8.03, 6.44 6.33, 7.68 3.66 M1.41 10.87 C3.87 8.62, 6.51 5.46, 7.69 4.39 M4.66 14.74 C5.4 12.54, 7.13 10.53, 9.41 7.27 M4.46 13.85 C5.88 12.23, 7.93 9.61, 10.12 7.59" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.74 0.88 C6.68 2.95, 9.01 3.28, 10.45 9.82 M5.81 0.06 C7.7 2.44, 8.54 4.96, 10.72 9.13 M10.28 9.21 C8.65 11.7, 6.84 16.22, 6.92 17.44 M10.28 9.33 C9.54 11.59, 8.66 13.25, 6.27 18.06 M5.93 18.14 C3.5 14.87, 1.78 11.67, 0.95 8.44 M5.75 17.97 C4.22 15.91, 2.91 13.78, 0.53 9.11 M1.06 8.61 C1.39 6.53, 3.1 6.19, 6.69 -0.56 M-0.2 9.53 C1.46 6.53, 2.94 5.07, 5.63 0.17" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2120.8583787282314 741.9444440205892) rotate(0 24 14.5)"><path d="M1.74 -0.84 C19.67 1.82, 34.25 -0.3, 49.62 -0.25 M0.13 0.77 C12.24 -0.04, 24.6 0.28, 48.25 0.79 M48.42 -0.5 C46.89 8.14, 49.4 19.32, 47.55 28.27 M48.67 0.08 C48.7 11.49, 47.43 21.95, 48.8 29.15 M48.9 27.88 C32.04 28.16, 15.39 30.77, -1.07 27.28 M48.58 28.11 C31.94 27.84, 15.19 29.78, 0.21 28.08 M-0.72 29.4 C-1.09 19.16, 1.74 8.1, -1.03 -1.1 M0.99 28.97 C-0.6 20.55, 0.76 11.47, 0.32 0.19" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2144.8583787282314 749.6111005147299) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.82 10.29 C4.24 8.88, 5.19 6.49, 8.6 4.05 M1.54 11.3 C3.64 8.83, 5.29 7.22, 7.35 4.42 M4.21 13.99 C6.64 11.09, 7.44 9.46, 10.62 8.35 M3.84 14.61 C5.01 13, 6.72 11.52, 10.25 7.09" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.57 0.91 C7.98 1.4, 8.06 5.21, 10.54 8.6 M6.39 -0.13 C7.45 2.87, 9.2 6.27, 11.07 9 M10.42 8.39 C8.72 12.65, 8.3 14.82, 5.64 18.34 M10.71 9.29 C9.42 11.62, 7.72 15.28, 6.07 17.8 M5.41 17.55 C3.26 13.74, 2.31 10.41, -0.91 9.4 M5.53 17.76 C3.76 14.94, 2.99 12.64, -0.48 9.43 M0.22 8.4 C2.36 7.3, 4.15 3.14, 5.41 -0.1 M-0.02 8.78 C2.23 6.14, 4.09 2.48, 6.1 0.16" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2120.52506573995 775.2777875264486) rotate(0 24 14.5)"><path d="M1.79 1.69 C11.64 -0.23, 27.94 -0.05, 47.21 0.83 M-0.26 -0.22 C12.19 -0.27, 25.41 0.42, 48.01 0.48 M46.75 -0.58 C49.32 9.43, 47.61 14.39, 49.38 29.75 M48.59 0.8 C47.52 6.98, 49 13.01, 48.28 29.88 M47.78 28.2 C32.81 30.54, 18.81 27.01, 0.77 28.96 M48.18 28.07 C35.5 29.57, 23.87 27.66, 0.82 28.96 M-1.11 30.25 C1.83 18.73, -0.93 4.8, -0.19 1.37 M-0.4 28.98 C0.67 20.7, 0.03 13.95, 0.3 0.24" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2119.1916917165127 802.9444440205892) rotate(0 24 14.5)"><path d="M1.69 -1.52 C18.15 1.19, 36.92 -1.22, 48.83 -0.76 M-0.22 -0.4 C15.11 0.37, 30.82 0.13, 48.48 -0.39 M47.42 1.26 C49.79 8.86, 47.19 20, 48.75 27.44 M48.8 -0.68 C48.58 11.46, 48.17 21.59, 48.88 28.93 M47.2 27.87 C33.25 27.88, 13.17 29.71, -0.04 28.07 M47.07 28.67 C31.8 29.29, 12.68 29.91, -0.04 29.98 M1.25 30.73 C1.22 20.31, -1.16 13.48, 1.37 -0.75 M-0.02 29.96 C-0.67 17.76, 0.2 6.18, 0.24 0.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2141.8583787282314 811.2777875264486) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.82 10.81 C3.22 9.66, 5.36 6.72, 6.89 4.07 M1.78 10.81 C3.46 8.89, 4.87 7.88, 7.98 4.32 M3.36 13.55 C5.81 12.7, 8.66 9.37, 10.63 6.65 M4.36 14.27 C5.57 12.97, 6.35 11.58, 10.14 7.65" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.23 -0.22 C8.11 2.16, 8.09 5.02, 10.28 9.13 M5.8 0.05 C7.86 3.81, 9.5 7.04, 10.47 9.11 M11.29 9.92 C9.11 11.01, 8.73 14.12, 5.23 18.33 M10.33 9.27 C9.67 11.78, 7.98 14.81, 5.97 17.89 M5.41 18.62 C3.98 14.62, 3.49 13.4, -0.49 9.61 M5.82 18.19 C4.83 15.29, 3.88 13.92, 0.52 8.81 M0.93 9.69 C1.41 5.49, 3.79 3.95, 5.6 1.07 M0.52 8.63 C1.99 6.43, 3.77 3.78, 6.28 0.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1922.8584702809655 623.361131032308) rotate(0 99.61084169938476 40.74434897966137)"><path d="M-1.06 0.82 C32.47 14.1, 167.06 66.7, 200.28 80.35 M0.58 0.21 C34.12 13.53, 166.44 67.81, 199.78 81.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1922.8584702809655 623.361131032308) rotate(0 99.61084169938476 40.74434897966137)"><path d="M171.17 81.55 C174.54 78.74, 185.14 82.05, 198.59 82.7 M169.78 80.47 C179.37 79.76, 189.93 81.15, 199.64 81.1" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1922.8584702809655 623.361131032308) rotate(0 99.61084169938476 40.74434897966137)"><path d="M178.91 62.55 C180.67 63.9, 189.54 71.45, 198.59 82.7 M177.52 61.46 C184.52 67.35, 192.41 75.31, 199.64 81.1" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(2149.934976988394 812.7563059403802) rotate(0 -103.48397560700892 101.45670440057938)"><path d="M-0.8 0.48 C-14.86 23.88, -50.21 106.52, -84.74 140.31 C-119.26 174.1, -187.63 192.86, -207.95 203.22 M0.98 -0.31 C-13.24 23.27, -51.44 108.06, -85.85 141.69 C-120.27 175.32, -185.46 191.13, -205.52 201.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(2149.934976988394 812.7563059403802) rotate(0 -103.48397560700892 101.45670440057938)"><path d="M-182.25 181.04 C-189.66 185.38, -193.39 192.92, -204.89 199.9 M-183.54 181.32 C-189.89 187.6, -197.28 194.71, -204.98 201.61" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(2149.934976988394 812.7563059403802) rotate(0 -103.48397560700892 101.45670440057938)"><path d="M-174.72 200.13 C-184.17 199.23, -189.94 201.58, -204.89 199.9 M-176.01 200.41 C-184.98 200.58, -194.8 201.53, -204.98 201.61" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(2143.191752751669 780.1944897969564) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.01 11.64 C4.43 8.89, 6.59 6.23, 7.63 4.45 M1.53 11.27 C3.57 8.41, 5.92 6.57, 7.88 3.85 M4.19 13.51 C6.41 12.15, 7.21 10.04, 10.8 7.37 M4.25 14.13 C5.63 12.02, 7.99 10.43, 10.42 7.49" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.65 0.99 C8.09 1.66, 8.53 3.85, 9.93 8.35 M6.12 -0.45 C6.78 2.38, 8.06 4.78, 10.25 9.46 M10.78 8.72 C9.59 12.01, 6.28 16.2, 6.64 17.43 M10.86 9.36 C9.41 11.23, 8 13.4, 5.7 17.86 M6.16 16.97 C4.74 15.13, 3.49 12.62, 0.09 8.38 M6.49 18.13 C3.86 14.93, 2.24 12.43, -0.06 9.28 M0.7 9.12 C0.57 6.96, 2.87 5.83, 6.35 0.8 M-0.29 8.52 C2.67 5.74, 4.76 2.41, 5.87 -0.15" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2092.858531316122 681.3611920674642) rotate(0 49.333343505859375 88.66667175292969)"><path d="M24.67 0 M24.67 0 C36.56 0.22, 48.02 0.8, 74 0 M24.67 0 C37.94 0.12, 52.7 -0.39, 74 0 M74 0 C89.69 1.83, 98.82 8.94, 98.67 24.67 M74 0 C91.35 -1.52, 98.78 9.95, 98.67 24.67 M98.67 24.67 C100.47 74.37, 100.48 123.65, 98.67 152.67 M98.67 24.67 C97.41 49.96, 96.81 76.65, 98.67 152.67 M98.67 152.67 C98.57 169.12, 90.06 176.67, 74 177.33 M98.67 152.67 C98.08 167.28, 90.72 176.74, 74 177.33 M74 177.33 C64.08 176.08, 51.37 176.15, 24.67 177.33 M74 177.33 C61.66 176.6, 48.75 178.02, 24.67 177.33 M24.67 177.33 C7.28 178.26, 1.43 169.27, 0 152.67 M24.67 177.33 C6.39 178.76, 0.17 167, 0 152.67 M0 152.67 C0.5 103.92, -0.57 54.24, 0 24.67 M0 152.67 C-0.62 125.88, 0.07 98.03, 0 24.67 M0 24.67 C-1.98 6.49, 10.04 0.44, 24.67 0 M0 24.67 C-0.9 6.37, 7.71 -0.95, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1965.5252183278405 664.027879079183) rotate(0 34 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(void **)</text></g><g transform="translate(1733.191844304403 553.6944745381674) rotate(0 40 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_ptrs</text></g><g stroke-linecap="round" transform="translate(1663.1917832692468 545.3611920674642) rotate(0 136.66668701171875 22)"><path d="M1.27 -0.16 C102.13 1.34, 204.57 0.44, 272.95 1.55 M0.41 -0.32 C59.3 -1.97, 117.65 -1.45, 274.08 0.76 M274.2 -0.24 C274.71 10.88, 273.3 21.59, 274.56 44.91 M274.27 -0.69 C272.63 12.2, 273.47 24.77, 273.06 44.08 M274.65 45.21 C173.69 43.49, 70.68 46.37, 0.99 43.78 M272.63 44.12 C186.09 43.78, 98.49 43.09, -0.41 43.68 M1.33 42.36 C2.08 33.1, -0.22 19.91, 1.82 -1.27 M0.6 44.67 C-0.27 32.68, 1.07 22.17, 0.6 -0.53" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1676.191844304403 556.6945203145345) rotate(0 13.33331298828125 9.666671752929688)"><path d="M13.83 -0.12 C19.1 2.74, 21.67 5.03, 28.28 8.64 M13.66 0.37 C17.57 2.66, 21.87 6.65, 27.45 9.44 M26.48 10.76 C22.33 13.37, 17.78 18.36, 14.72 19.01 M26.12 9.28 C22.22 13.32, 18.02 16.43, 14.06 19.88 M15.31 20.8 C7.57 15.57, 5.93 14.18, -0.24 10.32 M14.13 19.35 C10.24 16.12, 5.4 13.31, -0.34 9.88 M-1.41 11.68 C5.24 6.89, 8.5 6.04, 12.91 -1.07 M0.58 9.58 C2.79 8.15, 6.25 5.43, 13.54 0.58" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2282.524974187216 618.7778027852377) rotate(0 24 14.5)"><path d="M-0.1 1.52 C17 -0.35, 35.5 0.63, 46.54 0.11 M-0.08 -0.6 C15.97 -1.39, 32 -0.41, 47.49 0.37 M49.26 -0.72 C47.54 4.2, 47.21 12.44, 47.6 29.64 M48.65 -0.69 C49.07 8.61, 47.17 19.56, 48.2 28.82 M49.26 27.67 C34.7 28.77, 19.25 27.11, -0.03 30.7 M48.3 29.54 C36.33 29.16, 26.74 28.35, -0.76 28.34 M0.18 29.58 C1.8 18.54, 0.81 11.48, 0.37 -0.2 M0.08 29.67 C-0.71 17.22, -0.61 5.89, 0.84 -0.35" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2306.524974187216 626.4444592793783) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.52 11.46 C3.39 8.61, 5.26 6.89, 7.68 4.76 M1.61 11.3 C3.82 8.54, 6.47 5.76, 7.45 3.78 M4.13 14.85 C7.2 11.6, 8.42 9.55, 10.85 7.55 M4.37 14.62 C5.63 11.97, 7.32 10.32, 10.26 7.27" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.77 -0.56 C7 2.2, 8.82 4.37, 10.72 9.3 M5.7 0.07 C6.87 2.64, 8.65 4.66, 10.85 8.55 M10.31 8.81 C8.42 11.08, 8.17 13.65, 6.31 17.89 M10.33 9.48 C8.64 11.48, 7.85 14.95, 5.91 17.57 M5.3 17.77 C3.97 13.53, 0.85 11.22, 0.89 8.2 M6.29 17.18 C4.4 15.63, 2.46 12.92, -0.35 9.1 M0.31 10.06 C1.4 6.35, 4.68 2.86, 5.89 0.94 M0.36 8.51 C1.04 6.49, 2.36 5.31, 5.81 0.38" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2282.1916001637783 651.9444287618002) rotate(0 24 14.5)"><path d="M-1.11 -0.57 C11.57 0.05, 23.07 -0.25, 48.59 -0.54 M0.15 -0.95 C19.15 0.32, 37.08 0.65, 47.11 -0.22 M47.61 -1.92 C47.45 8.83, 47.78 17.9, 48.46 29.72 M48.97 -0.76 C47.25 6.66, 48.39 11.51, 47.81 29.73 M48.19 29.24 C36.48 27.25, 28.49 30.38, -1.52 28.03 M47.08 28.91 C31.3 28.36, 13.34 28.6, 0.18 29.52 M1.95 27.77 C0.93 19.92, 0.34 8.79, 1.74 -1.4 M-0.91 28.44 C-0.83 18.46, 0.82 8.91, 0.71 -0.64" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2306.1916001637783 659.6110852559408) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.46 10.9 C3.38 9.12, 5.81 6.91, 8.55 4.65 M1.57 11.19 C3.81 8.87, 5.28 6.26, 8.15 4.37 M4.95 14.21 C5.27 13.15, 7.74 11.08, 9.88 8.26 M4.07 13.85 C5.97 11.86, 8.05 9.73, 9.75 7.42" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.71 -0.36 C7.66 1.94, 8.88 5.64, 10.39 9.93 M5.52 0.18 C7.32 2.36, 8.86 4.8, 10.56 8.99 M9.72 8.64 C9.04 11.94, 7.56 15.51, 6.35 16.7 M10.29 8.54 C9.31 12.31, 7.11 15.27, 6.36 17.19 M6.13 16.73 C3.13 14.51, 2.6 10.58, -0.51 9.56 M5.95 17.8 C3.5 14.35, 1.65 11.99, 0.27 9.24 M-0.67 9.52 C2.33 6.36, 3.58 4.32, 5.24 0.44 M-0.3 8.56 C1.43 6.74, 3.45 3.89, 5.66 -0.4" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2281.858287175497 685.2777722676595) rotate(0 24 14.5)"><path d="M-0.7 0.41 C16.59 0.25, 36.69 -0.41, 49.83 -0.16 M0.35 0.03 C11.03 0.82, 22.19 0.24, 47.98 0.63 M47.27 0.21 C47.54 8.29, 48.41 16.03, 46.03 30.29 M47.06 0.82 C48.49 6.52, 48.09 14.14, 47.03 29.63 M46.22 27.57 C36.76 30.75, 24.07 28.09, 1.06 29.59 M48.25 28.1 C30.23 28.29, 14.15 29.47, 0.45 29.09 M0.96 29.93 C0.09 19.26, 1.45 8.52, 0.81 0.16 M-0.81 28.33 C1.1 18.02, 0.97 7.1, -0.75 0.94" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2280.5249131520595 712.9444287618002) rotate(0 24 14.5)"><path d="M0.41 -1.46 C11.86 0.76, 22.94 2, 47.84 -1.19 M0.03 -0.51 C15.48 -1.06, 30 -0.19, 48.63 -0.36 M48.21 -0.4 C48.36 8.59, 48.44 14.29, 49.29 27.62 M48.82 0.2 C47.6 11.32, 48.51 22.06, 48.63 28.33 M46.57 28.97 C34.84 27.05, 17.33 29.64, 0.59 30.09 M47.1 28.24 C37.35 29.3, 28.54 29.57, 0.09 29.29 M0.93 29.37 C-0.02 19.2, -1.22 6.74, 0.16 1.33 M-0.67 29.84 C-0.18 23.65, -0.47 16.13, 0.94 -0.68" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2303.1916001637783 721.2777722676595) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.43 10.81 C4.04 9.96, 5.44 7.53, 7.28 4.94 M2.02 10.58 C2.9 9.64, 4.91 7.33, 7.71 4.38 M4.75 14.99 C6.55 11.45, 9.52 9.23, 10.43 8.19 M4 14.4 C5.67 12.07, 7.41 10.61, 10.23 7.31" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.26 0.06 C7.54 2.16, 9.43 4.8, 10.06 9.15 M5.74 0.19 C6.53 1.73, 7.93 4, 10.48 8.9 M10.47 9.31 C9.91 11.13, 7.76 13.18, 5.32 18.62 M10.77 8.91 C9.45 11.34, 8.01 13.24, 5.67 17.71 M5.98 18.56 C3.4 14.41, 2.89 12.53, 0.57 8.03 M5.6 17.32 C4.33 15.37, 2.73 12.62, 0.15 9.51 M0.2 8.89 C2.33 6.07, 3.25 4.77, 6.72 -0.98 M0.45 8.81 C1.92 6.5, 2.6 5.15, 5.63 -0.37" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2304.524974187216 690.1944745381674) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.78 11.55 C4.47 9.34, 5.58 6.26, 8.6 3.54 M1.55 10.57 C4.41 8.63, 5.9 5.81, 8.05 4.46 M4.94 14.34 C5.74 13.01, 7.85 10.53, 10.84 7.2 M4.35 14.06 C5.09 12.82, 6.69 11.56, 9.95 7.45" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.06 0.3 C6.98 3.35, 8.41 4.2, 10.82 8.03 M6.19 -0.45 C7.46 3.03, 9.45 5.88, 10.57 8.51 M10.98 9.23 C9.8 10.31, 8.85 12.88, 6.96 16.92 M10.58 8.91 C10.13 10.32, 9.12 12.26, 6.05 17.73 M6.89 16.87 C4.29 16.4, 3.84 14.58, -0.97 8.9 M5.65 17.76 C4.4 15.05, 2.23 12.15, 0.51 8.67 M-0.11 9.94 C1.29 6.29, 4.22 3.45, 5.02 -0.6 M-0.19 9.38 C1.03 6.58, 3.2 4.64, 5.63 -0.14" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(2254.191752751669 591.3611768086752) rotate(0 49.333343505859375 88.66667175292969)"><path d="M24.67 0 M24.67 0 C41.08 -0.57, 58.14 -0.19, 74 0 M24.67 0 C36.88 0.5, 47.88 0.84, 74 0 M74 0 C88.66 -0.44, 98.62 9.48, 98.67 24.67 M74 0 C89.62 -0.45, 96.46 7.38, 98.67 24.67 M98.67 24.67 C98.87 65.1, 96.44 105.39, 98.67 152.67 M98.67 24.67 C98.97 55.06, 100.11 83.65, 98.67 152.67 M98.67 152.67 C98.29 170.57, 88.5 178.59, 74 177.33 M98.67 152.67 C97.14 169.33, 90.72 175.29, 74 177.33 M74 177.33 C61.2 176.78, 52.5 178.34, 24.67 177.33 M74 177.33 C56.76 176.39, 38.27 176.63, 24.67 177.33 M24.67 177.33 C8.58 178.37, 0.9 169.29, 0 152.67 M24.67 177.33 C8.89 179.58, -1.42 170.21, 0 152.67 M0 152.67 C1.5 106.92, 0.57 64.14, 0 24.67 M0 152.67 C0.35 105.06, 2 58.45, 0 24.67 M0 24.67 C1.42 6.95, 6.73 1.88, 24.67 0 M0 24.67 C-1.56 6.65, 7.61 -0.57, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1926.191844304403 562.027879079183) rotate(0 178.01153459552688 28.13887480236599)"><path d="M0.46 -0.79 C59.4 8.68, 295.24 47.73, 354.51 57.07 M-0.76 1.4 C58.49 10.55, 297.37 46.39, 356.79 55.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1926.191844304403 562.027879079183) rotate(0 178.01153459552688 28.13887480236599)"><path d="M326.05 60.05 C340 60.39, 347.8 56.78, 358.11 57.16 M328.19 61.52 C335.82 60.39, 344.9 58.12, 357.6 55.22" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1926.191844304403 562.027879079183) rotate(0 178.01153459552688 28.13887480236599)"><path d="M329.13 39.76 C341.98 47.59, 348.64 51.47, 358.11 57.16 M331.27 41.23 C337.91 46.1, 346.09 49.82, 357.6 55.22" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(2067.658549626669 563.7611615498862) rotate(0 34 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(void **)</text></g><g stroke-linecap="round"><g transform="translate(2308.858470280966 732.6945660909017) rotate(0 -158.19461159479806 185.4654627719708)"><path d="M0.93 0.8 C-22.89 45.08, -90.46 203.94, -143.42 265.42 C-196.38 326.89, -287.73 352.33, -316.82 369.64 M-0.04 0.17 C-23.93 44.63, -91.19 204.88, -144.07 266.65 C-196.95 328.42, -288.33 353.55, -317.32 370.76" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(2308.858470280966 732.6945660909017) rotate(0 -158.19461159479806 185.4654627719708)"><path d="M-294.63 350.66 C-302.54 356.2, -307.73 359.79, -318.61 371.93 M-296.51 350.28 C-304.8 357.79, -313.66 365.71, -316.96 371.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(2308.858470280966 732.6945660909017) rotate(0 -158.19461159479806 185.4654627719708)"><path d="M-286.09 369.32 C-296.18 370.07, -303.59 368.8, -318.61 371.93 M-287.97 368.94 C-299.8 368.99, -312.06 369.46, -316.96 371.06" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(1464.858317693075 534.444627126058) rotate(0 24 14.5)"><path d="M1.33 0.31 C18.25 -0.2, 37.63 -0.27, 46.77 0.82 M-0.38 0.27 C9.73 0.02, 21.55 -0.68, 47.99 -0.43 M46.11 -0.69 C48.07 9.81, 48.19 21.08, 47.96 29.69 M48.08 0.72 C47.59 9.53, 49.07 19.8, 47.32 28.61 M48.98 27.99 C29.68 29.11, 10.74 30.01, 0.69 30.53 M48.96 29.95 C31.38 29.86, 13.88 29.28, -0.4 29.45 M-1.69 27.85 C-0.93 20.46, -0.33 14.9, -1.34 -0.41 M-0.29 28.44 C0.53 18.66, 0.14 8.54, -0.11 0.16" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1488.858317693075 542.1112836201986) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.52 10.19 C3.91 8.1, 6.51 5.68, 7.6 4.02 M1.59 10.64 C3.76 8.97, 5.93 6.89, 8.18 4.3 M5.06 13.46 C6.89 11.46, 7.2 10.38, 10.84 7.33 M4.04 14.08 C5.26 13.1, 6.3 11.48, 9.68 7.81" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.16 0.19 C7.25 2.93, 8.26 3.37, 11.08 8.2 M6.14 -0.45 C7.08 2.09, 7.73 3.87, 10.45 9.33 M10.33 9.09 C8.99 11.34, 8.11 13.39, 6.34 18.15 M11.02 8.68 C8.66 12.72, 6.95 15.27, 5.81 18.08 M5.47 17.7 C3.78 14.22, 2.03 11.63, 0.81 9.68 M6.5 18.13 C4.11 15.08, 1.66 11.3, 0.24 8.72 M-0.62 8.45 C0.96 6.38, 3.46 3.44, 5.78 0.54 M-0.3 9.38 C2 5.93, 4.19 2.45, 6.09 0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1464.5249436696374 567.6112531026205) rotate(0 24 14.5)"><path d="M0.37 0.25 C20.75 0.11, 36.53 0.75, 46.43 -1.72 M-0.9 0.13 C15.79 -0.7, 30.98 -0.57, 48.66 -0.43 M48.19 -0.8 C48.04 5.71, 47.68 12.41, 48.99 30.62 M47.36 -0.6 C48.86 10.36, 47.35 21.24, 48.83 29.71 M48.06 29.04 C32.36 29.7, 18.38 30.29, 1.29 30.17 M48.88 29.59 C31.81 29.47, 13.49 29.9, -0.53 28.72 M-1.01 27.62 C-0.16 22.86, -1.1 15.86, 1 1.23 M0.71 28.81 C0.4 17.98, -0.03 7.44, 0.06 0.97" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1488.5249436696374 575.2779095967611) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.76 10.58 C3.92 8.66, 5.17 6.8, 7.88 4.72 M1.95 11.11 C4.2 9.02, 6.11 6.76, 7.85 3.88 M4.95 13.59 C4.51 13.36, 7.3 11.38, 9.31 6.82 M3.97 14.57 C5.86 12.02, 7.95 9.85, 10.5 7.02" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.13 0.95 C7.82 2.67, 9.85 5.79, 9.79 9.23 M6.07 0.15 C6.96 2.4, 8.25 5.1, 10.45 8.5 M10.27 9.16 C9.6 10.76, 9.06 13.05, 6.8 18.38 M10.37 9.41 C9.06 11.31, 7.66 14.72, 6.35 17.74 M6.02 17.41 C4.44 15.01, 2.66 12.3, 0.62 9.58 M6.31 18.13 C3.55 14.08, 1.4 10.58, -0.15 8.58 M-0.75 8.78 C1.47 6.37, 2.42 5.69, 6.67 0.81 M-0.1 9.17 C1.59 6.46, 3.39 4.11, 6.52 0.18" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1464.1916306813562 600.9445966084799) rotate(0 24 14.5)"><path d="M1.87 0.18 C13.91 0.76, 28.7 -1.78, 48.46 -0.75 M0.3 -0.57 C15.7 -0.5, 32.07 -0.49, 47.02 -0.95 M48.32 -0.15 C47.99 8.39, 49.01 17.02, 49.46 29.17 M48.84 -0.46 C47.14 10.39, 48.64 22.28, 48.16 29.49 M47.51 29.94 C36.71 30.54, 25.32 30.18, 1.11 30.92 M48.87 29.01 C28.64 29.73, 9.54 29, -0.8 28.15 M-0.41 29.23 C-1.19 21.56, 1.15 16.17, 1.49 -0.58 M0.31 28.84 C-0.32 22.08, -0.14 15.81, 0.33 -0.05" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1462.8582566579187 628.6112531026205) rotate(0 24 14.5)"><path d="M0.18 -1.23 C16.1 -2.02, 28.84 0.01, 47.25 0.54 M-0.57 -0.01 C9.67 0.52, 19.77 -1.12, 47.05 -0.34 M47.85 -0.04 C48.58 9.97, 49.5 19.42, 48.17 30.44 M47.54 -0.68 C47.43 7.67, 48.54 13.84, 48.49 28.5 M48.94 29.69 C34.98 30.17, 20.07 29.99, 1.92 30.9 M48.01 28.6 C29.82 28.89, 10.46 28.62, -0.85 28.42 M0.23 27.66 C-0.21 22.76, 1.43 16.01, -0.58 -1.12 M-0.16 28.89 C0.21 18.3, 1.02 7.8, -0.05 -0.37" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1485.5249436696374 636.9445966084799) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.61 10.73 C3.51 9.01, 5.93 7.1, 7.24 3.62 M2.13 11.31 C3.93 8.72, 5.43 6, 8.18 3.69 M4.65 14.98 C6.38 10.91, 8.14 9.57, 9.78 7.12 M4.33 13.83 C5.96 13.03, 6.63 10.56, 10.06 7.32" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.38 0.42 C6.75 1.93, 9.23 5.24, 10.94 8.09 M6 -0.22 C7.82 2.62, 8.45 5.18, 10.49 9.05 M10.65 9.34 C9.95 12.04, 8.97 13.58, 6.71 17.04 M10.33 8.81 C10.03 11.41, 8.57 13.39, 5.75 17.68 M6.37 18.47 C4.89 15.69, 2.98 13.48, 1 9.93 M5.79 17.9 C3.49 14.41, 1.19 11, -0.3 8.73 M-0.73 8.78 C1.95 7.58, 3.6 4.52, 5.4 0.77 M-0.06 9.09 C1.69 7, 3.53 3.92, 5.8 -0.46" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1486.858317693075 605.8612988789877) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.7 10.81 C3.52 9.72, 5.16 6.76, 7.28 4.3 M2.28 11.09 C3.96 8.24, 5.52 6.48, 7.35 4.46 M4.93 14.12 C4.81 12.05, 7.4 10.83, 9.76 6.98 M3.78 14.6 C6.84 11.29, 8.22 9.18, 9.97 7.89" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.42 -0.8 C6.97 3.8, 9.3 7.39, 9.76 9.13 M5.78 0.33 C7.27 2.47, 8.55 5.76, 10.72 8.8 M11.01 9.49 C9.98 12.45, 7.8 15.18, 5.37 17.08 M10.47 9.41 C9.19 12.37, 7.29 15.37, 6.02 17.68 M6.81 18.35 C4.92 15.88, 3.66 13.91, 0.93 9.62 M6.24 17.39 C3.53 13.86, 0.91 10.63, -0.27 8.64 M-0.22 9.54 C2.33 7.33, 3.03 3.4, 6.77 -0.2 M0.09 9.03 C2.53 6.2, 3.96 2.84, 5.54 -0.04" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1436.525096257528 507.0280011494955) rotate(0 49.333343505859375 88.66667175292969)"><path d="M24.67 0 M24.67 0 C38.34 -1.92, 55.62 -0.95, 74 0 M24.67 0 C41.1 -0.63, 56.94 -0.5, 74 0 M74 0 C91.77 -0.86, 96.71 6.33, 98.67 24.67 M74 0 C89.65 0.22, 97.74 8.59, 98.67 24.67 M98.67 24.67 C99.63 63.71, 100.1 99.69, 98.67 152.67 M98.67 24.67 C98.68 71.81, 97.17 119.48, 98.67 152.67 M98.67 152.67 C100.33 170.53, 90.76 178.32, 74 177.33 M98.67 152.67 C97.51 169.18, 90.49 176.77, 74 177.33 M74 177.33 C58.18 178.88, 40.88 179.63, 24.67 177.33 M74 177.33 C55.38 177.64, 34.62 178.07, 24.67 177.33 M24.67 177.33 C7.16 176.77, -1.61 167.42, 0 152.67 M24.67 177.33 C6.9 176.17, -1.59 168.64, 0 152.67 M0 152.67 C1.86 114.04, 2.35 72.37, 0 24.67 M0 152.67 C-0.6 121.26, -1.02 90.34, 0 24.67 M0 24.67 C0.13 10.16, 8.88 -0.11, 24.67 0 M0 24.67 C-0.86 6.25, 8.07 2.05, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1492.8585618337 645.3613599141439) rotate(0 52.59395427841696 52.05072146447378)"><path d="M0.13 0.47 C17.65 11.2, 93.17 46.73, 104.49 63.92 C115.82 81.12, 74.33 96.82, 68.07 103.65 M-1.25 -0.34 C16.26 10.59, 92.67 47.61, 104.16 65.07 C115.65 82.53, 73.89 97.59, 67.69 104.44" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1492.8585618337 645.3613599141439) rotate(0 52.59395427841696 52.05072146447378)"><path d="M84.75 84.96 C78.6 89.59, 74.1 92.96, 68.08 103.59 M83.46 83.6 C77.87 90.56, 73.68 98.31, 68.42 104.24" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1492.8585618337 645.3613599141439) rotate(0 52.59395427841696 52.05072146447378)"><path d="M94.71 100.44 C86.14 101.23, 79.17 100.76, 68.08 103.59 M93.41 99.08 C84.24 100.67, 76.59 103.04, 68.42 104.24" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1690.1917527516687 688.694642384847) rotate(0 88.5 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> uint8 *load_addr;</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr"> uint64 load_size;</text></g><g stroke-linecap="round" transform="translate(1678.1918748219812 688.694642384847) rotate(0 128 19)"><path d="M0.57 -0.77 C63.53 1.49, 128.3 1.3, 257.41 0.99 M0.17 -0.72 C90.22 -0.63, 181.58 -0.54, 256.72 -0.49 M254.01 0.74 C257.68 6.94, 256.7 17.64, 255.48 38.8 M255.37 -0.45 C255.3 10.67, 256.74 22.37, 255.1 37.9 M255.97 36.84 C198.26 36.18, 138.84 35.9, 0.48 38.94 M256.67 38.09 C156.05 36.74, 57.3 36.37, -0.11 38.58 M-0.35 36.67 C0.47 27.67, 0.15 18.69, 0.57 1.18 M-0.33 37.7 C1.12 28.22, 1.24 17.58, 0.8 0.92" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(1698.8585007985437 692.694642384847) rotate(0 8.66668701171875 6.6666717529296875)"><path d="M8.6 0.47 C12.34 1.36, 14.09 4.25, 16.47 6.07 M8.78 -0.34 C12.05 2.55, 14.44 4.5, 17.86 6.8 M16.66 6.83 C15.02 10.08, 11.44 11.37, 8.04 13.41 M17.18 6.69 C13.62 9.42, 10.84 12.25, 8.69 13.2 M9.94 13.83 C6.92 10.3, 2.85 10.42, -0.83 8.08 M9.31 13.53 C6.7 11.46, 3.73 10.02, -0.4 7.15 M0.2 6.87 C1.35 6.06, 4.87 3.47, 9.98 -0.45 M-0.15 6.99 C2.98 4.5, 6.53 1.12, 8.7 0.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(1706.8585007985437 696.694642384847) rotate(0 -31.090329816178382 47.383988468069674)"><path d="M1.14 0.85 C-9.16 12.52, -59.07 55.54, -62.56 71.16 C-66.04 86.77, -27.14 90.63, -19.78 94.52 M0.29 0.24 C-10.04 12.12, -59.59 54.27, -63.1 69.64 C-66.61 85.01, -28.36 88.69, -20.78 92.46" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1706.8585007985437 696.694642384847) rotate(0 -31.090329816178382 47.383988468069674)"><path d="M-44.36 95.64 C-37.92 92.91, -33.03 94.79, -19.88 91.17 M-45.98 94.33 C-39.61 93.68, -30.81 92.07, -21.09 92.16" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(1706.8585007985437 696.694642384847) rotate(0 -31.090329816178382 47.383988468069674)"><path d="M-39.73 79.14 C-34.24 80.38, -30.45 86.18, -19.88 91.17 M-41.35 77.83 C-36.22 81.89, -28.73 84.96, -21.09 92.16" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(1290.0222428639734 1014.5390800476074) rotate(0 119 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMFunction (second module)</text></g><g transform="translate(1416.5252946217859 488.02792485555017) rotate(0 88 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::functions</text></g><g transform="translate(2219.674662907919 572.4278943379721) rotate(0 92.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::func_ptrs</text></g><g transform="translate(2060.2694276173916 637.7612073262534) rotate(0 80 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModule::</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">fast_jit_func_ptrs</text></g><g stroke-linecap="round" transform="translate(184.77769978841184 540.4275586446128) rotate(0 70.33334350585938 16.166656494140625)"><path d="M0.05 -1.29 C46.02 1.64, 91.97 2.01, 141.03 -1.96 M-0.93 0.88 C31.51 -1.18, 63.8 -1.49, 141.48 -0.85 M139.62 0.79 C141.05 9.44, 140.37 17.52, 141.53 32.51 M140.81 -0.98 C141.47 8.56, 140.73 14.95, 140.03 31.91 M142.19 33.52 C112.51 31.06, 84.41 29.96, 0.12 33.71 M140.27 33.1 C94.28 32.52, 47.52 31.51, 0.39 31.77 M1.65 34.22 C-1.84 22.92, -1.67 14.09, 1.49 0.51 M0.67 33.06 C0.27 23.06, -0.97 12.38, 0.01 -0.44" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(215.1110432942712 546.0942151387534) rotate(0 40 10)"><text x="40" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">func_ptrs</text></g><g stroke-linecap="round" transform="translate(195.44432576497434 552.760871632894) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.33 11.69 C2.6 8.64, 3.75 7.21, 6.87 4.66 M1.85 11.28 C3.75 8.94, 5.43 6.7, 7.33 4.44 M3.88 14.52 C6.61 11.51, 8.04 8.85, 9.72 7.38 M4.36 14.66 C5.88 12.01, 8.07 10.27, 9.76 7.6" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.84 0.12 C6.58 2.14, 8.05 2.64, 9.92 9.33 M5.86 -0.25 C7.65 2.69, 9.58 5.81, 10.64 9.3 M10.76 8.95 C9.42 10.03, 9.13 12.67, 5.42 18.33 M10.95 9.38 C8.75 12.09, 6.66 15.62, 5.52 17.86 M6.2 17.74 C5.17 15.45, 3.59 14.95, 0.29 8.84 M5.86 18.18 C4.09 15.57, 3.31 13.19, 0.03 9.33 M-0.88 9.26 C0.39 7.89, 3.26 5.43, 6.08 0.19 M0.18 9.35 C1.3 6.12, 3.65 3.16, 6.1 0.23" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(203.7777608235681 460.0940930684409) rotate(0 70 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">import_func_ptrs</text></g><g stroke-linecap="round" transform="translate(166.33329264322958 598.4274060567221) rotate(0 92.66670227050781 17.499984741210938)"><path d="M-0.48 0.83 C51.51 0.16, 97.16 1.25, 183.62 1.2 M0.05 0.2 C38.01 -0.05, 76.55 -0.09, 185.28 0.85 M185.94 -1.18 C185.56 11.41, 185.9 22.13, 183.51 35.27 M185.01 -0.61 C185 12.66, 185.71 27.21, 184.53 34.52 M184.14 36.78 C135.88 32.22, 90.61 32.2, -0.66 35.94 M184.46 34.32 C144.36 36.61, 103.99 35.88, 0.89 36 M1.53 35.39 C1.12 27.86, -0.46 18.36, 1.87 -1.4 M0.81 34.57 C-1.17 25.79, 0.49 18.21, -0.75 0.65" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(168.9999491373702 610.4274060567221) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.78 10.68 C2.84 9.52, 4.24 8.87, 7.23 3.92 M1.97 11.17 C4.2 8.57, 5.92 6.11, 7.65 4.48 M3.64 14.33 C5.19 12.75, 7.02 10.17, 9.82 6.66 M4.07 14.37 C5.78 12.42, 7.45 10.56, 9.9 7.23" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.98 -0.47 C6.11 2.24, 7.37 4.94, 9.71 9.74 M5.98 0.49 C7.88 3.66, 9.29 6.81, 10.83 9.46 M10.62 8.9 C9.19 11.46, 6.54 15.14, 6.76 17 M10.62 8.72 C9.79 11.49, 7.94 13.01, 5.81 17.86 M5.4 16.92 C5.69 14.99, 2.98 14.28, -0.86 8.11 M5.74 17.91 C3.71 14.34, 2.2 11.87, -0.27 9.5 M0.79 9.85 C1.91 6.34, 5.04 2.09, 5.31 0.82 M-0.49 8.5 C2.52 5.62, 3.88 2.83, 6.09 0.43" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(184.9999491373702 607.2607495625815) rotate(0 80 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">fast_jit_func_ptrs</text></g><g stroke-linecap="round" transform="translate(302.77745564778684 1048.1773984273277) rotate(0 24 14.5)"><path d="M-0.24 -1.15 C11.27 1.2, 24.56 -0.87, 48.84 -0.46 M-0.52 0.49 C11.26 -0.03, 23.48 -0.09, 47.96 0.87 M46.76 -1.74 C48.69 6.91, 46.24 11.11, 46.77 29.52 M47.12 0.1 C47.77 7.63, 48.85 14.96, 48.65 29.82 M47.82 27.17 C36.11 28.7, 24.45 30.51, 1.04 28.16 M47.5 29.15 C34.89 28.35, 22.29 29.69, -0.92 29.57 M-1.6 27.84 C0.23 21.46, 0.3 18.32, 0.01 0.17 M0.93 29.5 C-0.09 17.5, -1.18 6.44, -0.74 -0.11" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(326.77745564778684 1055.8440549214683) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.59 11.77 C4.19 8.64, 4.78 7.68, 7.87 3.3 M1.73 10.93 C2.98 9.16, 5.27 7.49, 7.66 4.47 M4.42 13.79 C6.66 12.17, 8.5 9.27, 9.96 7.03 M4.54 13.9 C6.29 12.14, 8.35 9.75, 10.4 7.54" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.42 -0.26 C7.5 2.8, 7.64 5.01, 10.43 8.35 M6.25 -0.03 C7.08 2.31, 8.01 3.72, 11.11 8.62 M9.81 9.4 C9.74 10.38, 7.42 12.79, 6.26 17.15 M10.72 8.79 C9.13 12.44, 7.5 15.59, 6.4 17.33 M5.03 17.24 C4.33 15.08, 4 14.52, -0.44 8.73 M6.08 17.69 C3.82 15.37, 2.74 11.97, 0.3 8.54 M-0.63 9.04 C0.74 6.92, 3.86 4.65, 6.09 0.82 M0.27 9.1 C2.01 4.92, 4.27 1.49, 5.94 -0.35" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(302.44408162434934 1081.3440244038902) rotate(0 24 14.5)"><path d="M-0.51 0.78 C11.19 -1.01, 21.24 -0.19, 46.72 -1.87 M-0.06 0.15 C17.13 -0.14, 32.52 0.64, 47.24 -0.45 M48.82 0.41 C46.19 8.77, 46.59 21.83, 46.96 30.28 M47.58 0.44 C48.41 7.48, 48.4 14.6, 47.31 28.13 M47.18 28.36 C28.81 29.73, 13.46 27.72, -0.52 28.98 M48.04 28.29 C33.6 29.71, 17.08 29.65, -0.86 28.45 M0.07 27.65 C0.37 21.96, 0.24 11.68, 1.51 1.84 M0.18 28.39 C-1.18 19.12, -1.01 10.7, -0.65 0.5" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(326.44408162434934 1089.0106808980308) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.6 10.51 C3.03 9.69, 4.94 6.63, 7.43 4.44 M1.44 11 C4.41 8.57, 6.21 6.16, 7.8 4.33 M4.86 14.32 C7.02 11.07, 8.38 8.86, 10.32 6.77 M4.33 14.32 C6 12.36, 7.6 10.75, 10.17 7.64" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.4 0.51 C6.64 3.03, 8.4 4.54, 9.72 9.4 M6.08 0.43 C7.25 2.22, 8.8 4.09, 10.44 9.34 M10.87 8.2 C8.55 10.48, 8.63 12.63, 6.63 17.05 M10.88 9.33 C9.97 11.14, 9.09 12.32, 5.57 18.01 M5.66 16.93 C4.95 15.67, 2.15 12.33, -0.01 9.13 M5.63 17.98 C4.82 15.02, 3.29 12.88, -0.29 9.01 M-0.73 9.08 C2.3 7.02, 2.78 5.86, 7 0.15 M-0.33 8.51 C1.89 5.05, 4.61 1.56, 6.27 -0.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(302.1107686360681 1114.6773679097496) rotate(0 24 14.5)"><path d="M1 -1.29 C12.47 -0.65, 21.98 -2.06, 48.78 -1.03 M0.85 0.09 C16.7 0.8, 32.73 -0.52, 48.67 -0.62 M46.37 -1.89 C46.89 6.7, 47.07 13.64, 46.75 27.25 M48.66 0.59 C48.53 9.81, 47.19 17.12, 48.71 28.91 M46.6 30.17 C39.04 28.01, 27.48 28.82, 0.25 28 M48.6 29.63 C31.94 29.23, 16.86 28.11, 0.02 28.2 M0.14 30.71 C0 22.16, 1.5 16.82, 0.28 1.86 M-0.91 28.22 C-0.79 18.74, -0.7 9.2, -0.12 -0.06" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(300.7773946126306 1142.3440244038902) rotate(0 24 14.5)"><path d="M-1.29 0.84 C12.7 -1.52, 24.46 0.54, 46.97 0.98 M0.09 -0.04 C14.99 -1.17, 27.79 0.27, 47.38 -0.87 M46.11 -1.23 C48.58 8.84, 49.34 18.53, 46.25 29.21 M48.59 0.65 C48.94 6.79, 47.25 15.67, 47.91 28.08 M49.17 30.04 C34.73 28.15, 23.1 28.91, -1 29.31 M48.63 28.08 C33.96 28.43, 18.23 29.3, -0.8 28.42 M1.71 29.01 C0.36 21.71, 2.04 11.68, 1.86 1 M-0.78 28.26 C0.07 19.13, 0.68 10.44, -0.06 -0.9" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(323.44408162434934 1150.6773679097496) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.42 11 C3.35 7.97, 6.76 6.37, 7.51 4.19 M2.09 10.79 C3.46 9.45, 4.56 8.27, 7.86 3.85 M3.48 14.11 C5.97 11.9, 7.91 8.86, 10.77 6.76 M4.08 14.54 C6.2 12.06, 8.23 9.49, 10.48 7.28" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.43 -0.23 C6.98 2.13, 9.61 5.61, 11.16 8.94 M5.98 0.44 C7.16 2.61, 9.36 5.36, 10.23 9.21 M10.06 9.26 C8.59 12.36, 6.99 13.65, 6.1 17.25 M10.99 9.4 C8.78 11.58, 7.86 14.95, 5.55 17.47 M6.55 17.23 C4.18 15.37, 2.98 12.53, 0.16 9.05 M5.52 17.97 C4.12 15.43, 3.21 13.31, -0.31 9.02 M0 9.09 C2.21 7.85, 2.94 5.77, 6.54 0.19 M-0.4 8.94 C1.17 7.16, 2.89 4.71, 5.51 0.32" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(324.77745564778684 1119.5940701802574) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.97 10.09 C3.08 9.43, 5.61 7.08, 7.85 3.29 M1.76 11.27 C3.78 8.86, 5.97 6.5, 7.51 4.41 M4.06 13.82 C6.18 11.53, 7.48 10.8, 9.4 7.7 M4.49 14.33 C6.08 12.32, 7.56 10.4, 9.93 7.2" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.77 -0.65 C6.62 3.53, 8.68 6.77, 10.61 9.16 M6.44 -0.38 C7.58 3.81, 9.28 6.48, 10.87 9.1 M10.92 8.49 C10.2 10.25, 7.68 12.86, 5.59 18.1 M11.07 8.66 C8.58 12.55, 7.26 14.92, 5.8 17.51 M5.56 17.39 C4.56 15.84, 2.66 13.87, 0.05 8.25 M6.3 17.21 C3.49 14.5, 1.2 11.06, 0.02 8.65 M0.09 9.82 C2.76 6.39, 4.61 4.02, 6.19 -0.66 M-0.06 8.65 C1.59 7.1, 2.54 4.8, 6.32 -0.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(274.44423421223996 1037.094207509359) rotate(0 49.333343505859375 80.49995422363281)"><path d="M24.67 0 M24.67 0 C35 -1.76, 48.68 -0.92, 74 0 M24.67 0 C42.72 0.02, 59.04 0.79, 74 0 M74 0 C88.93 -0.9, 100.01 6.98, 98.67 24.67 M74 0 C88.44 0.94, 99.14 6.35, 98.67 24.67 M98.67 24.67 C96.94 48.92, 96.73 68.86, 98.67 136.33 M98.67 24.67 C98.86 59.9, 98.85 94.78, 98.67 136.33 M98.67 136.33 C97.28 151.03, 91.86 160.82, 74 161 M98.67 136.33 C96.56 151.84, 89.71 159.39, 74 161 M74 161 C55.79 160.77, 38.87 159.8, 24.67 161 M74 161 C59.05 161.28, 41.97 161.22, 24.67 161 M24.67 161 C6.49 159.89, 0.03 151.18, 0 136.33 M24.67 161 C6.88 161.08, -1.55 152.94, 0 136.33 M0 136.33 C1.51 95.14, 0.27 52.12, 0 24.67 M0 136.33 C-1.11 96.47, -0.94 58.05, 0 24.67 M0 24.67 C-1.3 9.22, 7.98 -0.12, 24.67 0 M0 24.67 C-2.06 9.6, 7.83 2.3, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(257.7778065999353 997.4275357564292) rotate(0 87 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance::</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">fast_jit_func_ptrs</text></g><g stroke-linecap="round"><g transform="translate(173.99997965494833 619.262046716285) rotate(0 5.143713119950576 215.89068972666576)"><path d="M0.15 -0.88 C-14.33 17.3, -79.65 63.13, -86.74 110.18 C-93.83 157.23, -73.31 227.83, -42.41 281.42 C-11.51 335, 74.85 406.64, 98.65 431.71 M-1.24 1.27 C-15.81 20.13, -80.81 64.61, -87.26 111.47 C-93.72 158.32, -70.89 228.89, -39.96 282.43 C-9.03 335.96, 75.11 407.71, 98.3 432.66" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(173.99997965494833 619.262046716285) rotate(0 5.143713119950576 215.89068972666576)"><path d="M69.48 421.7 C78.71 422.7, 87 426.04, 97.82 433.65 M70.46 421.01 C78.58 422.93, 86.34 427.1, 97.87 432.6" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(173.99997965494833 619.262046716285) rotate(0 5.143713119950576 215.89068972666576)"><path d="M83.79 407 C88.73 412.56, 92.6 420.44, 97.82 433.65 M84.77 406.3 C88.85 412.55, 92.52 420.92, 97.87 432.6" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(470.110753377279 1150.0106656392418) rotate(0 24 14.5)"><path d="M-1.02 0.64 C11.18 -0.82, 20.53 -0.68, 48.3 -0.58 M0.66 -0.1 C17.6 0.21, 33.99 -0.69, 48.74 0.38 M49.07 -0.58 C48.32 9.55, 48.12 19.02, 46.36 29.15 M48.17 0.93 C48.49 5.37, 47.79 12.06, 47.16 29.64 M47.94 27.79 C36.37 28.31, 24.36 28.98, -0.08 28.08 M48.13 28.51 C33.17 28.4, 18.68 29.45, -0.64 28.21 M-1.72 30.48 C1.64 18.29, 0.67 12.31, -0.36 0.13 M0.55 29.25 C-0.27 23.23, 0.51 17.4, 0.97 0.26" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(494.110753377279 1157.6773221333824) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.91 10.67 C3.09 9.37, 5.66 8.11, 7.38 4.68 M1.63 10.57 C4.41 7.89, 6.1 5.34, 8 4.25 M3.42 14.79 C6.92 12.4, 9.18 8.94, 9.37 7.43 M4.01 13.83 C5.42 12.72, 6.47 11.34, 10.37 7.62" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.32 0.65 C6.5 2.73, 7.79 4.85, 10.37 9.5 M5.95 0.42 C7.77 2.92, 8.73 5.81, 10.86 8.97 M10.38 9.02 C9.32 12.38, 7.93 15.08, 6.07 16.72 M11.13 9.15 C8.69 11.98, 7.37 14.93, 6.31 17.32 M5.36 17.34 C3.97 13.99, 2.38 11.99, -0.48 9.08 M5.74 17.64 C4.38 15.92, 3.63 13.58, -0.42 9.06 M0.8 10.03 C1.4 6.06, 5.39 1.87, 6.07 -1.06 M0.13 8.74 C1.37 7.05, 2.79 5.32, 6.14 0.11" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(469.7773793538415 1183.1772916158043) rotate(0 24 14.5)"><path d="M1.28 -1.24 C10.95 -1.25, 20.76 -0.74, 48.99 0.07 M0.82 0.56 C18.36 -0.29, 36.58 0.43, 47.94 0.96 M48.04 1.03 C48 10.33, 46.52 16.87, 46.07 30.31 M48.3 -0.53 C47.65 8.5, 47.21 17.1, 47.29 29.25 M47.38 28.72 C36.06 29.1, 27.28 27.79, 0.16 27.33 M47.95 28.4 C33.75 29.21, 18.38 27.97, 0.12 29.88 M1.9 27.35 C1.17 20.61, -0.11 9.51, -1.95 -1.37 M-0.47 29.1 C0.16 18.24, 0.81 7.47, 0.2 0.27" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(493.7773793538415 1190.843948109945) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.6 11.13 C4.15 9.91, 4.55 7.96, 8.49 3.24 M2.08 10.55 C3.85 7.97, 6.76 5.76, 8.09 4.39 M4.74 14.99 C6.91 11.67, 7.67 9.42, 9.34 6.68 M4.1 14.18 C5.76 12.18, 8.19 10.22, 10.05 7.33" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.37 0.37 C6.63 2.36, 8.06 4.96, 10.7 9.74 M6.28 0.22 C7.53 3.63, 9.6 6.51, 11.15 8.94 M11.17 8.92 C9.96 11.26, 7.42 14.18, 6.65 17.51 M10.41 8.8 C9.4 11.35, 8.1 14.17, 6.12 17.25 M5.85 16.81 C4.48 15.03, 2 12.58, -0.88 9.02 M5.68 17.79 C4.39 14.61, 1.86 12.3, 0.47 9.2 M-0.89 9.5 C1.98 6.83, 2.57 4.04, 5.26 0.82 M0.05 9.17 C2.18 6.36, 4.38 2.74, 6.15 0.52" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(469.4440663655603 1216.5106351216637) rotate(0 24 14.5)"><path d="M0.72 -1.1 C16.23 -0.29, 32.85 0.37, 49.47 1.32 M0.44 -0.34 C14.66 0.11, 27.77 0.69, 47.88 0.53 M47.84 1.97 C46.37 8.01, 46.07 17.04, 47.68 29.35 M47.6 0.27 C47.25 12.05, 47.38 23.07, 47.15 28.97 M46.38 29.39 C36.43 28.02, 25.17 27.27, 0.04 29.27 M48.24 29.44 C35.3 27.92, 23.99 29.59, 0.38 28.14 M0.92 30.42 C-0.63 18.28, -2.23 5.94, 1.51 1.11 M0.32 29.14 C1.11 19.84, 0.33 10.44, 0.96 0.73" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(468.1106923421228 1244.1772916158043) rotate(0 24 14.5)"><path d="M-1.1 0.3 C16.88 0.81, 34.99 1.29, 49.32 -0.2 M-0.34 0.74 C18.74 -0.27, 37.66 -0.33, 48.53 -0.29 M49.97 -1.64 C48.3 6.83, 49.46 17.21, 48.35 30.87 M48.27 -0.84 C48.48 8.87, 48.1 18.29, 47.97 28.39 M48.39 28.92 C34.16 28.77, 20.49 28.65, 0.27 28.03 M48.44 28.36 C33.04 29.23, 20.55 29.5, -0.86 29.74 M1.42 28.64 C0.37 15.59, -1.13 7.6, 1.11 0.49 M0.14 29.97 C0.23 21.87, 0.24 15.3, 0.73 -0.79" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(490.7773793538415 1252.5106351216637) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M2.62 10.51 C4.03 9.72, 4.2 7.95, 7.33 3.48 M1.56 11.13 C4.14 8.87, 6.36 6.36, 7.36 4.35 M4.04 13.51 C6.24 11, 7.61 9.45, 9.72 6.62 M4.2 14.51 C6.01 12.35, 7.35 10.97, 10.3 7.51" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M6.15 -0.3 C7.64 2.2, 9 4.98, 10.56 9.83 M6.38 0.19 C7.67 3.7, 9.3 6.69, 10.52 9.01 M9.86 9.07 C8.07 12.74, 7.22 15.31, 6.92 17.96 M10.25 9.31 C9.13 11.28, 7.91 13.28, 5.7 17.51 M5.96 17.18 C4.44 14.32, 2.66 12.87, -0.51 8.95 M5.66 17.25 C4.61 16.08, 3.31 13.09, 0.39 9.5 M-0.19 9.07 C0.21 6.26, 3.39 5.64, 6.27 -0.51 M0.53 9.14 C1.94 6.35, 4.21 3.81, 5.57 0.44" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(492.110753377279 1221.4273373921715) rotate(0 5.333343505859375 8.833328247070312)"><path d="M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M6.04 -0.05 C6.04 -0.05, 6.04 -0.05, 6.04 -0.05 M1.48 11.47 C4.47 7.75, 6.48 5.95, 7.14 4.56 M2.1 11.04 C3.58 9.68, 4.8 7.45, 8.01 4.35 M3.46 14.22 C5.64 10.89, 8.78 8.7, 9.26 7.25 M4.46 14.42 C5.86 12.2, 8.03 10.59, 10.16 7.07" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M5.7 0.5 C7.55 3.76, 9.76 5.94, 11.5 9.57 M6.19 -0.03 C8.06 3, 9.45 6.01, 10.68 9.26 M10.74 8.05 C10.03 11.34, 8.2 14.95, 6.3 17.15 M10.98 8.65 C9.6 10.79, 8.25 13.16, 5.85 17.6 M5.52 17.75 C3.79 15.79, 3.5 13.36, -0.05 8.36 M5.58 17.73 C4.49 15.03, 1.63 12.41, 0.5 8.56 M0.07 7.94 C1.27 6.71, 4.69 3.05, 5.49 0.1 M0.14 9.11 C2.12 6.48, 4.36 2.55, 6.44 -0.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(441.77753194173215 1138.927474721273) rotate(0 49.333343505859375 80.49995422363281)"><path d="M24.67 0 M24.67 0 C37.74 0.21, 50.3 1.46, 74 0 M24.67 0 C39.41 -0.61, 54.01 0.11, 74 0 M74 0 C90.32 1.91, 98.43 9.29, 98.67 24.67 M74 0 C89.78 0.05, 99.85 8.04, 98.67 24.67 M98.67 24.67 C95.82 70.46, 97.43 113.98, 98.67 136.33 M98.67 24.67 C98.6 68.86, 98.16 113.17, 98.67 136.33 M98.67 136.33 C97.25 153.28, 88.74 160.94, 74 161 M98.67 136.33 C97.27 152.07, 90.12 159.13, 74 161 M74 161 C58.39 159.11, 42.51 161.04, 24.67 161 M74 161 C61.84 161.14, 48.56 159.91, 24.67 161 M24.67 161 C8.47 162.77, 0.77 151.05, 0 136.33 M24.67 161 C9.93 163.19, -1.9 153.84, 0 136.33 M0 136.33 C-1.75 93.55, 1.71 54.61, 0 24.67 M0 136.33 C0.84 100.21, 1.5 64.07, 0 24.67 M0 24.67 C0.39 8.76, 10.15 1.47, 24.67 0 M0 24.67 C-1.81 10.08, 7.01 -2.08, 24.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(425.11110432942746 1099.2608029683433) rotate(0 87 20)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance::</text><text x="0" y="34" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">func_ptrs</text></g><g stroke-linecap="round" transform="translate(328.33328247070347 771.983044687907) rotate(0 37.3333740234375 80.49995422363281)"><path d="M18.67 0 M18.67 0 C30.32 0.2, 41.1 -1.67, 56 0 M18.67 0 C31.8 -0.64, 46.18 0.57, 56 0 M56 0 C68.28 -0.52, 75.66 7.68, 74.67 18.67 M56 0 C67.86 1.16, 73.13 5.5, 74.67 18.67 M74.67 18.67 C75.64 57.8, 74.63 96.69, 74.67 142.33 M74.67 18.67 C74.4 45.3, 72.86 71.04, 74.67 142.33 M74.67 142.33 C75.73 153.47, 67.22 161.5, 56 161 M74.67 142.33 C72.61 154.57, 68.38 161.76, 56 161 M56 161 C47.61 162.53, 35.51 162.67, 18.67 161 M56 161 C44.43 161.72, 31.8 160.5, 18.67 161 M18.67 161 C8.22 159.75, 0.69 154.88, 0 142.33 M18.67 161 C7.57 161.64, 0.05 156.09, 0 142.33 M0 142.33 C-1.57 108.84, 1.47 77.26, 0 18.67 M0 142.33 C0.49 112.05, 1.56 80.8, 0 18.67 M0 18.67 C0.99 8.01, 4.32 -0.81, 18.67 0 M0 18.67 C1.88 7.43, 7.45 1.79, 18.67 0" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(202.44444783528684 560.9274213155112) rotate(0 42.970853330900354 325.633728864521)"><path d="M-0.66 -0.88 C-25.5 29.73, -151.06 81.25, -148.34 183.6 C-145.63 285.95, -48.26 538.11, 15.63 613.22 C79.51 688.33, 198.07 631.04, 234.98 634.26 M1.2 1.27 C-23.82 32.05, -151.29 83.21, -149.01 184.88 C-146.72 286.55, -49.05 536.77, 14.9 611.29 C78.84 685.81, 197.81 628.51, 234.69 632.01" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(202.44444783528684 560.9274213155112) rotate(0 42.970853330900354 325.633728864521)"><path d="M206.95 647.41 C217.07 641.52, 228.71 634.47, 235.67 633.8 M208.94 647.04 C214.63 643.15, 218.33 641.21, 235.44 633" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(202.44444783528684 560.9274213155112) rotate(0 42.970853330900354 325.633728864521)"><path d="M203.78 627.13 C215.04 628.59, 227.82 628.87, 235.67 633.8 M205.78 626.76 C212.03 627, 216.38 629.21, 235.44 633" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(494.4444274902346 1230.03844426473) rotate(0 671.8436045117085 -44.75660807210909)"><path d="M0.54 0.8 C132.51 5.04, 566.85 44.81, 790.81 24.7 C1014.77 4.59, 1252.14 -96, 1344.32 -119.86 M-0.64 0.17 C131.34 4.15, 566.17 42.83, 790.29 23.01 C1014.41 3.19, 1251.72 -94.84, 1344.08 -118.76" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(494.4444274902346 1230.03844426473) rotate(0 671.8436045117085 -44.75660807210909)"><path d="M1321.64 -99.11 C1326.9 -102.86, 1329.97 -107.51, 1345.67 -119.95 M1320.75 -99.8 C1325.5 -103.62, 1331.23 -108.24, 1343.26 -118.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(494.4444274902346 1230.03844426473) rotate(0 671.8436045117085 -44.75660807210909)"><path d="M1315.43 -118.67 C1321.91 -118.23, 1326.31 -118.67, 1345.67 -119.95 M1314.54 -119.36 C1320.69 -118.97, 1327.73 -119.42, 1343.26 -118.47" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g transform="translate(139.33328247070358 990.0384951273599) rotate(0 34 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">(void **)</text></g><g transform="translate(705.6110432942712 860.5385459899893) rotate(0 123 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#e67700" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance(second)</text></g><g stroke-linecap="round" transform="translate(695.7777506510422 883.4830192565909) rotate(0 135.3333180745442 97.11112467447924)"><path d="M-0.25 -0.49 C95.45 -1.51, 189.5 -1.32, 270.96 -0.07 M0.65 0.19 C88.75 -1.22, 176.2 -1.59, 270.94 0.57 M270.94 -1.72 C272.84 43.45, 272.7 86.02, 272.43 194.12 M270.78 0.53 C270.4 68.8, 271.15 138.06, 270.76 195.22 M269.26 195.34 C175.45 194.3, 83.34 194.34, 0.55 195.64 M271.45 194.24 C207.22 192.82, 144.97 192.65, 0.31 193.59 M0.51 192.67 C-0.52 145.85, 0.75 94.24, 0.52 -1.68 M0.66 193.97 C-0.23 152.47, 0.38 110.22, -0.59 -0.09" stroke="#d9480f" stroke-width="4" fill="none"></path></g><g transform="translate(32.22234090169263 1266.3721336364733) rotate(0 167.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">function pointer arrays for faster access</text></g><g stroke-linecap="round" transform="translate(10 1241.1498435974108) rotate(0 182.2222137451172 29.166692097981695)"><path d="M14.58 0 M14.58 0 C128.71 -1.41, 243.05 -1.09, 349.86 0 M349.86 0 C358.99 1.29, 362.45 3.19, 364.44 14.58 M364.44 14.58 C364.9 22.67, 362.68 33.54, 364.44 43.75 M364.44 43.75 C366.03 54.77, 358.05 60.18, 349.86 58.33 M349.86 58.33 C278.65 59.1, 206.11 57.35, 14.58 58.33 M14.58 58.33 C3.38 59.38, -1.74 54.99, 0 43.75 M0 43.75 C1.12 37.17, -0.41 31.13, 0 14.58 M0 14.58 C0.29 5.6, 3.11 -1.39, 14.58 0" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g stroke-linecap="round"><g transform="translate(375.5555725097656 1281.1498944600412) rotate(0 32.00485023098685 -10.063405875737544)"><path d="M1.15 -0.8 C11.76 -4.03, 52.31 -16.05, 62.86 -19.33" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(375.5555725097656 1281.1498944600412) rotate(0 32.00485023098685 -10.063405875737544)"><path d="M37.53 -2.12 C44.56 -3.79, 48.14 -8.28, 64.21 -18.16" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(375.5555725097656 1281.1498944600412) rotate(0 32.00485023098685 -10.063405875737544)"><path d="M31.58 -21.76 C40 -18.96, 44.95 -18.93, 64.21 -18.16" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(217.77776082356775 1240.03874944051) rotate(0 28.512432670220733 -21.582885223254607)"><path d="M0.55 1.05 C10.14 -6.2, 47.18 -36.37, 56.48 -44.21" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(217.77776082356775 1240.03874944051) rotate(0 28.512432670220733 -21.582885223254607)"><path d="M43.02 -16.81 C45.97 -22.62, 46.17 -28.42, 55.79 -43.5" stroke="#000000" stroke-width="1.5" fill="none"></path></g><g transform="translate(217.77776082356775 1240.03874944051) rotate(0 28.512432670220733 -21.582885223254607)"><path d="M29.96 -32.64 C35.57 -35.14, 38.55 -37.59, 55.79 -43.5" stroke="#000000" stroke-width="1.5" fill="none"></path></g></g><mask></mask></svg> \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.excalidraw b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.excalidraw
new file mode 100644
index 000000000..947153520
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.excalidraw
@@ -0,0 +1,2313 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
+ "elements": [
+ {
+ "type": "rectangle",
+ "version": 381,
+ "versionNonce": 2068900405,
+ "isDeleted": false,
+ "id": "D5Ay5TxydaAe4f80l_79L",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 982.833251953125,
+ "y": 298.00006103515625,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 99.666748046875,
+ "height": 211.00007629394523,
+ "seed": 1123866381,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "5S0qe2-BjQRPwuEEQ_UsU",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679660991439,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 317,
+ "versionNonce": 1880855285,
+ "isDeleted": false,
+ "id": "4JTzPDASWmnx1PVSabO3A",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 914.833251953125,
+ "y": 236.3333282470703,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 103,
+ "height": 20,
+ "seed": 422161475,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661135316,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "global_data:",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "global_data:"
+ },
+ {
+ "type": "text",
+ "version": 183,
+ "versionNonce": 1437992789,
+ "isDeleted": false,
+ "id": "HQjUeFzLlihuH1Lf8XZQq",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 528.1666870117188,
+ "y": 324.00001525878906,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 274,
+ "height": 20,
+ "seed": 2018585571,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661163124,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstanceExtra::globals",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstanceExtra::globals"
+ },
+ {
+ "type": "arrow",
+ "version": 453,
+ "versionNonce": 92905717,
+ "isDeleted": false,
+ "id": "I86Qg5wzdmE77J5SbA7HP",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 759.0470523835444,
+ "y": 472.4753157819668,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 223.44867715016005,
+ "height": 152.25013181880155,
+ "seed": 661894701,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Qm7oDN7yJzVFQrCa0EE1G"
+ }
+ ],
+ "updated": 1679660991440,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "Sd34CflTFN9Elv1dedCI1",
+ "focus": 0.9595350520837825,
+ "gap": 4.004209431139316
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 223.44867715016005,
+ -152.25013181880155
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 4,
+ "versionNonce": 2089047221,
+ "isDeleted": false,
+ "id": "Qm7oDN7yJzVFQrCa0EE1G",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 844.2713909586244,
+ "y": 386.350249872566,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 53,
+ "height": 20,
+ "seed": 1720249052,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661201718,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "offset",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "I86Qg5wzdmE77J5SbA7HP",
+ "originalText": "offset"
+ },
+ {
+ "type": "rectangle",
+ "version": 213,
+ "versionNonce": 1454183483,
+ "isDeleted": false,
+ "id": "Sd34CflTFN9Elv1dedCI1",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 986.4999389648438,
+ "y": 315.6666564941406,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 91.66668701171875,
+ "height": 27.999999999999996,
+ "seed": 357984397,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "I86Qg5wzdmE77J5SbA7HP",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679660991440,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 192,
+ "versionNonce": 706008283,
+ "isDeleted": false,
+ "id": "X5nXXDxRcZputNDZp2WfW",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 984.4998779296875,
+ "y": 350.83333587646484,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 94.3333740234375,
+ "height": 19.333358764648438,
+ "seed": 1611395779,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "PFkOKGbMOcdhcpcv4DutQ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679660991442,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 369,
+ "versionNonce": 1307818581,
+ "isDeleted": false,
+ "id": "PFkOKGbMOcdhcpcv4DutQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 753.8716651262948,
+ "y": 690.3334503173828,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 220.3341412661283,
+ "height": 341.60985534904495,
+ "seed": 1747362403,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "MPb6tVMlSBtnXhUTpZvIC"
+ }
+ ],
+ "updated": 1679660991442,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "X5nXXDxRcZputNDZp2WfW",
+ "gap": 5.794568769140314,
+ "focus": 1.2182487723741706
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 220.3341412661283,
+ -341.60985534904495
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 4,
+ "versionNonce": 1008745755,
+ "isDeleted": false,
+ "id": "MPb6tVMlSBtnXhUTpZvIC",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 837.538735759359,
+ "y": 509.52852264286037,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 53,
+ "height": 20,
+ "seed": 1880081892,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661201719,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "offset",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "PFkOKGbMOcdhcpcv4DutQ",
+ "originalText": "offset"
+ },
+ {
+ "type": "text",
+ "version": 429,
+ "versionNonce": 147921333,
+ "isDeleted": false,
+ "id": "5GnY6Vq9qPDS0ntZW3UOE",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 917.166748046875,
+ "y": 259.3333282470703,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 197,
+ "height": 20,
+ "seed": 1179957165,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661138960,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "hold values of GLOBALs",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "hold values of GLOBALs"
+ },
+ {
+ "type": "rectangle",
+ "version": 234,
+ "versionNonce": 339097851,
+ "isDeleted": false,
+ "id": "FcG2LCAdKxw_z2SzLhPPr",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 548.3333129882812,
+ "y": 351.666748046875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 228.66668701171866,
+ "height": 299.66668701171875,
+ "seed": 407083364,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "_acaSZ2N5FSiuPGQjH8RA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679660870990,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 182,
+ "versionNonce": 1735336804,
+ "isDeleted": false,
+ "id": "OdBdX2K4Kcn9Hq7vInwKA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 571,
+ "y": 387.3333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 190,
+ "height": 30,
+ "seed": 175211612,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "OZDTfM4SDGXEVbxgCAbsx"
+ }
+ ],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 135,
+ "versionNonce": 1695691996,
+ "isDeleted": false,
+ "id": "OZDTfM4SDGXEVbxgCAbsx",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 621.5,
+ "y": 392.3333740234375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 89,
+ "height": 20,
+ "seed": 1994750564,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint8 type;",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "OdBdX2K4Kcn9Hq7vInwKA",
+ "originalText": "uint8 type;"
+ },
+ {
+ "type": "text",
+ "version": 174,
+ "versionNonce": 2063524661,
+ "isDeleted": false,
+ "id": "w5el7zqw5vcK9RGIcDlFZ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 580.9999389648438,
+ "y": 357.8333435058594,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 171,
+ "height": 19,
+ "seed": 1831729636,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "_acaSZ2N5FSiuPGQjH8RA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679660882880,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMGlobalInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMGlobalInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 147,
+ "versionNonce": 1194277212,
+ "isDeleted": false,
+ "id": "gd9UxDYh5XZYBG_P0f0c2",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 568.3333129882812,
+ "y": 424.666748046875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 195,
+ "height": 30,
+ "seed": 1018791012,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "YeoEjoPWRnxxyB2DjNi3g"
+ }
+ ],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 104,
+ "versionNonce": 1904253540,
+ "isDeleted": false,
+ "id": "YeoEjoPWRnxxyB2DjNi3g",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 600.8333129882812,
+ "y": 429.666748046875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 130,
+ "height": 20,
+ "seed": 839439588,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "bool is_mutable;",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "gd9UxDYh5XZYBG_P0f0c2",
+ "originalText": "bool is_mutable;"
+ },
+ {
+ "type": "rectangle",
+ "version": 91,
+ "versionNonce": 1480043996,
+ "isDeleted": false,
+ "id": "MB23InQWKES3OnYie8bbP",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 569.6666870117188,
+ "y": 460.666748046875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 195,
+ "height": 30,
+ "seed": 1468762332,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "--vP8lM62PEnMBhgFRqTM"
+ }
+ ],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 63,
+ "versionNonce": 717729252,
+ "isDeleted": false,
+ "id": "--vP8lM62PEnMBhgFRqTM",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 582.6666870117188,
+ "y": 465.666748046875,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 169,
+ "height": 20,
+ "seed": 695551844,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint32 data_offset;",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "MB23InQWKES3OnYie8bbP",
+ "originalText": "uint32 data_offset;"
+ },
+ {
+ "type": "rectangle",
+ "version": 111,
+ "versionNonce": 155030108,
+ "isDeleted": false,
+ "id": "pUUma4amJviNKdfn5otpb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 577.6666870117188,
+ "y": 497.33338928222656,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 180.33331298828125,
+ "height": 30,
+ "seed": 1550527844,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "JybtW1PyDYQa00JaSYsuo"
+ }
+ ],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 63,
+ "versionNonce": 1625313636,
+ "isDeleted": false,
+ "id": "JybtW1PyDYQa00JaSYsuo",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 618.8333435058594,
+ "y": 502.33338928222656,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 98,
+ "height": 20,
+ "seed": 1952693084,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "initial_value",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "pUUma4amJviNKdfn5otpb",
+ "originalText": "initial_value"
+ },
+ {
+ "type": "rectangle",
+ "version": 91,
+ "versionNonce": 1494410972,
+ "isDeleted": false,
+ "id": "CewuQtNj0ZC6Ogsq68ite",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 569.6666870117188,
+ "y": 546.6667022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 191,
+ "height": 30,
+ "seed": 10317668,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "4xSFF2vFZIoA0G7GTeC8-"
+ }
+ ],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 63,
+ "versionNonce": 588809444,
+ "isDeleted": false,
+ "id": "4xSFF2vFZIoA0G7GTeC8-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 588.1666870117188,
+ "y": 551.6667022705078,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 154,
+ "height": 20,
+ "seed": 1109403492,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "import_module_inst",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "CewuQtNj0ZC6Ogsq68ite",
+ "originalText": "import_module_inst"
+ },
+ {
+ "type": "rectangle",
+ "version": 123,
+ "versionNonce": 474590044,
+ "isDeleted": false,
+ "id": "AuHfz77U4KxNTCmKvW6bJ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 573,
+ "y": 589.3333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 184,
+ "height": 30,
+ "seed": 2058570588,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "h7MfnIO2f08rV_U7840Zp"
+ }
+ ],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 75,
+ "versionNonce": 1727940708,
+ "isDeleted": false,
+ "id": "h7MfnIO2f08rV_U7840Zp",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 591,
+ "y": 594.3333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 148,
+ "height": 20,
+ "seed": 1917882340,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643912221,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "import_global_inst",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "AuHfz77U4KxNTCmKvW6bJ",
+ "originalText": "import_global_inst"
+ },
+ {
+ "type": "text",
+ "version": 134,
+ "versionNonce": 1361481211,
+ "isDeleted": false,
+ "id": "Clf1NqZqRXJuRl-CQgx_u",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 232.6667175292969,
+ "y": 454.6668395996094,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 237,
+ "height": 20,
+ "seed": 1711793252,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "_acaSZ2N5FSiuPGQjH8RA",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMGlobalInstance *globals;",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMGlobalInstance *globals;"
+ },
+ {
+ "type": "text",
+ "version": 30,
+ "versionNonce": 1504826724,
+ "isDeleted": false,
+ "id": "Mj7l2FOHQ7NNAkTiGq7T_",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 641,
+ "y": 631.0001373291016,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 29,
+ "height": 20,
+ "seed": 1401608924,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643959727,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[0]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[0]"
+ },
+ {
+ "type": "rectangle",
+ "version": 52,
+ "versionNonce": 894397020,
+ "isDeleted": false,
+ "id": "CGwcN3BpsJaehLlHjEn6l",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 548.6666259765625,
+ "y": 653.0000457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 227,
+ "height": 87,
+ "seed": 253331684,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644065258,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 107,
+ "versionNonce": 1424372828,
+ "isDeleted": false,
+ "id": "YjTAPKLSA0k-ml5j0Ho59",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 565.1666259765625,
+ "y": 671.6667327880859,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 195,
+ "height": 30,
+ "seed": 192441436,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "jmlAM3nHo1CJVxGKppt1O"
+ }
+ ],
+ "updated": 1679643968867,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 78,
+ "versionNonce": 2064306020,
+ "isDeleted": false,
+ "id": "jmlAM3nHo1CJVxGKppt1O",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 578.1666259765625,
+ "y": 676.6667327880859,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 169,
+ "height": 20,
+ "seed": 1473779556,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643968868,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint32 data_offset;",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "YjTAPKLSA0k-ml5j0Ho59",
+ "originalText": "uint32 data_offset;"
+ },
+ {
+ "type": "text",
+ "version": 32,
+ "versionNonce": 1512962780,
+ "isDeleted": false,
+ "id": "QnLh-KZNv_MoD4Ak5RsLk",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 636.1666259765625,
+ "y": 719.0000457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 22,
+ "height": 20,
+ "seed": 927449564,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679643979051,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[1]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[1]"
+ },
+ {
+ "type": "rectangle",
+ "version": 62,
+ "versionNonce": 626330844,
+ "isDeleted": false,
+ "id": "F26JZDrwDBDSk5o5kcV_E",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 547.3333129882812,
+ "y": 739.6667327880859,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 227.666748046875,
+ "height": 60.666656494140625,
+ "seed": 725179740,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644057644,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 71,
+ "versionNonce": 1658992100,
+ "isDeleted": false,
+ "id": "H6cL4L0PUBLB5An3KDf-i",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 636.6666259765625,
+ "y": 784.0003204345703,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 31,
+ "height": 20,
+ "seed": 83711068,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644496025,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "[...]",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "[...]"
+ },
+ {
+ "type": "rectangle",
+ "version": 158,
+ "versionNonce": 208125412,
+ "isDeleted": false,
+ "id": "M6cl8S-GRJkkRSQrUxzJV",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 566.833251953125,
+ "y": 747.6667327880859,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 195,
+ "height": 30,
+ "seed": 997959652,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "DrpXGgZIT2RAhz4L6EM2n"
+ }
+ ],
+ "updated": 1679644019993,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 128,
+ "versionNonce": 493257308,
+ "isDeleted": false,
+ "id": "DrpXGgZIT2RAhz4L6EM2n",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 579.833251953125,
+ "y": 752.6667327880859,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 169,
+ "height": 20,
+ "seed": 157169756,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644019993,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint32 data_offset;",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "M6cl8S-GRJkkRSQrUxzJV",
+ "originalText": "uint32 data_offset;"
+ },
+ {
+ "type": "rectangle",
+ "version": 223,
+ "versionNonce": 680765365,
+ "isDeleted": false,
+ "id": "nPxM8HePICecTvRXbdEeU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 983.333251953125,
+ "y": 378.1666793823242,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 97.66668701171875,
+ "height": 30.000015258789062,
+ "seed": 1516156124,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "Y_Dw9hCEvutA3MjjHfyJK",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679660991443,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 165,
+ "versionNonce": 430152219,
+ "isDeleted": false,
+ "id": "Y_Dw9hCEvutA3MjjHfyJK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 756.6666259765625,
+ "y": 766.3333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 217.14296385054604,
+ "height": 385.92617569738337,
+ "seed": 703298780,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "MraNxq38RWxCBOb3EhIue"
+ }
+ ],
+ "updated": 1679660991443,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "nPxM8HePICecTvRXbdEeU",
+ "gap": 9.523662126016394,
+ "focus": 1.1442737969660202
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 217.14296385054604,
+ -385.92617569738337
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 4,
+ "versionNonce": 1122104853,
+ "isDeleted": false,
+ "id": "MraNxq38RWxCBOb3EhIue",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 838.7381079018355,
+ "y": 563.3703014335349,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 53,
+ "height": 20,
+ "seed": 1058889828,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661201730,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "offset",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Y_Dw9hCEvutA3MjjHfyJK",
+ "originalText": "offset"
+ },
+ {
+ "type": "text",
+ "version": 239,
+ "versionNonce": 551950564,
+ "isDeleted": false,
+ "id": "O5mHltv55Fs4-vM6wNcf-",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 226.99996948242188,
+ "y": 655.0000457763672,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 164,
+ "height": 20,
+ "seed": 352849508,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "1QAmzR8Zkk8scUA3tqI0k",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679644753215,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMGlobalInstance",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMGlobalInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 104,
+ "versionNonce": 219644132,
+ "isDeleted": false,
+ "id": "CpOJESdMD1E9wBe2Gkkvf",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 216.66665649414062,
+ "y": 681.6666412353516,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 180.33331298828125,
+ "height": 46.666778564453125,
+ "seed": 705788380,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644728661,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 153,
+ "versionNonce": 296383867,
+ "isDeleted": false,
+ "id": "1QAmzR8Zkk8scUA3tqI0k",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 583.9999694824219,
+ "y": 602.3333587646484,
+ "strokeColor": "#000000",
+ "backgroundColor": "#15aabf",
+ "width": 179.2173434297432,
+ "height": 75.12469349055664,
+ "seed": 869061340,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "N9fS0DKeDh1d_Ueyopb9v"
+ }
+ ],
+ "updated": 1679661068533,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "O5mHltv55Fs4-vM6wNcf-",
+ "focus": 1.1855962422681312,
+ "gap": 14.0001220703125
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -179.2173434297432,
+ 75.12469349055664
+ ]
+ ]
+ },
+ {
+ "id": "N9fS0DKeDh1d_Ueyopb9v",
+ "type": "text",
+ "x": 449.39129776755027,
+ "y": 629.8957055099268,
+ "width": 90,
+ "height": 20,
+ "angle": 0,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "roundness": null,
+ "seed": 339183189,
+ "version": 24,
+ "versionNonce": 270159573,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1679661092509,
+ "link": null,
+ "locked": false,
+ "text": "when import",
+ "fontSize": 16,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 14,
+ "containerId": "1QAmzR8Zkk8scUA3tqI0k",
+ "originalText": "when import"
+ },
+ {
+ "type": "rectangle",
+ "version": 59,
+ "versionNonce": 96174172,
+ "isDeleted": false,
+ "id": "oDs6sXYd2cCCUTlDuFyfK",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 199.66659545898438,
+ "y": 599.9999847412109,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 236.33343505859375,
+ "height": 196.3333740234375,
+ "seed": 1531972708,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644717838,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 72,
+ "versionNonce": 1711293284,
+ "isDeleted": false,
+ "id": "Gyz12ttmraGX-CaCTWl3h",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 191.99990844726562,
+ "y": 576.3333892822266,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 239,
+ "height": 20,
+ "seed": 683171044,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "957MNrV_zCOsf-ssBBkla",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679644717838,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "WASMModuleInstance (second)",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance (second)"
+ },
+ {
+ "type": "text",
+ "version": 185,
+ "versionNonce": 1644000405,
+ "isDeleted": false,
+ "id": "7TYuQ_yCiwRN4oz8zkdGb",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 38.33337402343753,
+ "y": 248.66676330566406,
+ "strokeColor": "#d9480f",
+ "backgroundColor": "transparent",
+ "width": 171,
+ "height": 19,
+ "seed": 1694546652,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModuleInstance",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstance"
+ },
+ {
+ "type": "rectangle",
+ "version": 151,
+ "versionNonce": 1152705621,
+ "isDeleted": false,
+ "id": "DN3tWnhyoeDPQR_-BYeYI",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 36.666656494140625,
+ "y": 269.00010681152344,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 202.00003051757815,
+ "height": 124.66665649414062,
+ "seed": 693300324,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "-n6vwSfIOzGpAxjpRyuNZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679661004485,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 150,
+ "versionNonce": 458299605,
+ "isDeleted": false,
+ "id": "K0JMv-qZGU4i9Or0Xz4Gg",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 246.33328247070315,
+ "y": 399.33343505859375,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 218,
+ "height": 19,
+ "seed": 881476572,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661029361,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 3,
+ "text": "WASMModuleInstanceExtra",
+ "baseline": 15,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "WASMModuleInstanceExtra"
+ },
+ {
+ "type": "rectangle",
+ "version": 169,
+ "versionNonce": 769392085,
+ "isDeleted": false,
+ "id": "CERoUCjzlaXjrdr4PSxtB",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 225.33328247070312,
+ "y": 428.00010681152344,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 256.3333740234375,
+ "height": 91.33331298828128,
+ "seed": 1750838620,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "-n6vwSfIOzGpAxjpRyuNZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679661027326,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 88,
+ "versionNonce": 1947089019,
+ "isDeleted": false,
+ "id": "H3BkjBVeDYM2F429PxOI9",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 233.0000915527344,
+ "y": 447.00010681152344,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 243.00006103515625,
+ "height": 31,
+ "seed": 258806116,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "-n6vwSfIOzGpAxjpRyuNZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 257,
+ "versionNonce": 314119835,
+ "isDeleted": false,
+ "id": "_acaSZ2N5FSiuPGQjH8RA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 463.97668298272777,
+ "y": 453.66683959960943,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 80.59006409386518,
+ "height": 100.23285752369344,
+ "seed": 1866235612,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false,
+ "startBinding": {
+ "elementId": "Clf1NqZqRXJuRl-CQgx_u",
+ "focus": 0.8216444271084713,
+ "gap": 1
+ },
+ "endBinding": {
+ "elementId": "FcG2LCAdKxw_z2SzLhPPr",
+ "focus": 1.009989878742988,
+ "gap": 3.7665659116883603
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 80.59006409386518,
+ -100.23285752369344
+ ]
+ ]
+ },
+ {
+ "type": "rectangle",
+ "version": 63,
+ "versionNonce": 1164697781,
+ "isDeleted": false,
+ "id": "NIObCr2apYl6JLLzA37G2",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 232.66665649414065,
+ "y": 486.66676330566406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 244.33331298828125,
+ "height": 30,
+ "seed": 1813909212,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "sYEF77zbpRw-pcdX1ass6"
+ }
+ ],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 24,
+ "versionNonce": 4682011,
+ "isDeleted": false,
+ "id": "sYEF77zbpRw-pcdX1ass6",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 272.33331298828125,
+ "y": 491.66676330566406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 165,
+ "height": 20,
+ "seed": 382274908,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint32 global_count;",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "NIObCr2apYl6JLLzA37G2",
+ "originalText": "uint32 global_count;"
+ },
+ {
+ "type": "rectangle",
+ "version": 142,
+ "versionNonce": 519569941,
+ "isDeleted": false,
+ "id": "7jX0wgP7v4HHkuITKOf89",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 94.3333435058594,
+ "y": 344.33351135253906,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 115,
+ "height": 30.333358764648438,
+ "seed": 1226666212,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "sK7ecOoz_3QIduVF0nHd7"
+ }
+ ],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 116,
+ "versionNonce": 1846580667,
+ "isDeleted": false,
+ "id": "sK7ecOoz_3QIduVF0nHd7",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 146.3333435058594,
+ "y": 349.5001907348633,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 11,
+ "height": 20,
+ "seed": 1178170724,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "e",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "7jX0wgP7v4HHkuITKOf89",
+ "originalText": "e"
+ },
+ {
+ "type": "diamond",
+ "version": 135,
+ "versionNonce": 691599221,
+ "isDeleted": false,
+ "id": "yTfoj623sdm1eh4Eusmvt",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 174.66665649414065,
+ "y": 352.0001983642578,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 13.66668701171875,
+ "height": 12.333328247070312,
+ "seed": 559414236,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "arrow",
+ "version": 324,
+ "versionNonce": 1197545819,
+ "isDeleted": false,
+ "id": "-n6vwSfIOzGpAxjpRyuNZ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 182.00003051757815,
+ "y": 356.66676330566406,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 45.12566323463764,
+ "height": 69.66665649414062,
+ "seed": 1850539876,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661027326,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "CERoUCjzlaXjrdr4PSxtB",
+ "gap": 1,
+ "focus": -0.6072997775389923
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 45.12566323463764,
+ 69.66665649414062
+ ]
+ ]
+ },
+ {
+ "type": "arrow",
+ "version": 68,
+ "versionNonce": 732107996,
+ "isDeleted": false,
+ "id": "957MNrV_zCOsf-ssBBkla",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 578.0000305175781,
+ "y": 557.6666717529297,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 144.0692777412945,
+ "height": 39.30743410761045,
+ "seed": 1605267676,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644717838,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "Gyz12ttmraGX-CaCTWl3h",
+ "focus": 1.0338080600507247,
+ "gap": 3.00006103515625
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -144.0692777412945,
+ 39.30743410761045
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 20,
+ "versionNonce": 825681252,
+ "isDeleted": false,
+ "id": "pKw8fr7S6f80J93nrJtkQ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 575.8333129882812,
+ "y": 553.5000076293945,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 13.66668701171875,
+ "height": 12.333328247070312,
+ "seed": 222063588,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644481683,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "diamond",
+ "version": 20,
+ "versionNonce": 825681252,
+ "isDeleted": false,
+ "id": "XKwLDKrjsXcSogvJHSY-e",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 573.8333129882812,
+ "y": 597.5000076293945,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 13.66668701171875,
+ "height": 12.333328247070312,
+ "seed": 1140569180,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644483164,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 215,
+ "versionNonce": 510935253,
+ "isDeleted": false,
+ "id": "oPjebDyI5NP26BNK4PLtX",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 50.33343505859378,
+ "y": 290.33338928222656,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 180,
+ "height": 31,
+ "seed": 727213156,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "ZK3cjtpUxVpruHBkbgevo"
+ }
+ ],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 175,
+ "versionNonce": 1653383931,
+ "isDeleted": false,
+ "id": "ZK3cjtpUxVpruHBkbgevo",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 58.33343505859378,
+ "y": 295.83338928222656,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 164,
+ "height": 20,
+ "seed": 1130592356,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "uint8 * global_data",
+ "baseline": 14,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "oPjebDyI5NP26BNK4PLtX",
+ "originalText": "uint8 * global_data"
+ },
+ {
+ "type": "arrow",
+ "version": 159,
+ "versionNonce": 345149237,
+ "isDeleted": false,
+ "id": "5S0qe2-BjQRPwuEEQ_UsU",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 228.00003051757812,
+ "y": 299.9999694824219,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 754.7517447227082,
+ "height": 17.8331298828125,
+ "seed": 1256331620,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679661008047,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "D5Ay5TxydaAe4f80l_79L",
+ "focus": 0.9720307648275319,
+ "gap": 1
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 385.0834503173828,
+ -17.8331298828125
+ ],
+ [
+ 754.7517447227082,
+ -2.996583692902334
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 89,
+ "versionNonce": 1413439029,
+ "isDeleted": false,
+ "id": "szV9RT3yAJ51dUnP5JYMS",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 220.1667175292969,
+ "y": 294.50000762939453,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 13.66668701171875,
+ "height": 12.333328247070312,
+ "seed": 1642184284,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679661000688,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 160,
+ "versionNonce": 715957468,
+ "isDeleted": false,
+ "id": "DuwilIDd-fhNUxybFRKva",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 255.16659545898438,
+ "y": 750.6665496826172,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 99,
+ "height": 20,
+ "seed": 121250780,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644739787,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "global_data",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "global_data"
+ },
+ {
+ "type": "rectangle",
+ "version": 143,
+ "versionNonce": 2046173532,
+ "isDeleted": false,
+ "id": "6CMun9I8IOX876t85IJ2X",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "dashed",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 215.83328247070312,
+ "y": 738.6664733886719,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 180.33331298828125,
+ "height": 46.666778564453125,
+ "seed": 2113088100,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "igqxFPh3AgDb1kYMsORSZ",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1679644784578,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 34,
+ "versionNonce": 1198703204,
+ "isDeleted": false,
+ "id": "cbSo4pUG_J3a4Pnk3ODCA",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 276.6665954589844,
+ "y": 693.3332366943359,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 55,
+ "height": 20,
+ "seed": 328242020,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1679644771096,
+ "link": null,
+ "locked": false,
+ "fontSize": 16,
+ "fontFamily": 1,
+ "text": "globals",
+ "baseline": 14,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "globals"
+ },
+ {
+ "type": "arrow",
+ "version": 81,
+ "versionNonce": 311117156,
+ "isDeleted": false,
+ "id": "igqxFPh3AgDb1kYMsORSZ",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 247.33328247070312,
+ "y": 706.3332366943359,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 71.66665649414062,
+ "height": 58.33343505859375,
+ "seed": 1345639908,
+ "groupIds": [],
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1679644787747,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": {
+ "elementId": "6CMun9I8IOX876t85IJ2X",
+ "focus": -0.8452179527426857,
+ "gap": 1.499908447265625
+ },
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -71.66665649414062,
+ 15.66668701171875
+ ],
+ [
+ -32.999908447265625,
+ 58.33343505859375
+ ]
+ ]
+ },
+ {
+ "type": "diamond",
+ "version": 135,
+ "versionNonce": 691599221,
+ "isDeleted": false,
+ "id": "koTtnTl85TIGelUbfKlR9",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 459.58338928222656,
+ "y": 446.0001754760742,
+ "strokeColor": "#000000",
+ "backgroundColor": "#be4bdb",
+ "width": 13.66668701171875,
+ "height": 12.333328247070312,
+ "seed": 626707637,
+ "groupIds": [],
+ "roundness": null,
+ "boundElements": null,
+ "updated": 1679661018823,
+ "link": null,
+ "locked": false
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.svg b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.svg
new file mode 100644
index 000000000..fa3461732
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/images/wasm_globals.svg
@@ -0,0 +1,16 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1097.5000915527344 587.6669921875" width="1097.5000915527344" height="587.6669921875">
+ <!-- svg-source:excalidraw -->
+
+ <defs>
+ <style class="style-fonts">
+ @font-face {
+ font-family: "Virgil";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Virgil.woff2");
+ }
+ @font-face {
+ font-family: "Cascadia";
+ src: url("https://unpkg.com/@excalidraw/excalidraw@0.14.2/dist/excalidraw-assets/Cascadia.woff2");
+ }
+ </style>
+ </defs>
+ <rect x="0" y="0" width="1097.5000915527344" height="587.6669921875" fill="#ffffff"></rect><g stroke-linecap="round" transform="translate(956.1665954589844 71.66673278808594) rotate(0 49.8333740234375 105.5000381469726)"><path d="M0.55 1.55 C23.08 -2.77, 46.37 0.12, 101.07 1.25 M-1 -0.94 C20.97 -0.39, 43.99 0.19, 100.66 -0.85 M100.97 -1.48 C97.64 51.04, 99.53 106.82, 99.82 210.11 M99.96 -0.87 C99.69 43.88, 100.88 87.81, 100.26 210.6 M100.02 211.94 C74.25 211.44, 52.66 209.51, -0.54 209.49 M100.02 210.65 C61.09 211.14, 21.28 211.47, -0.33 210.96 M-0.25 212.66 C-1.16 150.57, -0.84 86.79, -0.38 1.66 M0.69 211.48 C0.83 141.17, 0.99 69.8, 0.7 0.8" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(888.1665954589844 10) rotate(0 51.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">global_data:</text></g><g transform="translate(501.5000305175781 97.66668701171875) rotate(0 137 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstanceExtra::globals</text></g><g mask="url(#mask-I86Qg5wzdmE77J5SbA7HP)" stroke-linecap="round"><g transform="translate(732.3803958894038 246.1419875348965) rotate(0 111.7857120288877 -76.38810235405538)"><path d="M1.1 0.98 C45.43 -31.25, 92.72 -64.96, 221.97 -153.76 M0.78 -0.66 C60.08 -42.22, 120.77 -82.53, 222.79 -152.71" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(732.3803958894038 246.1419875348965) rotate(0 111.7857120288877 -76.38810235405538)"><path d="M206.73 -127.07 C207.47 -132.28, 212.86 -140.42, 220.91 -154.64 M206.32 -129.17 C209.53 -135.52, 214.36 -140.87, 221.96 -153.31" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(732.3803958894038 246.1419875348965) rotate(0 111.7857120288877 -76.38810235405538)"><path d="M195.14 -144.01 C198.15 -145.79, 205.92 -150.46, 220.91 -154.64 M194.73 -146.11 C201.11 -147.89, 209.08 -148.65, 221.96 -153.31" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask id="mask-I86Qg5wzdmE77J5SbA7HP"><rect x="0" y="0" fill="#fff" width="1055.8290730395638" height="498.39211935369804"></rect><rect x="817.6047344644838" y="160.01692162549563" fill="#000" width="53" height="20" opacity="1"></rect></mask><g transform="translate(817.6047344644837 160.01692162549568) rotate(0 26.561373453807732 9.736963555345426)"><text x="26.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">offset</text></g><g stroke-linecap="round" transform="translate(959.8332824707031 89.33332824707031) rotate(0 45.833343505859375 14)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.86 7.13 C1.84 4.4, 2.51 3.16, 4.4 0.94 M-0.61 6.17 C0.7 5.01, 1.93 3.38, 4.8 0.15 M-0.29 12.96 C2.61 8.66, 8.92 3.44, 11.94 -0.28 M-0.25 12.38 C3.69 8.98, 7.1 5.25, 11.32 0.58 M1.67 17.5 C6.69 9.81, 13.94 4.43, 14.97 0.01 M-0.84 17.95 C3.01 13.01, 8.56 9.14, 16.21 0.21 M-1.18 23.27 C6.8 15.93, 14.82 5.6, 19.3 0.07 M-0.5 24.14 C4.67 17.97, 10.53 11.71, 21.6 0.87 M3.03 27.33 C7.25 20.35, 17.1 12.02, 25.84 1.69 M2.11 29.47 C11.47 19.28, 20.47 8.25, 25.85 -0.37 M6.57 30.91 C14.28 23.78, 19.53 15.2, 33.31 -1.67 M6.84 28.62 C11.52 23.03, 19.33 15.12, 31.08 -0.26 M12.19 27.9 C21.26 18.18, 27.49 8.91, 35.46 0 M11.55 29.92 C20.57 18.75, 29.1 7.68, 36.61 -0.16 M15.75 29.92 C26.71 17.96, 31.93 9.44, 42.34 0.17 M17.12 28.58 C26.29 18.72, 37.25 6.03, 41.64 -0.05 M22.9 30.6 C29.33 20.02, 33.36 12.37, 49.09 0.72 M23.57 27.91 C29.26 21.97, 33.81 15.32, 48.48 0.55 M25.9 30.47 C37.79 20.55, 47.44 9.33, 53.33 -1.12 M27.29 28.45 C34.7 22.09, 41.14 13.93, 53.28 0.55 M32.96 27.89 C40.05 18.17, 50.15 10.67, 59.88 0.19 M33.75 27.93 C42.21 18.12, 50.36 9.95, 57.24 0.4 M37.04 28.03 C44.23 22.43, 51.73 12.78, 62.15 1.38 M38.7 28.33 C43.35 22.88, 48.47 18.37, 63.32 0.05 M45.13 29.77 C50.54 17, 62.45 9.21, 66.89 -0.64 M42.94 27.91 C51.95 20.43, 60.13 11.62, 69.46 0.01 M47.1 30.68 C55.06 18.39, 66.2 12.95, 75.55 -1.86 M49.49 28.25 C56.26 20.58, 64.84 11.13, 75.33 -0.6 M53.02 29.88 C63.98 16.64, 74.85 6.12, 81.07 1.78 M54.32 28.26 C61.78 20.75, 69.29 10.8, 79.52 0.94 M57.93 29.08 C69.2 17.54, 79.68 5.19, 85.2 1.28 M59.58 29.22 C65 21.72, 71.54 14.44, 84.24 -0.98 M63.19 27.43 C72.56 17.07, 82.41 10.69, 91.31 -0.42 M64.33 28.83 C72.99 19.8, 80.7 10.81, 90.58 0.7 M69.27 30.51 C77.98 22.41, 86 14.04, 91.72 0.73 M69.71 28.2 C78.57 19.06, 88.84 8.64, 93.24 2.04 M77.08 29.22 C84.17 19.68, 87.62 13.29, 95.82 7.04 M75.73 27.91 C80.93 23.17, 84.62 16.9, 95.05 7.31 M80.77 28.8 C85.69 23.36, 88.11 18.35, 92.01 13.31 M80.42 29.07 C84.12 24.64, 87.08 22.53, 94.29 14.31 M85.64 28.13 C88.31 25.75, 90.94 23.51, 94.49 20.85 M86.48 29.01 C88.56 25.94, 91.67 22.25, 93.07 20.68" stroke="#868e96" stroke-width="0.5" fill="none"></path><path d="M-1.6 1.14 C32.29 -2.57, 62.29 -2.5, 91.09 0.26 M-0.5 -0.53 C29.7 1.51, 59.38 0.18, 90.68 0.48 M89.86 0.5 C91.09 11.02, 89.71 19.71, 90.97 29.69 M91.08 0.95 C91.4 6.76, 92.32 12.5, 92.11 28.57 M93.51 27.93 C69.11 28.01, 45.48 28.29, 0.11 27.48 M91.59 28.93 C59.81 27.82, 30.59 28.29, 0.66 28.5 M0.69 26.99 C-0.44 22.81, 1.14 14.21, 1.69 0.11 M0.63 28.14 C-1.16 19.73, -0.76 11.85, -1 -0.68" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(957.8332214355469 124.50000762939453) rotate(0 47.16668701171875 9.666679382324219)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.47 7.03 C0.91 4.57, 2.83 2.45, 5.57 -0.1 M-0.49 6.13 C1.73 3.93, 3.48 1.85, 4.78 0.57 M1.05 10.85 C4.46 9.51, 6.97 5.43, 10.38 -0.01 M0.47 12.35 C3.18 9.82, 5.54 7.14, 11.24 0.73 M-1.07 18.88 C1.93 15.72, 7.23 9.58, 15.31 -0.5 M-0.62 17.5 C3.88 13.6, 9.48 8.15, 15.5 0.95 M1.42 20.78 C8.85 14.41, 13.29 6.15, 21.4 -1.19 M2.3 21.03 C7.17 15.99, 11.95 10.47, 22.2 -0.21 M6.24 20.24 C12.97 16.43, 18.37 8.13, 27.65 1.73 M8.37 22.17 C13.55 16.34, 17.89 10.07, 25.59 -0.43 M14.45 23.66 C17.98 18.5, 20.06 14.07, 30.33 -1.21 M12.15 20.88 C20.43 14.66, 26.38 5.54, 31.74 0.12 M17.47 22.7 C22.71 14.28, 28.42 6.76, 36.63 1.35 M19.49 21.07 C23.34 15.29, 27.27 10.1, 36.46 0.5 M24.12 23.32 C28.1 13.02, 35.51 7.03, 42.83 1.6 M22.78 21.11 C29.38 16.32, 33.13 9.2, 42.61 -0.56 M30.84 21.82 C33.98 12.07, 40.08 8.27, 48 -1.3 M28.15 22.3 C33.12 15.93, 37.36 11.83, 47.83 0.81 M35.33 22.98 C43.05 15.5, 49.43 5.79, 52.2 -1.22 M33.31 22.34 C38.83 17.26, 42.51 11.41, 53.87 0.08 M38.79 20.03 C43.73 15.94, 50.87 10.85, 58.14 1.04 M38.83 21.77 C44.39 14.94, 51.56 7.65, 58.35 -0.18 M43.56 20.79 C50.27 16.41, 52.94 9.68, 65.36 -2.2 M43.86 21.48 C48.56 16.48, 54.21 11.32, 64.04 0.15 M51.34 19.67 C54.16 16.27, 61.94 5.66, 67.98 0.56 M49.48 21.15 C55.01 17.08, 59.23 13.29, 68.63 0.21 M56.87 19.79 C57.46 18.79, 64.9 13.98, 72.8 0.05 M54.45 20.74 C59.83 16.77, 63.44 13.67, 74.05 0.59 M62.11 20.98 C63.92 17.73, 68.47 13.69, 81.06 0.32 M60.49 20.93 C67.96 13.72, 73.01 7.36, 80.22 0.9 M65.94 21.92 C72.77 14.58, 78.75 5.31, 86.6 -1.22 M66.08 20.62 C71.38 14.53, 76.88 8.51, 84.34 0.11 M70.32 20.12 C74.46 16.24, 82.55 11.72, 89.53 0.3 M71.72 21.38 C77.24 15, 82.8 8.95, 90.65 0.13 M78.03 22.05 C82.26 18.31, 86.21 10.38, 93.79 1.96 M75.72 20.93 C80.56 18.06, 84.11 12.51, 95.1 0.97 M82.76 23.06 C84.54 15.77, 89.3 14.08, 94.23 6.22 M81.51 21.57 C86.77 15.37, 90.56 12.01, 94.48 7.22 M87.1 21.78 C88.71 18.49, 90.59 16.31, 94.74 11.72 M87.26 21.68 C88.68 19.39, 91.49 17.38, 95.34 12.82" stroke="#868e96" stroke-width="0.5" fill="none"></path><path d="M1.14 0.2 C32.93 -1.13, 67.92 0.18, 94.59 0.57 M-0.53 -0.41 C38.42 -0.37, 74.77 -0.52, 94.81 0.7 M94.82 -0.58 C94.87 4.05, 93.26 11.25, 95.96 18.08 M95.25 -0.44 C94.42 7.55, 93.6 14.62, 94.88 18.83 M94.27 19.52 C69.29 19.51, 43.81 20.31, -0.52 20.1 M95.27 18.49 C69.03 20.2, 44.34 19.92, 0.5 18.75 M-0.98 18.85 C1.34 14.99, -0.43 10.19, 0.11 -0.1 M0.13 18.43 C-0.19 11.47, 0.18 3.69, -0.66 -0.45" stroke="#000000" stroke-width="1" fill="none"></path></g><g mask="url(#mask-PFkOKGbMOcdhcpcv4DutQ)" stroke-linecap="round"><g transform="translate(727.2050086321542 464.0001220703125) rotate(0 110.16582959061594 -171.5074190704382)"><path d="M-1.11 -1.05 C46.33 -75.61, 96.03 -150.15, 221.44 -342.55 M0.41 -0.47 C55.8 -85.52, 111.52 -170.05, 220.38 -341.89" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(727.2050086321542 464.0001220703125) rotate(0 110.16582959061594 -171.5074190704382)"><path d="M211.89 -314.49 C213.22 -319.63, 216.84 -324.93, 222.37 -343.58 M214.62 -313.44 C215.07 -320.89, 217.77 -326.53, 220.47 -342.4" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(727.2050086321542 464.0001220703125) rotate(0 110.16582959061594 -171.5074190704382)"><path d="M194.58 -325.52 C199.78 -328.25, 207.21 -331.12, 222.37 -343.58 M197.32 -324.47 C202.04 -329.09, 209.06 -331.97, 220.47 -342.4" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask id="mask-PFkOKGbMOcdhcpcv4DutQ"><rect x="0" y="0" fill="#fff" width="1047.5391498982826" height="905.6099774193574"></rect><rect x="810.8720792652184" y="283.19519439579005" fill="#000" width="53" height="20" opacity="1"></rect></mask><g transform="translate(810.8720792652184 283.19519439579005) rotate(0 26.49875895755173 9.297508604084243)"><text x="26.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">offset</text></g><g transform="translate(890.5000915527344 33) rotate(0 98.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">hold values of GLOBALs</text></g><g stroke-linecap="round" transform="translate(521.6666564941406 125.33341979980469) rotate(0 114.33334350585932 149.83334350585938)"><path d="M-1.59 0.12 C63.53 1.16, 125.8 0.88, 228.3 -1.58 M-0.49 0.72 C83.14 0.58, 165.59 0.39, 228.72 -0.68 M228.05 0.19 C230.78 97.55, 231.13 196.94, 228.37 298.49 M229.01 -0.41 C227.17 102.47, 227.64 204.61, 228.88 300.01 M228.15 298.78 C172.04 302.26, 113.15 302.1, 0.04 299.34 M227.92 300.26 C172.55 299.52, 117.07 299.47, 0.76 299.1 M0.58 299.36 C-2.33 219.38, -2.11 140.84, 0.55 -1.2 M0.73 299.01 C-0.21 214.76, -0.05 130.28, 0.5 0.34" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(544.3333435058594 161.0000457763672) rotate(0 95 15)"><path d="M0.58 0.94 C52.11 3.07, 107.13 1.02, 188.96 1.83 M0.02 -0.19 C73.57 -1.35, 148.17 -2.42, 190.7 -0.29 M191.77 -1.34 C189.36 10.09, 191.42 18.91, 189.58 28.37 M190.38 -0.82 C189.63 7.41, 189.84 16.01, 189.11 29.42 M191.36 30.92 C137.09 31.66, 85.12 31.88, -0.97 29.15 M189.7 29.76 C145.28 28, 101.79 28.79, 0.7 29.11 M0.55 31.41 C0.23 20.18, -0.74 13.86, 0.49 -1.28 M-0.65 30.53 C-0.34 24.23, 0.31 16.69, 0.65 -0.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(594.8333435058594 166.0000457763672) rotate(0 44.5 10)"><text x="44.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">uint8 type;</text></g><g transform="translate(554.3332824707031 131.50001525878906) rotate(0 85.5 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMGlobalInstance</text></g><g stroke-linecap="round" transform="translate(541.6666564941406 198.3334197998047) rotate(0 97.5 15)"><path d="M1.45 -1.09 C51.71 -2.19, 101.94 -2.61, 193.77 1.56 M-0.59 -0.42 C59.44 -0.88, 118.48 -0.15, 195.31 0.47 M196.98 -0.49 C195.9 11.2, 193.22 20.47, 194.78 29.61 M195.14 0.4 C194.98 7.1, 195.78 14.26, 195.92 29.43 M195.61 31.66 C120.22 29.8, 42.61 32.44, -1.3 28.71 M194.82 30.68 C151.01 30.22, 107.86 30.2, 0.56 29.59 M1.51 30.2 C-0.33 24.22, 0.56 17.81, -0.89 1.45 M0.56 29.53 C-1.18 21.67, -1.09 12.31, -0.18 0.99" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(574.1666564941406 203.3334197998047) rotate(0 65 10)"><text x="65" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">bool is_mutable;</text></g><g stroke-linecap="round" transform="translate(543.0000305175781 234.3334197998047) rotate(0 97.5 15)"><path d="M-1.39 -0.67 C66.17 0.45, 135.48 -1.5, 194.64 1.48 M-0.3 0.92 C52.43 0.32, 104.34 0.81, 195.51 0.73 M194.15 1.8 C195.72 8.38, 194.32 13.05, 195.28 29.8 M195.11 0.28 C194.98 10.03, 194.92 18.18, 195.49 30.17 M194.16 28.77 C130.18 28.8, 66.97 28.6, -1.46 29.21 M195.93 30.24 C120.16 30.99, 44.24 32.63, 0.65 30.09 M-1.48 30.89 C0.39 21.02, -0.94 13.31, 0.54 -1.03 M-0.89 29.35 C-0.63 21.53, -0.14 13.36, -0.34 0.92" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(556.0000305175781 239.3334197998047) rotate(0 84.5 10)"><text x="84.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">uint32 data_offset;</text></g><g stroke-linecap="round" transform="translate(551.0000305175781 271.00006103515625) rotate(0 90.16665649414062 15)"><path d="M-0.67 0.54 C59.04 0.08, 119.98 -0.63, 178.56 -1.29 M-0.19 -0.34 C43.16 0.93, 84.33 0.44, 180.16 0.05 M180.79 1.7 C181.15 7.79, 181.88 16.9, 181.7 30.4 M180.79 -0.15 C180.52 7.13, 180.89 12.05, 180.47 30.48 M182.24 29.47 C110.35 33.15, 38.87 31, 0.6 29.52 M181.12 30.82 C144.46 30.37, 108.3 30.18, -0.91 29.9 M1.71 28.15 C-0.89 19.69, -0.44 8.32, 1.85 -0.41 M-0.17 29.1 C0.08 23.35, 0.24 17.47, -0.02 0.03" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(592.1666870117188 276.00006103515625) rotate(0 49 10)"><text x="49" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">initial_value</text></g><g stroke-linecap="round" transform="translate(543.0000305175781 320.3333740234375) rotate(0 95.5 15)"><path d="M1.64 0.73 C73.54 -0.61, 146.51 -3.31, 190.81 1.46 M-0.92 -0.4 C63.71 -1.81, 126.9 -0.71, 190.8 -0.75 M189.2 0.68 C191.47 12.56, 193.2 23.11, 191.07 28.4 M191.78 0.65 C190.76 8.35, 190.63 16.85, 190.22 30.78 M190.49 31.37 C150.67 31.06, 111.42 31.84, -0.52 30.74 M191.92 29.84 C148.02 30.04, 104.69 30.72, 0.46 31 M-0.07 31.18 C-1.34 20.31, -1.78 8.87, 1.37 1.07 M0.08 30.89 C-0.9 18.25, 0.71 7.8, -0.13 -0.69" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(561.5000305175781 325.3333740234375) rotate(0 77 10)"><text x="77" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">import_module_inst</text></g><g stroke-linecap="round" transform="translate(546.3333435058594 363.00006103515625) rotate(0 92 15)"><path d="M1.64 0.35 C53.1 2.92, 104.74 1.32, 183.31 -0.07 M-0.86 -0.99 C66.72 0.64, 132.9 -0.02, 184.76 0.08 M185.34 1.52 C183.46 10.29, 183.37 22.2, 182.09 31.53 M184.93 -0.88 C184.76 11.19, 184.05 20.54, 183.56 29.77 M185.2 29.03 C118.46 32.64, 50.8 31.34, -1.75 31.1 M183.8 29.86 C119.1 30.13, 53.07 28.63, 0.37 30.77 M-0.66 28.39 C0.52 19.71, 1.47 12.11, -0.6 1.55 M0.78 30.18 C-0.37 18.49, -0.38 7.02, 0.3 -0.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(564.3333435058594 368.00006103515625) rotate(0 74 10)"><text x="74" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">import_global_inst</text></g><g transform="translate(206.00006103515628 228.33351135253906) rotate(0 118.49999999999999 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMGlobalInstance *globals;</text></g><g transform="translate(614.3333435058594 404.66680908203125) rotate(0 14.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[0]</text></g><g stroke-linecap="round" transform="translate(521.9999694824219 426.6667175292969) rotate(0 113.5 43.5)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.18 6.59 C0.53 4.24, 2.14 2.54, 5.4 0.03 M-0.03 6.77 C1.88 4.13, 3.19 2.42, 5.31 0.46 M0.03 11.37 C3.17 8.14, 6.85 2.31, 9.24 -1.62 M0.74 11.53 C2.98 8.38, 7.29 4.29, 10.37 0.04 M-1.56 17.63 C7.88 12.61, 14.46 3.46, 15.26 1.92 M-0.69 18.26 C4.5 13.7, 8.53 9.08, 15.93 0.71 M-1.58 25.01 C8.83 16.98, 17.43 6.73, 21.27 -0.58 M0.99 24.38 C6.83 14.85, 15.92 7.57, 21.3 -0.76 M0.16 28.75 C6.18 23.52, 12.92 15.79, 26.26 1.87 M-0.92 30.78 C7.18 20.81, 16.3 11.81, 26.2 -0.5 M1.67 36.29 C6.76 28.52, 14.14 18.17, 33.3 -1.29 M-0.49 37.41 C12.29 21.66, 24.89 8.17, 31.21 0.1 M0.03 42.12 C8.2 32.96, 16.6 23.57, 35.12 0.2 M-0.66 42.98 C9.23 32, 17.65 22.16, 36.79 0.09 M0.67 50.81 C13.79 32.71, 29.87 15.14, 42.66 0.12 M-0.81 48.87 C11.27 34.85, 23.4 22.71, 42.94 0.53 M1.22 56.48 C16.87 38.89, 29.09 18.5, 47.06 -1.42 M0.23 55.49 C17.8 34.87, 34.96 13.35, 48.32 0.16 M1.5 61.53 C14.28 45.58, 29.25 27.14, 52.14 0.74 M-0.75 61.92 C12.2 46.69, 24.28 34.22, 53.84 -1.02 M-0.63 68.19 C21.41 39.82, 47.72 14.69, 56.43 -0.43 M-0.31 68.27 C14.84 49.62, 31.03 32.13, 57.83 -0.06 M0.01 73.48 C17.43 55.22, 33.28 35.48, 65.66 -1.43 M0 73.56 C14.7 58.52, 26.95 42.95, 63.66 0.48 M1.21 80.24 C20.63 52.57, 43.27 29.26, 70.73 -1.42 M0.06 79.59 C21.69 54.49, 43.21 30.22, 68.84 0.24 M1.18 84.6 C23.29 62.43, 44.92 37.05, 76.25 0.48 M0.17 85.34 C15.26 65.83, 30.88 47.89, 74.64 0.61 M2.58 88.48 C23.16 64.71, 43.41 40.82, 78.54 -0.06 M2.11 88.28 C31.83 53.08, 63.03 18.63, 79.26 0.42 M6.33 89.38 C38.58 54.1, 69.12 15.58, 86.09 -1.8 M8.17 89.07 C29.74 62.73, 51.16 38.12, 85.42 -0.48 M13.72 87.62 C44.37 55.18, 73.3 19.52, 89.6 0.81 M12.31 89.67 C30.68 68.93, 47.35 49.62, 89.48 0.42 M18.75 88.04 C34.28 70.28, 53.21 49.69, 94.47 0.35 M17.68 87.95 C41.08 61.98, 62.88 35.81, 95.08 -0.09 M22.89 90.56 C44.78 61.67, 71.87 35.61, 98.77 -0.76 M22.47 89.05 C54.35 55.42, 83.8 20.49, 100.29 0.71 M27.52 88.89 C46.83 65.14, 67.73 44.55, 105.79 0.42 M29.49 89.01 C44.41 70.15, 61.56 50.08, 107.17 -0.95 M32 89.31 C59 61.49, 83.17 32.83, 110.01 -1.83 M33.35 88.42 C56.56 61.09, 80.38 34.57, 110.95 0.35 M38.11 89.38 C58.65 68.4, 77.5 45.52, 116.95 1.54 M40.08 88.03 C58.94 64.87, 79.75 41.24, 116.97 -0.47 M44.09 88.73 C66.67 61.12, 92.74 35.8, 120.44 1.4 M44.19 88.38 C64.74 65, 85.07 41.48, 121.13 0.95 M49.12 87.79 C75.55 55.25, 105.49 27.47, 127.93 1.42 M50.38 89.39 C74.25 62.55, 96.29 34.49, 126.22 0.24 M55.33 90.56 C71.9 69.87, 89.94 48.09, 132.29 1.6 M54.62 88.06 C73.93 68.73, 90.89 47.99, 132.96 0.7 M60.29 87.31 C78.5 68.69, 98.61 46.78, 137.85 0.95 M61.77 88.02 C81.71 66.13, 101.69 42.97, 137.08 0.9 M67.01 89.41 C89.39 63.24, 113.61 33.73, 144.89 0.32 M66.74 89.19 C95.52 54.93, 125.02 21.09, 142.99 0.32 M72.47 87.99 C98.5 60.03, 126.73 25.44, 147.64 1.11 M72.06 89.39 C94.53 62.96, 118.17 35.47, 148.84 1.01 M77.55 88.77 C107.37 54.53, 136.51 22.3, 154.75 0.01 M77.07 88.01 C105.98 52.62, 137.64 18.56, 154.22 -0.87 M82.97 87.51 C96.79 67.68, 112.7 48.83, 159.33 -0.23 M80.83 88.32 C102.88 64.34, 124.68 38.87, 159.21 0.66 M86.49 89.02 C110.02 59.24, 134.79 33.67, 163.45 -0.05 M86.58 89.38 C115.58 56.48, 146.02 23.24, 164.08 -1.02 M92.23 90.17 C120.57 55.6, 153.15 20.05, 168.1 -0.34 M92.08 89.92 C114.1 64.05, 134.45 40.53, 170.35 0.51 M98.49 87.38 C116.62 67.68, 138.52 44.83, 173.72 0.32 M96.66 88.69 C121.5 63.49, 143.27 35.04, 174.44 0.31 M103.8 87.4 C125.63 64, 144.52 40.58, 178.22 0.41 M102.28 90.11 C123.07 67.29, 141.78 45.31, 180.83 -0.25 M107.35 89.99 C138.9 53.28, 165.63 19.96, 185.43 -1.81 M109.16 87.88 C138.37 53.03, 169.74 19.48, 185.62 0.1 M115.05 90.75 C139.38 59.3, 163.47 33.39, 191.13 -1.5 M112.97 88.63 C143.25 53.54, 175.16 17.78, 189.69 0.16 M119.98 87.81 C143.45 62.61, 165.86 33.96, 195.55 -0.53 M118.36 89.49 C145.23 58.59, 170.11 28.58, 196.34 -0.1 M124.44 88.64 C138.87 69.33, 157.77 50.21, 201.36 -0.71 M124.16 89.79 C153.41 54.42, 182.3 21.04, 200.39 0.07 M128.42 88.73 C151.82 65.47, 173.72 39.6, 206.18 -1.04 M128.96 88.6 C150.25 65.58, 169.5 41.68, 207.81 -0.17 M135.59 90.39 C157.82 63.58, 177.66 39.12, 212.57 1.04 M134.28 88.44 C160.1 59.03, 184.03 31.04, 212.83 0.38 M141.84 89.48 C156.33 68.81, 174.92 50.54, 216.55 0.36 M140.13 88.85 C169.58 54.1, 199.39 21.78, 217.63 0.57 M145.23 90.17 C167.54 61.64, 191.92 31.82, 221.56 -1.15 M144.19 90.03 C160.59 71.39, 176.75 53.5, 223.36 0.54 M150.52 87.67 C170.44 61.74, 191 41.08, 226.36 0.96 M151.43 88.45 C175.75 59.49, 201.29 29.82, 227.2 0.1 M155.2 91.03 C180.45 61.62, 203.38 35.05, 228.34 7.5 M155.21 88.52 C172.59 70.41, 189.75 49.76, 226.84 7.37 M161.9 89.81 C176.99 70.88, 191.35 53.05, 227.9 12.76 M160.92 88.17 C177.93 69.73, 192.91 52.75, 227.85 12.8 M164.48 88.9 C190.82 63.32, 213.53 35.71, 229.26 18.36 M167.09 88.49 C185.64 67.5, 205.9 43.87, 227.79 17.94 M172.5 87.24 C191.03 67.55, 209.97 43.04, 229.61 22.73 M173.04 89.34 C186.7 71.93, 199.61 57.26, 228.34 23.71 M177.18 88.58 C195.77 64.49, 217.59 41.17, 229.08 31.87 M177.99 89.03 C196.18 65.62, 215.38 44.09, 228.47 30.11 M183.99 88.21 C195.94 76.32, 207.75 60.02, 226.58 38.82 M182.7 87.87 C201.68 68.92, 218.32 47.74, 227.39 36.52 M186.54 87.75 C199.93 74.1, 214.4 61.22, 229.09 42.66 M188.55 89.84 C196.96 77.26, 206.38 67.12, 226.96 43.59 M195.16 89.85 C207.87 73.4, 218.62 58.84, 228.96 47.56 M193.24 88.2 C204.77 75.5, 218.29 60.42, 228.11 49.19 M198.89 88.97 C207.34 77.57, 219.41 67.59, 227.71 54.22 M197.83 89.14 C208.94 77.44, 219.1 66.19, 227.79 54.66 M205.28 90.88 C212.95 79.23, 223.23 69.95, 226.07 62.65 M203.77 90.11 C208.71 82.11, 215.57 75.53, 228.1 60.54 M209.72 87.65 C215.73 81.08, 218.53 74.22, 227.82 67.66 M209.3 89.74 C213.72 85.17, 217.2 79.35, 227.26 66.9 M212.69 88.67 C219.34 84.01, 220.62 79.35, 229.03 73.87 M213.83 89.68 C217.97 83.9, 220.77 79.96, 228.03 73.19 M219.61 88.4 C221.91 86.89, 225.4 84.3, 227.41 79.14 M219.18 88.94 C222.64 85.31, 225.81 82.02, 227.83 80.03 M224.15 88.83 C225.41 88.66, 225.73 87.67, 227.39 85.05 M224.77 89.36 C225.38 88.19, 226.35 86.95, 227.64 85.65" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-0.99 -1.57 C61.8 -0.4, 123.73 -1.4, 226.36 -0.41 M-0.41 0.16 C72.13 -1.53, 145.34 -2.14, 226.7 -0.05 M226.97 1.15 C226.73 27.93, 226.32 56.23, 225.26 87.23 M227.49 0.36 C227.23 30.16, 227.33 58.82, 226.63 87.38 M226.15 87.76 C166.89 89.69, 108.49 87.02, 0.64 87.08 M227.42 87.65 C163.74 88.89, 99.36 88.94, 0.25 86.91 M-1.17 88.19 C0.55 67.98, -0.69 47.82, 1.19 -1.59 M-0.79 87.09 C-1.55 65.7, -0.3 44.07, -0.32 0.24" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(538.4999694824219 445.3334045410156) rotate(0 97.5 15)"><path d="M-1.09 1.35 C66.75 1.92, 132.18 1.74, 193.7 1.48 M0.53 -0.73 C63.53 1.89, 128.73 1.94, 194.89 0.71 M196.44 0.56 C193.17 10.95, 192.91 22.81, 195.65 31.85 M195.92 -0.14 C194.38 7.86, 195.62 16.47, 194.56 30.76 M194.83 30.67 C141.6 31.47, 85.05 29.06, -0.99 30.67 M195.02 30.52 C141.59 30.2, 86.12 29.55, -0.91 29.71 M-1.61 28.24 C1.28 21.3, 2.11 7.1, 0.09 -0.62 M0.63 29.78 C-0.14 18.18, -0.7 7.7, -0.9 -0.18" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(551.4999694824219 450.3334045410156) rotate(0 84.5 10)"><text x="84.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">uint32 data_offset;</text></g><g transform="translate(609.4999694824219 492.6667175292969) rotate(0 11 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[1]</text></g><g stroke-linecap="round" transform="translate(520.6666564941406 513.3334045410156) rotate(0 113.8333740234375 30.333328247070312)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M0.22 6.72 C1.95 4.11, 3.36 2.69, 5.71 0.42 M0.02 6.12 C1.38 4.48, 2.68 2.97, 4.91 0.53 M0.13 12.8 C5.48 8.64, 9.34 1.75, 9.94 -0.4 M0.76 12.01 C3.08 9.59, 5.15 6.8, 9.92 0.61 M0.33 19.93 C5.13 13.55, 9.89 9.33, 13.85 -0.69 M-0.7 17.68 C6.41 12.75, 9.99 6.7, 15.92 1.01 M-0.81 23.71 C5.4 17.3, 7.56 15.53, 20.91 -1.77 M0.15 24.02 C6.93 17.2, 11.16 11.85, 20.58 -0.37 M0.23 30.35 C7.86 23.88, 15.23 15.49, 25.49 2.17 M-0.55 30.33 C7.09 24.26, 13.55 15.75, 27.01 0.17 M-1.7 38.2 C12.35 21.98, 21.82 8.58, 32.8 1.86 M-1.2 37.06 C7.02 29.07, 13.07 20.95, 31.42 -0.03 M-1.73 43.43 C11.07 30.39, 24.58 17.21, 38.26 2.1 M1.11 42.41 C13.13 27.68, 25.11 13.08, 37.3 0.49 M1.84 49.52 C15.81 30.9, 32.49 12.02, 41.44 -0.99 M0.19 49.05 C10.93 34.29, 23.42 20.75, 42.29 -0.27 M0.92 53.27 C15.95 36.39, 32.06 18.09, 45.6 1.27 M1.04 55.11 C11.26 42.8, 20.66 30.71, 46.59 0.6 M1.08 62.07 C12.85 46.06, 29.54 28.47, 51.68 -0.6 M0.2 60.66 C18.87 41.17, 36.13 19.91, 53.78 -0.72 M4.82 61.06 C22.92 39.17, 41.86 21.01, 57.8 -1.02 M5.84 59.99 C22.39 40.54, 39.99 19.67, 57.24 -0.4 M11.32 60.57 C29.15 39.12, 44.97 22.75, 65.27 -2.1 M10.44 60.15 C23.88 46.33, 37.9 30.36, 63.03 -0.58 M18.19 59.16 C35.96 36.77, 54.49 16.16, 70.05 -0.36 M15.39 61.13 C34.84 39.03, 52.43 18.9, 68.2 1.02 M19.73 59.01 C34.17 47.52, 46.1 33.05, 72.82 -1.52 M22.1 60.37 C31.67 47.88, 42.61 35.87, 73.74 -0.58 M28.91 59.09 C45.5 41.48, 63.47 22.22, 78.4 0.8 M26.9 61.06 C45.27 37.93, 64.38 16.71, 78.93 0.82 M32.88 60.44 C43.05 46.24, 54.11 35.81, 85.82 -1.75 M31.41 60.54 C51.16 38.11, 70.64 15.31, 84.19 -1.07 M38.96 59.43 C57.21 34.86, 77.24 13.72, 91.77 1.11 M37.39 60.7 C56.86 39.69, 75.36 16.98, 89.5 -0.6 M42.18 61.02 C59.91 41.72, 75.53 23.75, 96.64 -0.57 M43.17 60.31 C62.38 38.49, 83.89 14.65, 95.21 0.1 M47.22 59.94 C66.95 37.12, 88.4 16.54, 99.98 0.36 M48.46 61.42 C65.29 41.36, 83.7 21.59, 100.51 -0.4 M51.94 62.04 C72.59 38.28, 93 16.24, 106.52 1.37 M52.76 61.76 C69.91 41.43, 86.43 21.73, 106.2 -0.54 M56.75 62.21 C75.37 40.21, 96.03 20.62, 109.68 -0.51 M57.58 61.8 C77.13 40.07, 95.13 19.59, 111.15 0.69 M63.34 61.91 C82.77 39.77, 101.69 17.04, 116.91 1.31 M64.09 61.43 C78.38 41.34, 94.47 23.92, 116.46 0.79 M69.5 62.71 C79.47 46.28, 91.25 31.6, 120.45 0.52 M68.77 60.56 C82.63 44.21, 98.17 27.51, 121.16 0.4 M74.44 60.19 C92.42 38.57, 108.86 18.12, 128.12 -0.65 M73.66 60.27 C90.46 41.59, 106.56 24.42, 127.82 -0.02 M78.3 61.29 C91.13 46.22, 102.4 35.37, 132.7 -1.38 M78.66 61.15 C94.7 45, 107.56 27.12, 132.83 0.87 M84.15 61.52 C101.17 39.47, 121.58 21.32, 139.37 -1.04 M84.51 59.69 C101.97 41.79, 120.15 20.68, 136.71 -0.32 M89.5 62.2 C106.95 40.85, 126.66 16.86, 143.74 -1.92 M89.07 60.68 C107.81 42.91, 123.07 23.2, 143.03 0.69 M96.28 59.72 C109.91 46.39, 120.91 28.04, 147.38 0.01 M96.27 61.53 C105.77 47.04, 117.7 34.88, 148.77 0.19 M102.36 62.78 C119.76 41.93, 135.18 20.89, 155.75 0.32 M100.41 60.71 C111.1 47.1, 122.9 34.81, 153.19 -1.12 M107.52 61.68 C121.22 43.76, 139.05 24.7, 157.77 -0.54 M107.1 60.06 C121.85 43.77, 136.09 25.7, 158.21 0.25 M112.98 61.52 C128.12 40.24, 145.07 23.46, 163.78 -0.11 M111.62 61.23 C125.21 45.01, 138.25 28.15, 165.3 -1.08 M115.4 59.46 C132.65 43.48, 149.08 25.97, 169.04 -0.58 M117.75 60 C130.81 45.24, 145.63 28.25, 169.81 1.05 M122.36 62 C139.91 43.14, 155.14 21.91, 175.75 0.43 M122.22 60.69 C139.6 39.92, 158.28 17.03, 175.9 0.7 M126.37 62.21 C146.2 39.89, 162.04 21.45, 180.54 -0.87 M127.52 60.5 C144.76 40.24, 161.44 20.37, 180.89 0.21 M132.37 60.97 C154.25 35.36, 174.41 11.53, 184.47 -1.24 M132.31 59.94 C146.89 45.94, 158.96 31.65, 186.12 0.56 M139.72 60.23 C155.75 37.86, 173.26 15.98, 192.53 -1.07 M138.28 61.14 C154.97 40.12, 173.06 19.98, 191.35 -0.22 M141.73 60.28 C159.4 45.6, 170.79 28.57, 195.63 0.78 M142.53 60.29 C160.88 40.04, 179.66 19.71, 195.62 -0.73 M147.63 60.94 C169.13 38.65, 187 15.39, 202.11 0.3 M148.45 59.96 C165.31 41.92, 181.45 21.95, 201.65 0.26 M154.07 58.9 C171.09 41.16, 190.51 19.79, 207.76 1.53 M154.08 61.5 C167.87 43.62, 184.08 27.56, 206.66 0.06 M159.15 60.87 C168.84 47.14, 182.63 33.78, 211.28 1.85 M159.01 61.42 C171.65 48.11, 181.4 34.05, 212.81 0.58 M165.88 60.94 C175.36 45.73, 186.62 33.78, 216.3 1.18 M164.73 61.74 C182.57 38.91, 200.5 17.06, 218.03 0.57 M167.56 62.45 C181.06 47.96, 195.3 33.34, 222.89 -0.7 M168.87 61.17 C188.18 39.28, 209.51 15.06, 222.41 0.11 M174.53 59.62 C185.58 46.82, 198.2 35.04, 228.9 1.78 M174.83 61.64 C191.38 42.73, 205.21 24.86, 228.43 -0.35 M180.97 62.96 C198.61 42.83, 214.49 20.65, 227.45 7.55 M179.45 61.04 C189.61 48.78, 200.75 38.53, 227.35 6.7 M186.24 61.31 C197.67 45.85, 210 33.96, 229.54 12.3 M185.26 60.25 C196.75 48.34, 207.86 35.44, 228.61 12.39 M190.4 63.07 C202.12 50.09, 210.97 39.66, 229.57 16.57 M190.78 61.57 C205.39 44.69, 218.04 29.78, 228.33 18.6 M196.15 61.47 C201.99 53.83, 208.79 43.05, 226.12 24.98 M195.48 61.06 C206.84 50.99, 215.8 39.95, 226.91 24.42 M200.4 59.82 C206.38 55.79, 212.14 46.36, 227.32 32.19 M202.09 60.96 C210.34 51.45, 217.57 40.62, 227.23 31.2 M208.23 60.72 C212.1 53.87, 220.09 48.98, 229.58 36.46 M207.51 60.01 C212.09 54.76, 217.12 49.02, 228.37 37.16 M212.4 59.38 C215.95 55.32, 224.05 47.47, 228.39 41.12 M211.18 61.88 C216.11 56.52, 219.16 52.61, 227.18 42.11 M219.01 60.75 C220.69 56.78, 225.72 51.17, 227.78 48.56 M217.87 61.31 C219.94 57.81, 221.5 55.61, 228.5 48.47 M221.84 61 C223.68 59.8, 224.51 57.41, 227.65 54.36 M222.52 61.15 C223.83 59.36, 225.37 58.1, 227.87 55.23" stroke="#15aabf" stroke-width="0.5" fill="none"></path><path d="M-1.6 -1.22 C69.6 2, 141.66 2.26, 227.09 -0.3 M0.45 -0.48 C86.29 0.49, 173.22 0.2, 228.35 0.27 M225.85 -1.85 C229.09 21.08, 230.08 42.2, 228.55 60.67 M226.81 0.72 C228.31 15.66, 227.23 33.89, 228.22 60.71 M228.06 60.8 C173.62 59.59, 123.21 59.63, 0.66 60.68 M227.4 59.88 C141.63 59.52, 54.53 60.55, -0.45 60.63 M1.74 62.59 C-0.14 47.01, 0.73 33.74, -1.71 1.41 M-0.36 60.43 C-0.06 45.98, -1.21 31.17, 0.59 -0.68" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(609.9999694824219 557.6669921875) rotate(0 15.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">[...]</text></g><g stroke-linecap="round" transform="translate(540.1665954589844 521.3334045410156) rotate(0 97.5 15)"><path d="M1.96 0.91 C41.13 0.69, 84.78 1.01, 193.76 -0.53 M-0.72 0.71 C69.88 -0.45, 139.95 -0.41, 195 0 M193.66 1.09 C195.42 7.79, 195.65 20.29, 193.91 31.24 M195.6 0 C195.58 7.79, 195.92 14.08, 195.86 29.64 M194.24 28.3 C120.27 28.88, 42.61 29.86, -1.83 31.52 M195.24 29.93 C140.28 31.77, 86.52 31.93, 0.96 29.1 M1.35 30.31 C1.63 22.21, 1.92 15.09, 1.3 0.08 M-0.39 30.08 C-0.01 24.4, 0.04 17.53, 0.36 0.77" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(553.1665954589844 526.3334045410156) rotate(0 84.5 10)"><text x="84.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">uint32 data_offset;</text></g><g stroke-linecap="round" transform="translate(956.6665954589844 151.8333511352539) rotate(0 48.833343505859375 15.000007629394531)"><path d="M0 0 C0 0, 0 0, 0 0 M0 0 C0 0, 0 0, 0 0 M-0.73 6.57 C1.07 5.28, 2.51 3.49, 5.57 -0.43 M-0.64 6.24 C1.65 4.2, 2.86 2.32, 4.96 0.72 M-0.46 13.09 C2.58 7.48, 8.22 3.37, 10.78 -1.59 M-0.07 12.35 C2.4 9.22, 5.24 5.79, 10.87 -0.58 M1.6 17.23 C5.06 13.74, 8.24 5.33, 15.86 1.83 M-0.77 17.52 C3.99 13.95, 9.11 8.19, 14.97 0.18 M-0.42 24.75 C3.56 18.53, 11.6 11.92, 21.96 0.97 M0.6 24.66 C7.23 15.68, 15.1 7.4, 20.62 -0.92 M1.4 28.8 C7.16 21.02, 15.12 14.08, 25.94 -1.54 M-0.73 31.19 C6.43 22.83, 13.22 14.13, 25.59 0.43 M4.07 32.03 C12.27 24.34, 18.19 16.48, 31.04 -1.62 M6.16 30.63 C11.18 22.93, 16.67 17.01, 32.64 0.3 M9.26 30.25 C19.24 20.39, 29.78 8.67, 38.43 -0.86 M10.5 31.27 C20.25 17.7, 31.8 6.42, 35.94 0.81 M17.09 31.55 C23.48 18.41, 32.35 10.05, 41.22 -1.31 M16.44 30.37 C24.2 19.64, 33.41 11.61, 41.93 0.47 M20.36 31.59 C30.14 20.89, 37.51 11.29, 47.95 -0.17 M22.12 30.62 C32.35 18.86, 41.32 7.91, 47.73 0.57 M26.53 30.84 C34.95 20.69, 39.61 14.79, 52.57 -0.58 M26.64 30.44 C37.24 18.01, 47.09 6.87, 53.97 -0.45 M33.25 31.85 C43.01 18.93, 50.58 9.52, 57.98 1.65 M32.36 30.44 C39.41 22.71, 45.51 15.42, 57.22 -0.62 M38.36 28.49 C41.27 25.6, 49.11 18.95, 62 -0.75 M37.81 29.75 C42.83 24.35, 48.33 17.46, 62.81 -0.06 M43.36 31.2 C50.31 22.29, 57.53 12.64, 68.89 -1.19 M42.03 30.39 C49.46 23.13, 53.92 15.94, 69.25 -0.63 M47.45 28.23 C59.25 18.85, 65.68 8.34, 75.32 -2.04 M47.5 29.68 C56.82 19.86, 65.22 9.45, 75.07 0.48 M55 30.92 C57.76 23.44, 62.94 18.94, 77.92 -1.32 M52.48 30.56 C63.04 19.02, 72.45 6.2, 79.22 1.1 M57.55 30.91 C68.76 16.6, 78.96 7.64, 83.21 0.48 M57.88 30.03 C65.5 21.47, 71.97 13.54, 85.92 0.45 M65.33 29.44 C72.12 23.72, 77.86 13.86, 91.18 1.73 M63.65 29.48 C70.9 22.97, 76.62 17.36, 89.08 -0.45 M69.26 30.53 C75.97 22.12, 83.57 16.96, 97.23 0.84 M69.65 29.06 C77.32 22.44, 83.04 13.29, 95.11 -0.44 M72.42 30.29 C80.74 23.16, 88.55 16.28, 98.36 3.07 M74.03 30.1 C83.29 19.79, 92.43 9.88, 100.04 1.68 M80.09 30.16 C83.97 23.45, 92.98 17.74, 98.57 6.51 M80.08 29.44 C86.16 24.49, 90.99 17.82, 99.72 8.27 M83.2 30.15 C88.85 25.49, 91.93 19.4, 99.45 14.5 M84.66 29.83 C89.47 25.1, 95.56 18.37, 99.32 14.41 M91.22 30.74 C93.38 26.32, 97.47 23.11, 100.11 20.88 M90.25 30.9 C92.99 27.86, 95.69 24.13, 98.74 20.44 M96.21 30.36 C96.21 29.35, 97.31 28.39, 99.84 25.54 M95.52 30.27 C96.91 28.95, 97.68 27.79, 99.65 25.59" stroke="#868e96" stroke-width="0.5" fill="none"></path><path d="M0.14 0.18 C20.58 -0.9, 39.55 1.37, 97.22 0.67 M0.92 0.36 C36.87 0.12, 76.39 -0.78, 97.96 -0.36 M98.12 1.71 C96.66 8.49, 99.41 18.23, 96.98 30.82 M97.24 -0.09 C98.73 8.87, 98.11 16.78, 96.77 29.88 M97.39 30.61 C78.3 28.44, 55.64 28.48, 0.6 29.48 M98.19 29.24 C62.78 28.22, 29.15 29.61, 0.29 30 M0.75 29.59 C1.59 22.89, 1.06 18.36, -1.52 1.99 M-0.21 30.36 C-0.98 20.74, -0.03 10.75, 0.53 0.88" stroke="#000000" stroke-width="1" fill="none"></path></g><g mask="url(#mask-Y_Dw9hCEvutA3MjjHfyJK)" stroke-linecap="round"><g transform="translate(729.9999694824219 540.0000610351562) rotate(0 108.36802069720352 -193.44017890523946)"><path d="M-0.54 -0.42 C74.38 -131.13, 149.06 -263.34, 217.27 -386.81 M-0.11 -0.07 C64.3 -111.41, 126.4 -222.97, 216.82 -385.78" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(729.9999694824219 540.0000610351562) rotate(0 108.36802069720352 -193.44017890523946)"><path d="M211.01 -357.01 C213.59 -364.41, 216.48 -375.75, 217.08 -387.57 M211.86 -356.29 C214 -363.73, 214.39 -372.93, 216.18 -385.48" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(729.9999694824219 540.0000610351562) rotate(0 108.36802069720352 -193.44017890523946)"><path d="M193.07 -366.98 C201.75 -371.06, 210.75 -379, 217.08 -387.57 M193.93 -366.26 C201.15 -370.94, 206.71 -377.27, 216.18 -385.48" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask id="mask-Y_Dw9hCEvutA3MjjHfyJK"><rect x="0" y="0" fill="#fff" width="1047.142933332968" height="1025.9262367325396"></rect><rect x="812.0714514076949" y="337.0369731864646" fill="#000" width="53" height="20" opacity="1"></rect></mask><g transform="translate(812.0714514076949 337.0369731864646) rotate(0 26.2965387719305 9.522908943452194)"><text x="26.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">offset</text></g><g transform="translate(200.33331298828125 428.6667175292969) rotate(0 82 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMGlobalInstance</text></g><g stroke-linecap="round" transform="translate(190 455.33331298828125) rotate(0 90.16665649414062 23.333389282226562)"><path d="M2 -1.41 C60.79 1.26, 121.36 2.12, 179.34 0.68 M180.3 1.12 C178.89 15.02, 179.51 32.53, 179.39 48.06 M181.31 46.25 C141.11 43.46, 101.78 46.22, 0.78 45.19 M-0.99 46.04 C-1.15 29.65, -1.59 12.07, -1.7 -1.58" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g mask="url(#mask-1QAmzR8Zkk8scUA3tqI0k)" stroke-linecap="round"><g transform="translate(557.3333129882812 376.0000305175781) rotate(0 -90.69601062624105 38.22839422523566)"><path d="M-1.39 1.06 C-61.32 24.14, -119.9 51.02, -180.82 74.6 M-0.57 0.65 C-60.45 25.03, -121.91 51.15, -179.35 75.8" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(557.3333129882812 376.0000305175781) rotate(0 -90.69601062624105 38.22839422523566)"><path d="M-158.86 56.35 C-165.41 61.74, -170.33 70, -180.96 75.27 M-158.03 55.94 C-164.13 61.98, -171.78 69.42, -179.49 76.48" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(557.3333129882812 376.0000305175781) rotate(0 -90.69601062624105 38.22839422523566)"><path d="M-150.79 75.22 C-160.19 74.13, -167.87 75.95, -180.96 75.27 M-149.97 74.81 C-158.82 74.38, -169.23 75.36, -179.49 76.48" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask id="mask-1QAmzR8Zkk8scUA3tqI0k"><rect x="0" y="0" fill="#fff" width="836.5506564180245" height="551.1247240081348"></rect><rect x="422.7246412734096" y="403.56237726285644" fill="#000" width="90" height="20" opacity="1"></rect></mask><g transform="translate(422.72464127340965 403.56237726285644) rotate(0 43.91266108863056 10.666047479957342)"><text x="45" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">when import</text></g><g stroke-linecap="round" transform="translate(172.99993896484375 373.6666564941406) rotate(0 118.16671752929688 98.16668701171875)"><path d="M-0.45 0.1 C73.77 -1.22, 148.86 1.01, 235.5 0.09 M235.44 0.97 C234.46 75.19, 236.96 149.92, 235.62 194.61 M236.52 197.1 C142.22 195.91, 51.5 195.36, -1.12 195.88 M0.15 197.65 C1.03 139.69, -1.37 87.58, 1.84 0.61" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(165.333251953125 350.00006103515625) rotate(0 119.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance (second)</text></g><g transform="translate(11.666717529296903 22.33343505859375) rotate(0 85.5 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#d9480f" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstance</text></g><g stroke-linecap="round" transform="translate(10 42.666778564453125) rotate(0 101.00001525878908 62.33332824707031)"><path d="M0.05 -0.01 C79.52 2.89, 159.35 0.92, 203.36 0.85 M-0.12 0.28 C67.54 1.41, 135.68 1.33, 202.11 -0.08 M202.32 -1.77 C201.15 30.92, 201.82 57.96, 200.55 124.31 M201.6 0.86 C202.34 44.55, 201.85 89.09, 202.31 124.54 M201.95 124.26 C155.11 121.61, 106.88 122.96, 0.81 125.38 M201.67 124.33 C128.32 124.69, 53.21 123.82, 0.72 125.44 M0.25 124.34 C-0.66 91.45, 0.58 58.63, 1.26 -0.11 M0.49 124.96 C0.21 92.93, -0.68 59.93, 0.63 -0.52" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(219.66662597656253 173.00010681152344) rotate(0 108.99999999999999 9.5)"><text x="0" y="15" font-family="Cascadia, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">WASMModuleInstanceExtra</text></g><g stroke-linecap="round" transform="translate(198.6666259765625 201.66677856445312) rotate(0 128.16668701171875 45.666656494140625)"><path d="M1.43 0.51 C62.2 -0.81, 126.01 -0.38, 256.94 -0.28 M-0.42 0.28 C67.2 -0.6, 133.06 -0.54, 256.43 -0.14 M256.41 1.79 C256.78 22.02, 256.29 41.01, 257.42 90.01 M255.83 -0.59 C254.75 30.05, 255.48 58.76, 257.27 91.19 M257.6 92.16 C173.62 92.85, 92.89 91.98, -0.82 90.33 M255.85 91.56 C204.51 94.01, 152.16 93.75, -0.2 91.29 M-0.72 90.75 C0.88 58.64, -1.12 24.92, 1.98 1.36 M0.52 91.69 C-1.04 68.23, -1.07 45.43, -0.53 -0.54" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(206.33343505859378 220.66677856445312) rotate(0 121.50003051757811 15.5)"><path d="M1.07 -0.31 C70.02 3.51, 138.62 2.15, 242.4 1.29 M0 -0.6 C97.56 1.58, 193.5 0.99, 243.07 -0.62 M241.85 -1.2 C241.98 9.45, 243.77 20.97, 244.39 30.75 M243.87 0.89 C242.91 7.29, 242.42 16.22, 242.26 31.68 M244.52 32.07 C154.34 31.52, 62.83 31.49, 1.26 29.56 M242.93 30.71 C156.69 30.27, 72.05 29.27, 0.56 30.9 M0.58 31.05 C-1.02 20.75, 1.01 11.77, -0.13 -0.73 M-0.49 31.23 C0.29 20.43, 0.11 10.22, -0.05 -0.29" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(437.31002648858714 227.33351135253912) rotate(0 40.892993485752356 -50.4587129476586)"><path d="M1 0.17 C18.42 -20.46, 34.57 -45.01, 81.11 -99.74 M0.67 -0.1 C29.61 -36, 58.28 -71.39, 79.82 -101.09" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(437.31002648858714 227.33351135253912) rotate(0 40.892993485752356 -50.4587129476586)"><path d="M72.08 -72.22 C73.81 -77.11, 73.79 -85.57, 80.34 -100.6 M71.76 -72.48 C74.78 -83.12, 78.12 -93.29, 79.04 -101.94" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(437.31002648858714 227.33351135253912) rotate(0 40.892993485752356 -50.4587129476586)"><path d="M55.68 -84.54 C61.18 -86.59, 64.84 -92.27, 80.34 -100.6 M55.35 -84.8 C64.06 -91.11, 73.18 -96.94, 79.04 -101.94" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(206.00000000000003 260.33343505859375) rotate(0 122.16665649414061 15)"><path d="M-0.89 1.45 C94.1 0.94, 188.06 0.31, 244.3 0.04 M0.33 -0.62 C78.61 -1.13, 155.14 -1.93, 244.57 0.52 M242.81 -0.3 C244.66 5.77, 246.14 15.88, 243.48 30.25 M245.2 -0.49 C243.99 9.03, 244.25 15.66, 244.84 29.96 M243.03 30.24 C174.41 30.56, 103.07 30.08, -0.13 28.5 M243.85 29.42 C158.44 29.01, 72.66 29.56, 0.28 29.32 M-1.15 31.42 C1.69 23.14, 0.89 17.03, -0.62 1.42 M0.15 30.28 C-0.6 19.93, -0.07 10.39, 0.11 -0.67" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(245.66665649414062 265.33343505859375) rotate(0 82.5 10)"><text x="82.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">uint32 global_count;</text></g><g stroke-linecap="round" transform="translate(67.66668701171878 118.00018310546875) rotate(0 57.5 15.166679382324219)"><path d="M0.1 -0.15 C42.45 0.05, 89.54 -1.19, 113.83 -1.4 M-0.27 0.34 C32.95 -0.85, 67.31 -0.76, 114.42 0.71 M115.06 -0.62 C116.37 11.95, 115.14 24.49, 115.3 30.89 M114.58 0.11 C114.18 6.85, 115.33 14.51, 115.7 30.01 M113.03 29.73 C72.76 29.28, 27.48 29.85, 1.45 29.6 M114.88 30.61 C70.28 30.66, 25.08 30.84, -0.99 30.28 M-0.01 28.91 C-0.74 20.87, 1.08 15.08, -0.12 0.92 M-0.23 29.42 C-0.55 23.3, -0.36 17.12, -0.14 0.84" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(119.66668701171878 123.16686248779297) rotate(0 5.5 10)"><text x="5.5" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">e</text></g><g stroke-linecap="round" transform="translate(148.00000000000003 125.6668701171875) rotate(0 6.833343505859375 6.166664123535156)"><path d="M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M3.44 9.88 C5.46 6.5, 6.18 5.94, 9.98 2.48 M2.86 9.42 C4.89 6.55, 6.97 4.55, 9.69 1.39 M6.58 12.83 C8.01 11.17, 8.11 9.27, 12.4 5.98 M6.2 11.99 C8.68 9.72, 10.55 6.74, 12.25 5.37" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M6.35 -0.5 C9.4 1.86, 11.59 3.82, 14.41 6.68 M7.26 -0.16 C8.49 1.86, 10.83 3.57, 14.11 6.83 M13.95 7.16 C11.75 9, 8.66 10.3, 6.81 11.92 M13.48 6.78 C11.79 8.95, 9.5 10.46, 6.6 12.27 M6.48 11.67 C4.8 10.29, 3.17 10.18, -0.39 7.23 M6.9 12.43 C5.7 11.1, 3.88 10.27, 0.09 7 M-0.57 7.94 C2.33 4.94, 5.12 2.16, 7.83 -0.24 M-0.08 7.42 C2.06 5, 3.59 3.3, 6.98 -0.17" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round"><g transform="translate(155.33337402343753 130.33343505859375) rotate(0 23.01894331293626 34.688096238300204)"><path d="M0.24 -0.23 C13.08 19.18, 24.78 37.25, 45.87 67.69 M0.1 -0.01 C12.45 20.33, 25.95 41.78, 45.93 69.61" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(155.33337402343753 130.33343505859375) rotate(0 23.01894331293626 34.688096238300204)"><path d="M21.62 52.13 C28.56 57.66, 34.85 61.93, 46.68 67.63 M21.49 52.36 C27.88 57.13, 35.32 63.12, 46.74 69.55" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(155.33337402343753 130.33343505859375) rotate(0 23.01894331293626 34.688096238300204)"><path d="M38.45 40.39 C41.06 48.95, 42.92 56.31, 46.68 67.63 M38.32 40.61 C39.72 48.77, 42.19 58.22, 46.74 69.55" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(551.3333740234375 331.3333435058594) rotate(0 -71.78919714330704 19.427308002237908)"><path d="M0.44 1.24 C-31.67 8.53, -64.18 17, -144.01 37.51 M-0.14 -0.94 C-30.89 8.04, -60.67 16.48, -143.19 39.8" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(551.3333740234375 331.3333435058594) rotate(0 -71.78919714330704 19.427308002237908)"><path d="M-118.41 23.49 C-123.95 25.13, -130.02 28.78, -143.13 37.99 M-118.99 21.31 C-124.76 25.94, -129.76 29.88, -142.3 40.28" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(551.3333740234375 331.3333435058594) rotate(0 -71.78919714330704 19.427308002237908)"><path d="M-112.83 43.23 C-119.49 40.55, -126.79 39.85, -143.13 37.99 M-113.41 41.06 C-120.15 41.6, -126.3 41.44, -142.3 40.28" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(549.1666564941406 327.1666793823242) rotate(0 6.833343505859375 6.166664123535156)"><path d="M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M2.72 8.49 C5.8 7.55, 6.93 5.19, 9.19 1.67 M3.62 9.75 C4.95 7.98, 6.15 5.71, 9.39 1.54 M6.69 11.54 C8.55 10.59, 9.79 8.29, 12 4.84 M6.23 12.05 C7.43 10.13, 9.87 7.96, 12.54 5.66" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M6.55 0.78 C9.36 2.85, 11.04 4.05, 14.23 6.7 M7.3 -0.25 C8.88 2.03, 10.84 4.85, 13.93 7.46 M13.73 7.68 C12.04 9.53, 8.5 10.95, 7.68 13.11 M13.36 7.12 C11.66 9.05, 9.55 10.59, 6.72 12.27 M7.51 12.35 C4.03 9.64, 2.35 8.95, -0.21 6.52 M7.4 11.92 C4.46 10.45, 2.55 8.72, 0.16 6.6 M0.8 6.98 C3.17 4.62, 5.63 1.08, 6.77 -0.2 M-0.26 7.16 C1.92 4.84, 3.13 3.8, 6.62 0.47" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(547.1666564941406 371.1666793823242) rotate(0 6.833343505859375 6.166664123535156)"><path d="M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M2.29 10.01 C5.03 7.56, 6.35 5.49, 9.57 1.46 M3.54 9.48 C6 6.33, 7.95 3.79, 9.44 1.77 M5.73 12.67 C8.2 10.49, 9.32 8.42, 11.72 5.05 M6.24 11.66 C8.55 9.75, 10.63 7.03, 12.55 5.63" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M7.78 0.29 C9.82 2.26, 11.06 5.19, 13.36 7.14 M6.75 -0.27 C9.23 2.2, 12.37 5.52, 14.12 7.18 M14.34 7.59 C12.03 8.2, 9.29 11.47, 7.77 12.44 M13.79 7.04 C11.7 8.86, 9.21 10.45, 6.94 12.61 M7.02 11.89 C4.39 11.38, 3.77 9.32, -0.48 7.42 M6.59 12.23 C4.87 11.19, 2.85 9.28, -0.4 7.24 M-0.02 7.67 C2.04 5.66, 2.91 2.84, 6.8 -0.37 M0.16 7.14 C2.42 3.8, 5.97 1.18, 7.47 -0.15" stroke="#000000" stroke-width="1" fill="none"></path></g><g stroke-linecap="round" transform="translate(23.666778564453153 64.00006103515625) rotate(0 90 15.5)"><path d="M-0.66 1.22 C43.68 -0.24, 90.86 -0.14, 179.25 0.93 M-0.41 0.49 C46.13 0.48, 92.89 0.72, 180.45 0.15 M181.18 0.22 C179.51 5.59, 180.64 11.92, 178.93 30.77 M179.76 0.07 C180.35 9.41, 180.53 18.88, 180.44 31.06 M180.11 30.53 C126.6 29.17, 72.73 29.43, 1.01 31.92 M179.02 31.11 C135.98 32.92, 93.29 32.11, 0.85 31.9 M1.8 31.5 C-1.23 24.12, 1.89 12.68, -1.44 1.48 M0.71 31.46 C-0.16 19.63, -0.14 7.48, -0.48 -0.51" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(31.666778564453153 69.50006103515625) rotate(0 82 10)"><text x="82" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="middle" style="white-space: pre;" direction="ltr">uint8 * global_data</text></g><g stroke-linecap="round"><g transform="translate(201.3333740234375 73.66664123535156) rotate(0 376.88916503278216 -8.94848059563438)"><path d="M0.7 -1.18 C64.98 -4.48, 260.65 -18.36, 386.22 -18.71 C511.8 -19.06, 692.56 -6.07, 754.16 -3.29 M-0.38 0.82 C63.78 -1.84, 260.29 -17.14, 385.87 -17.63 C511.45 -18.12, 691.9 -4.38, 753.09 -2.13" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(201.3333740234375 73.66664123535156) rotate(0 376.88916503278216 -8.94848059563438)"><path d="M722.43 8.5 C732.85 2.41, 743.81 2.19, 754.65 -2.78 M723.53 6.63 C732.57 3.65, 739.75 0.79, 752.51 -1.39" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(201.3333740234375 73.66664123535156) rotate(0 376.88916503278216 -8.94848059563438)"><path d="M723.53 -11.99 C733.75 -10.94, 744.33 -4.02, 754.65 -2.78 M724.63 -13.86 C733.21 -11.17, 740.09 -8.35, 752.51 -1.39" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(193.50006103515628 68.16667938232422) rotate(0 6.833343505859375 6.166664123535156)"><path d="M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M3.98 9.18 C4.88 7.31, 7.9 3.95, 9.81 2.34 M3.45 9.11 C5.37 7.66, 6.66 5.53, 9.7 1.6 M5.9 11.26 C6.99 10.12, 9.21 8.41, 12.48 4.51 M6.35 12.22 C8.14 10.49, 9.36 8.66, 12.25 5.07" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M6.56 0.15 C10.46 2.75, 12.79 5.49, 14.25 6.1 M6.78 0.09 C8.76 1.6, 9.54 3.06, 14.08 7.47 M14.01 7.64 C11.46 9.2, 8.48 10.6, 6.22 13.16 M13.5 6.69 C11.86 8.03, 10.85 9.09, 6.74 12.37 M7.7 11.89 C3.89 9.97, 1.26 8.04, -0.59 6.2 M7.18 12.52 C5.17 10.51, 2.83 9.47, -0.18 6.59 M0.71 7.11 C2.1 5.12, 5.04 0.76, 7.82 -0.89 M0.34 6.53 C2.79 5, 5.06 1.68, 6.77 -0.25" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(228.49993896484375 524.3332214355469) rotate(0 49.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">global_data</text></g><g stroke-linecap="round" transform="translate(189.1666259765625 512.3331451416016) rotate(0 90.16665649414062 23.333389282226562)"><path d="M-0.06 -1.81 C69.05 1.17, 133.03 -1.43, 181.43 -0.61 M181.36 1.69 C179.85 18.36, 179.04 35.55, 181.59 47.65 M181.74 46.18 C110.81 44.67, 41.79 43.81, 1.97 48.08 M-1.91 47 C0.87 30.33, 1.49 17.36, 1.81 -1.72" stroke="#000000" stroke-width="1.5" fill="none" stroke-dasharray="8 9"></path></g><g transform="translate(249.99993896484375 466.9999084472656) rotate(0 27.5 10)"><text x="0" y="14" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">globals</text></g><g stroke-linecap="round"><g transform="translate(220.6666259765625 479.9999084472656) rotate(0 -35.06402359574449 29.23212979414967)"><path d="M-0.5 0.55 C-12.15 3.21, -65.26 5.95, -70.59 15.64 C-75.92 25.33, -38.92 51.41, -32.48 58.67 M1.44 -0.21 C-10.21 2.69, -65.24 7.71, -70.98 17.16 C-76.71 26.62, -39 49.85, -32.97 56.5" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(220.6666259765625 479.9999084472656) rotate(0 -35.06402359574449 29.23212979414967)"><path d="M-59.29 48.97 C-53.7 50.42, -46.51 53.61, -31.55 55.9 M-60 47.99 C-49.32 51.71, -39.06 54.94, -33.47 56.08" stroke="#000000" stroke-width="1" fill="none"></path></g><g transform="translate(220.6666259765625 479.9999084472656) rotate(0 -35.06402359574449 29.23212979414967)"><path d="M-46.92 33.64 C-44.36 38.74, -40.16 45.63, -31.55 55.9 M-47.63 32.66 C-41.69 42.18, -36.17 51.29, -33.47 56.08" stroke="#000000" stroke-width="1" fill="none"></path></g></g><mask></mask><g stroke-linecap="round" transform="translate(432.91673278808594 219.6668472290039) rotate(0 6.833343505859375 6.166664123535156)"><path d="M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M0.19 6.79 C0.19 6.79, 0.19 6.79, 0.19 6.79 M4.05 10.29 C6.17 7.33, 6.84 3.75, 9.08 2.09 M3.7 9.35 C4.68 7.39, 5.78 6.43, 9.88 2.27 M6.3 11.14 C8.42 10.69, 10.2 7.43, 12.99 4.98 M6.49 12.18 C8.37 10.13, 10.22 7.36, 12.04 5.36" stroke="#be4bdb" stroke-width="0.5" fill="none"></path><path d="M7.78 -0.36 C8.84 1.35, 9.97 2.98, 13.71 6.83 M6.85 0.47 C9.26 2.31, 10.44 4.32, 13.82 6.56 M14.34 7.45 C11.77 8.53, 10.07 9.92, 7.51 11.8 M13.69 7.39 C11.99 8.56, 9.76 9.69, 7.36 12.73 M7.79 11.79 C5.42 11.4, 2.84 9.11, -0.25 6.73 M7.26 12.07 C4.38 10.64, 1.74 8.28, -0.39 7.39 M-0.57 7.26 C2.63 5.32, 4.57 1.74, 7.42 0.43 M0.44 6.51 C1.59 5.03, 3.59 3.8, 7.41 0.4" stroke="#000000" stroke-width="1" fill="none"></path></g></svg> \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_exports.MD b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_exports.MD
new file mode 100644
index 000000000..70708cde3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_exports.MD
@@ -0,0 +1,22 @@
+# Wasm exports
+The internal data structure for Wasm exports:
+![](./images/wasm_exports.svg)
+
+## Setup exports for Module
+The array data structure pointed by `WASMModule::exports` is setup during loading a module. Basically the runtime will load the exports sections from the module file content, and construct an array of C struct `WASMExport`.
+
+A `WASMExport` item contains three elements that map the Wasm file exports section structure:
+- name: the name shown to external
+- kind: total 4 export types: function, globals, memory, table
+- index: As all the 4 export types are organized in array, this refers to index in target export type
+
+## Function exports
+### use function exports
+function exports are often used in two situations:
+ 1. **call by host**: runtime API `wasm_runtime_lookup_function` will walk through the array of `WASMModuleInstance::export_functions` and compare the exported name with given target symbol name in the function parameter. If any array item matches the name, it then returns the value of field `function` which points to associated function instance (WASMFunctionInstance)
+ 2. **import by another module**: During linking multiple modules, the runtime saves the pointer of exported WASMFunctionInstance in the local WASMFunctionInstance of importing module.
+
+### setup for instance
+The data structure pointed by `WASMModuleInstance::export_functions` is set up during instantiating module instance.
+
+The runtime will walk through the `WASMModule::exports` array and find all the item with kind equal to "function". Create a node of `WASMExportFuncInstance` for each matching, find the associated `WASMFunctionInstance` object and save its address in the field `function`.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_function.MD b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_function.MD
new file mode 100644
index 000000000..da4dac239
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_function.MD
@@ -0,0 +1,47 @@
+# Wasm Function
+
+## Internal data structure
+
+![](./images/wasm_function.svg)
+
+## Module level data (function)
+**WASMModule**: Data structure created for loading a module.
+- `WASMImport *import_functions`: initialized from the Wasm file function section
+- `WASMImport *import_functions`: initialized from the Wasm file import section. The runtime will try to solve the imports from the native API registration, refer to [Export native API to WASM application](../../../doc/export_native_api.md).
+
+**WASMFunction**: represent a Wasm function located in Wasm file code section. Track the links to the compiled function body.
+**WASMImport**: represent a imported Wasm function which can be a solved as a native function or another Wasm module exported function.
+
+## Instance level data (function)
+**WASMModuleInstance**: Data structure created for instantiating a module
+- `WASMModuleInstanceExtra::functions`: combined the imported and internal functions into single array of structure `WASMFunctionInstance`
+- `WASMModuleInstance::import_func_ptrs`: pointer array for solved function imports. This array is referred during calling imported native function. Note it is initialzed with the module level solved imports, but may points to different native function later due to c-api calls.
+
+## Execution paths
+**Interpreter**:
+- Execute internal bytecode function:
+ ```
+ WASMModuleInstance::e
+ -> WASMModuleInstanceExtra::functions[..]
+ -> WASMFunctionInstance::func
+ -> WASMFunction::code
+ ```
+
+- Execute imported function from other module:
+ ```
+ WASMModuleInstance::e
+ -> WASMModuleInstanceExtra::functions[..]
+ (WASMFunctionInstance flag indicates an import)
+ -> WASMFunctionInstance::import_func_inst
+ -> WASMModuleInstance(second)::func
+ -> WASMFunction (second module)::code
+ ```
+
+- Execute imported native function:
+ ```
+ WASMModuleInstance::e
+ -> WASMModuleInstanceExtra::functions[..]
+ (flag indicates imported native)
+ WASMModuleInstance::import_func_ptrs[..]
+ -> native function
+ ``` \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_globals.MD b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_globals.MD
new file mode 100644
index 000000000..e5019a9fc
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/doc/wasm_globals.MD
@@ -0,0 +1,4 @@
+# Wasm globals
+
+![](./images/wasm_globals.svg)
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/asmjit_sgx_patch.diff b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/asmjit_sgx_patch.diff
new file mode 100644
index 000000000..465b9de61
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/asmjit_sgx_patch.diff
@@ -0,0 +1,42 @@
+diff --git a/src/asmjit/core/cpuinfo.cpp b/src/asmjit/core/cpuinfo.cpp
+index 7bf7407..ae2160b 100644
+--- a/src/asmjit/core/cpuinfo.cpp
++++ b/src/asmjit/core/cpuinfo.cpp
+@@ -9,13 +9,13 @@
+
+ #if !defined(_WIN32)
+ #include <errno.h>
+- #include <sys/utsname.h>
++ //#include <sys/utsname.h>
+ #include <unistd.h>
+ #endif
+
+ // Required by `getauxval()` on Linux.
+ #if defined(__linux__)
+- #include <sys/auxv.h>
++ //#include <sys/auxv.h>
+ #endif
+
+ //! Required to detect CPU and features on Apple platforms.
+diff --git a/src/asmjit/core/globals.cpp b/src/asmjit/core/globals.cpp
+index 2bbd0c0..e6b69e5 100644
+--- a/src/asmjit/core/globals.cpp
++++ b/src/asmjit/core/globals.cpp
+@@ -105,6 +105,8 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept {
+ #endif
+ }
+
++extern "C" int os_printf(const char *message, ...);
++
+ // DebugUtils - Debug Output
+ // =========================
+
+@@ -112,7 +114,7 @@ ASMJIT_FAVOR_SIZE void DebugUtils::debugOutput(const char* str) noexcept {
+ #if defined(_WIN32)
+ ::OutputDebugStringA(str);
+ #else
+- ::fputs(str, stderr);
++ os_printf(str);
+ #endif
+ }
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ASMJIT b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ASMJIT
new file mode 100644
index 000000000..020a569db
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ASMJIT
@@ -0,0 +1,17 @@
+Copyright (c) 2008-2020 The AsmJit Authors
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ZYDIS b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ZYDIS
new file mode 100644
index 000000000..11185a5a7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/LICENSE_ZYDIS
@@ -0,0 +1,23 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2021 Florian Bernd
+Copyright (c) 2014-2021 Joel Höner
+
+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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp
new file mode 100644
index 000000000..e28acf98a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp
@@ -0,0 +1,9508 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_codegen.h"
+#include "jit_codecache.h"
+#include "jit_compiler.h"
+#include "jit_frontend.h"
+#include "jit_dump.h"
+
+#include <asmjit/core.h>
+#include <asmjit/x86.h>
+#if WASM_ENABLE_FAST_JIT_DUMP != 0
+#include <Zydis/Zydis.h>
+#endif
+
+#define CODEGEN_CHECK_ARGS 1
+#define CODEGEN_DUMP 0
+
+using namespace asmjit;
+
+static char *code_block_switch_to_jitted_from_interp = NULL;
+static char *code_block_return_to_interp_from_jitted = NULL;
+#if WASM_ENABLE_LAZY_JIT != 0
+static char *code_block_compile_fast_jit_and_then_call = NULL;
+#endif
+
+typedef enum {
+ REG_BPL_IDX = 0,
+ REG_AXL_IDX,
+ REG_BXL_IDX,
+ REG_CXL_IDX,
+ REG_DXL_IDX,
+ REG_DIL_IDX,
+ REG_SIL_IDX,
+ REG_I8_FREE_IDX = REG_SIL_IDX
+} RegIndexI8;
+
+typedef enum {
+ REG_BP_IDX = 0,
+ REG_AX_IDX,
+ REG_BX_IDX,
+ REG_CX_IDX,
+ REG_DX_IDX,
+ REG_DI_IDX,
+ REG_SI_IDX,
+ REG_I16_FREE_IDX = REG_SI_IDX
+} RegIndexI16;
+
+typedef enum {
+ REG_EBP_IDX = 0,
+ REG_EAX_IDX,
+ REG_EBX_IDX,
+ REG_ECX_IDX,
+ REG_EDX_IDX,
+ REG_EDI_IDX,
+ REG_ESI_IDX,
+ REG_I32_FREE_IDX = REG_ESI_IDX
+} RegIndexI32;
+
+typedef enum {
+ REG_RBP_IDX = 0,
+ REG_RAX_IDX,
+ REG_RBX_IDX,
+ REG_RCX_IDX,
+ REG_RDX_IDX,
+ REG_RDI_IDX,
+ REG_RSI_IDX,
+ REG_RSP_IDX,
+ REG_R8_IDX,
+ REG_R9_IDX,
+ REG_R10_IDX,
+ REG_R11_IDX,
+ REG_R12_IDX,
+ REG_R13_IDX,
+ REG_R14_IDX,
+ REG_R15_IDX,
+ REG_I64_FREE_IDX = REG_RSI_IDX
+} RegIndexI64;
+
+/* clang-format off */
+x86::Gp regs_i8[] = {
+ x86::bpl, x86::al, x86::bl, x86::cl,
+ x86::dl, x86::dil, x86::sil, x86::spl,
+ x86::r8b, x86::r9b, x86::r10b, x86::r11b,
+ x86::r12b, x86::r13b, x86::r14b, x86::r15b
+};
+
+x86::Gp regs_i16[] = {
+ x86::bp, x86::ax, x86::bx, x86::cx,
+ x86::dx, x86::di, x86::si, x86::sp,
+ x86::r8w, x86::r9w, x86::r10w, x86::r11w,
+ x86::r12w, x86::r13w, x86::r14w, x86::r15w
+};
+
+x86::Gp regs_i32[] = {
+ x86::ebp, x86::eax, x86::ebx, x86::ecx,
+ x86::edx, x86::edi, x86::esi, x86::esp,
+ x86::r8d, x86::r9d, x86::r10d, x86::r11d,
+ x86::r12d, x86::r13d, x86::r14d, x86::r15d
+};
+
+x86::Gp regs_i64[] = {
+ x86::rbp, x86::rax, x86::rbx, x86::rcx,
+ x86::rdx, x86::rdi, x86::rsi, x86::rsp,
+ x86::r8, x86::r9, x86::r10, x86::r11,
+ x86::r12, x86::r13, x86::r14, x86::r15,
+};
+
+#define REG_F32_FREE_IDX 15
+#define REG_F64_FREE_IDX 15
+
+x86::Xmm regs_float[] = {
+ x86::xmm0,
+ x86::xmm1,
+ x86::xmm2,
+ x86::xmm3,
+ x86::xmm4,
+ x86::xmm5,
+ x86::xmm6,
+ x86::xmm7,
+ x86::xmm8,
+ x86::xmm9,
+ x86::xmm10,
+ x86::xmm11,
+ x86::xmm12,
+ x86::xmm13,
+ x86::xmm14,
+ x86::xmm15,
+};
+/* clang-format on */
+
+int
+jit_codegen_interp_jitted_glue(void *exec_env, JitInterpSwitchInfo *info,
+ uint32 func_idx, void *target)
+{
+ typedef int32 (*F)(const void *exec_env, void *info, uint32 func_idx,
+ const void *target);
+ union {
+ F f;
+ void *v;
+ } u;
+
+ u.v = code_block_switch_to_jitted_from_interp;
+ return u.f(exec_env, info, func_idx, target);
+}
+
+#define PRINT_LINE() LOG_VERBOSE("<Line:%d>\n", __LINE__)
+
+#if CODEGEN_DUMP != 0
+#define GOTO_FAIL \
+ do { \
+ PRINT_LINE(); \
+ goto fail; \
+ } while (0)
+#else
+#define GOTO_FAIL goto fail
+#endif
+
+#if CODEGEN_CHECK_ARGS == 0
+
+#define CHECK_EQKIND(reg0, reg1) (void)0
+#define CHECK_CONST(reg0) (void)0
+#define CHECK_NCONST(reg0) (void)0
+#define CHECK_KIND(reg0, type) (void)0
+#define CHECK_REG_NO(no, kind) (void)0
+#else
+
+/* Check if two register's kind is equal */
+#define CHECK_EQKIND(reg0, reg1) \
+ do { \
+ if (jit_reg_kind(reg0) != jit_reg_kind(reg1)) { \
+ PRINT_LINE(); \
+ LOG_VERBOSE("reg type not equal:\n"); \
+ jit_dump_reg(cc, reg0); \
+ jit_dump_reg(cc, reg1); \
+ GOTO_FAIL; \
+ } \
+ } while (0)
+
+/* Check if a register is an const */
+#define CHECK_CONST(reg0) \
+ do { \
+ if (!jit_reg_is_const(reg0)) { \
+ PRINT_LINE(); \
+ LOG_VERBOSE("reg is not const:\n"); \
+ jit_dump_reg(cc, reg0); \
+ GOTO_FAIL; \
+ } \
+ } while (0)
+
+/* Check if a register is not an const */
+#define CHECK_NCONST(reg0) \
+ do { \
+ if (jit_reg_is_const(reg0)) { \
+ PRINT_LINE(); \
+ LOG_VERBOSE("reg is const:\n"); \
+ jit_dump_reg(cc, reg0); \
+ GOTO_FAIL; \
+ } \
+ } while (0)
+
+/* Check if a register is a special type */
+#define CHECK_KIND(reg0, type) \
+ do { \
+ if (jit_reg_kind(reg0) != type) { \
+ PRINT_LINE(); \
+ LOG_VERBOSE("invalid reg type %d, expected is: %d", \
+ jit_reg_kind(reg0), type); \
+ jit_dump_reg(cc, reg0); \
+ GOTO_FAIL; \
+ } \
+ } while (0)
+
+#define CHECK_I32_REG_NO(no) \
+ do { \
+ if ((uint32)no >= sizeof(regs_i32) / sizeof(regs_i32[0])) \
+ GOTO_FAIL; \
+ } while (0)
+
+#define CHECK_I64_REG_NO(no) \
+ do { \
+ if ((uint32)no >= sizeof(regs_i64) / sizeof(regs_i64[0])) \
+ GOTO_FAIL; \
+ } while (0)
+
+#define CHECK_F32_REG_NO(no) \
+ do { \
+ if ((uint32)no >= sizeof(regs_float) / sizeof(regs_float[0])) \
+ GOTO_FAIL; \
+ } while (0)
+
+#define CHECK_F64_REG_NO(no) \
+ do { \
+ if ((uint32)no >= sizeof(regs_float) / sizeof(regs_float[0])) \
+ GOTO_FAIL; \
+ } while (0)
+
+/* Check if a register number is valid */
+#define CHECK_REG_NO(no, kind) \
+ do { \
+ if (kind == JIT_REG_KIND_I32 || kind == JIT_REG_KIND_I64) { \
+ CHECK_I32_REG_NO(no); \
+ CHECK_I64_REG_NO(no); \
+ } \
+ else if (kind == JIT_REG_KIND_F32 || kind == JIT_REG_KIND_F64) { \
+ CHECK_F32_REG_NO(no); \
+ CHECK_F64_REG_NO(no); \
+ } \
+ else \
+ GOTO_FAIL; \
+ } while (0)
+
+#endif /* end of CODEGEN_CHECK_ARGS == 0 */
+
+/* Load one operand from insn and check none */
+#define LOAD_1ARG() r0 = *jit_insn_opnd(insn, 0)
+
+/* Load two operands from insn and check if r0 is non-const */
+#define LOAD_2ARGS() \
+ r0 = *jit_insn_opnd(insn, 0); \
+ r1 = *jit_insn_opnd(insn, 1); \
+ CHECK_NCONST(r0)
+
+/* Load three operands from insn and check if r0 is non-const */
+#define LOAD_3ARGS() \
+ r0 = *jit_insn_opnd(insn, 0); \
+ r1 = *jit_insn_opnd(insn, 1); \
+ r2 = *jit_insn_opnd(insn, 2); \
+ CHECK_NCONST(r0)
+
+/* Load three operands from insn and check none */
+#define LOAD_3ARGS_NO_ASSIGN() \
+ r0 = *jit_insn_opnd(insn, 0); \
+ r1 = *jit_insn_opnd(insn, 1); \
+ r2 = *jit_insn_opnd(insn, 2);
+
+/* Load four operands from insn and check if r0 is non-const */
+#define LOAD_4ARGS() \
+ r0 = *jit_insn_opnd(insn, 0); \
+ r1 = *jit_insn_opnd(insn, 1); \
+ r2 = *jit_insn_opnd(insn, 2); \
+ r3 = *jit_insn_opnd(insn, 3); \
+ CHECK_NCONST(r0)
+
+/* Load five operands from insn and check if r0 is non-const */
+#define LOAD_4ARGS_NO_ASSIGN() \
+ r0 = *jit_insn_opnd(insn, 0); \
+ r1 = *jit_insn_opnd(insn, 1); \
+ r2 = *jit_insn_opnd(insn, 2); \
+ r3 = *jit_insn_opnd(insn, 3);
+
+class JitErrorHandler : public ErrorHandler
+{
+ public:
+ Error err;
+
+ JitErrorHandler()
+ : err(kErrorOk)
+ {}
+
+ void handleError(Error e, const char *msg, BaseEmitter *base) override
+ {
+ (void)msg;
+ (void)base;
+ this->err = e;
+ }
+};
+
+/* Alu opcode */
+typedef enum { ADD, SUB, MUL, DIV_S, REM_S, DIV_U, REM_U, MIN, MAX } ALU_OP;
+/* Bit opcode */
+typedef enum { OR, XOR, AND } BIT_OP;
+/* Shift opcode */
+typedef enum { SHL, SHRS, SHRU, ROTL, ROTR } SHIFT_OP;
+/* Bitcount opcode */
+typedef enum { CLZ, CTZ, POPCNT } BITCOUNT_OP;
+/* Condition opcode */
+typedef enum { EQ, NE, GTS, GES, LTS, LES, GTU, GEU, LTU, LEU } COND_OP;
+
+typedef union _cast_float_to_integer {
+ float f;
+ uint32 i;
+} cast_float_to_integer;
+
+typedef union _cast_double_to_integer {
+ double d;
+ uint64 i;
+} cast_double_to_integer;
+
+static uint32
+local_log2(uint32 data)
+{
+ uint32 ret = 0;
+ while (data >>= 1) {
+ ret++;
+ }
+ return ret;
+}
+
+static uint64
+local_log2l(uint64 data)
+{
+ uint64 ret = 0;
+ while (data >>= 1) {
+ ret++;
+ }
+ return ret;
+}
+
+/* Jmp type */
+typedef enum JmpType {
+ JMP_DST_LABEL_REL, /* jmp to dst label with relative addr */
+ JMP_DST_LABEL_ABS, /* jmp to dst label with absolute addr */
+ JMP_END_OF_CALLBC, /* jmp to end of CALLBC */
+ JMP_LOOKUPSWITCH_BASE, /* LookupSwitch table base addr */
+} JmpType;
+
+/**
+ * Jmp info, save the info on first encoding pass,
+ * and replace the offset with exact offset when the code cache
+ * has been allocated actually.
+ */
+typedef struct JmpInfo {
+ bh_list_link link;
+ JmpType type;
+ uint32 label_src;
+ uint32 offset;
+ union {
+ uint32 label_dst;
+ } dst_info;
+} JmpInfo;
+
+static bool
+label_is_neighboring(JitCompContext *cc, int32 label_prev, int32 label_succ)
+{
+ return (label_prev == 0 && label_succ == 2)
+ || (label_prev >= 2 && label_succ == label_prev + 1)
+ || (label_prev == (int32)jit_cc_label_num(cc) - 1
+ && label_succ == 1);
+}
+
+static bool
+label_is_ahead(JitCompContext *cc, int32 label_dst, int32 label_src)
+{
+ return (label_dst == 0 && label_src != 0)
+ || (label_dst != 1 && label_src == 1)
+ || (2 <= label_dst && label_dst < label_src
+ && label_src <= (int32)jit_cc_label_num(cc) - 1);
+}
+
+/**
+ * Encode jumping from one label to the other label
+ *
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param label_dst the index of dst label
+ * @param label_src the index of src label
+ *
+ * @return true if success, false if failed
+ */
+static bool
+jmp_from_label_to_label(x86::Assembler &a, bh_list *jmp_info_list,
+ int32 label_dst, int32 label_src)
+{
+ Imm imm(INT32_MAX);
+ JmpInfo *node;
+
+ node = (JmpInfo *)jit_calloc(sizeof(JmpInfo));
+ if (!node)
+ return false;
+
+ node->type = JMP_DST_LABEL_REL;
+ node->label_src = label_src;
+ node->dst_info.label_dst = label_dst;
+ node->offset = a.code()->sectionById(0)->buffer().size() + 2;
+ bh_list_insert(jmp_info_list, node);
+
+ a.jmp(imm);
+ return true;
+}
+
+/**
+ * Encode detecting compare result register according to condition code
+ * and then jumping to suitable label when the condtion is met
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param label_src the index of src label
+ * @param op the opcode of condition operation
+ * @param r1 the label info when condition is met
+ * @param r2 the label info when condition is unmet, do nonthing if VOID
+ * @param is_last_insn if current insn is the last insn of current block
+ *
+ * @return true if success, false if failed
+ */
+static bool
+cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
+ bh_list *jmp_info_list, int32 label_src, COND_OP op,
+ JitReg r1, JitReg r2, bool is_last_insn)
+{
+ Imm imm(INT32_MAX);
+ JmpInfo *node;
+
+ node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
+ if (!node)
+ return false;
+
+ node->type = JMP_DST_LABEL_REL;
+ node->label_src = label_src;
+ node->dst_info.label_dst = jit_reg_no(r1);
+ node->offset = a.code()->sectionById(0)->buffer().size() + 2;
+ bh_list_insert(jmp_info_list, node);
+
+ bool fp_cmp = cc->last_cmp_on_fp;
+
+ bh_assert(!fp_cmp || (fp_cmp && (op == GTS || op == GES)));
+
+ switch (op) {
+ case EQ:
+ {
+ a.je(imm);
+ break;
+ }
+ case NE:
+ {
+ a.jne(imm);
+ break;
+ }
+ case GTS:
+ {
+ if (fp_cmp)
+ a.ja(imm);
+ else
+ a.jg(imm);
+ break;
+ }
+ case LES:
+ {
+ a.jng(imm);
+ break;
+ }
+ case GES:
+ {
+ if (fp_cmp)
+ a.jae(imm);
+ else
+ a.jnl(imm);
+ break;
+ }
+ case LTS:
+ {
+ a.jl(imm);
+ break;
+ }
+ case GTU:
+ {
+ a.ja(imm);
+ break;
+ }
+ case LEU:
+ {
+ a.jna(imm);
+ break;
+ }
+ case GEU:
+ {
+ a.jnb(imm);
+ break;
+ }
+ case LTU:
+ {
+ a.jb(imm);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ break;
+ }
+ }
+
+ if (r2) {
+ int32 label_dst = jit_reg_no(r2);
+ if (!(is_last_insn && label_is_neighboring(cc, label_src, label_dst)))
+ if (!jmp_from_label_to_label(a, jmp_info_list, label_dst,
+ label_src))
+ return false;
+ }
+
+ return true;
+}
+
+#if WASM_ENABLE_FAST_JIT_DUMP != 0
+static void
+dump_native(char *data, uint32 length)
+{
+ /* Initialize decoder context */
+ ZydisDecoder decoder;
+ ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64,
+ ZYDIS_STACK_WIDTH_64);
+
+ /* Initialize formatter */
+ ZydisFormatter formatter;
+ ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
+
+ /* Loop over the instructions in our buffer */
+ ZyanU64 runtime_address = (ZyanU64)(uintptr_t)data;
+ ZyanUSize offset = 0;
+ ZydisDecodedInstruction instruction;
+ ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
+
+ while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(
+ &decoder, data + offset, length - offset, &instruction, operands,
+ ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY))) {
+ /* Print current instruction pointer */
+ os_printf("%012" PRIX64 " ", runtime_address);
+
+ /* Format & print the binary instruction structure to
+ human readable format */
+ char buffer[256];
+ ZydisFormatterFormatInstruction(&formatter, &instruction, operands,
+ instruction.operand_count_visible,
+ buffer, sizeof(buffer),
+ runtime_address);
+ puts(buffer);
+
+ offset += instruction.length;
+ runtime_address += instruction.length;
+ }
+}
+#endif
+
+/**
+ * Encode extending register of byte to register of dword
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src tho no of src register
+ * @param is_signed the data is signed or unsigned
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+extend_r8_to_r32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
+ bool is_signed)
+{
+ if (is_signed) {
+ a.movsx(regs_i32[reg_no_dst], regs_i8[reg_no_src]);
+ }
+ else {
+ a.movzx(regs_i32[reg_no_dst], regs_i8[reg_no_src]);
+ }
+ return true;
+}
+/**
+ * Encode extending register of word to register of dword
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src tho no of src register
+ * @param is_signed the data is signed or unsigned
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+extend_r16_to_r32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
+ bool is_signed)
+{
+ if (is_signed) {
+ a.movsx(regs_i32[reg_no_dst], regs_i16[reg_no_src]);
+ }
+ else {
+ a.movzx(regs_i32[reg_no_dst], regs_i16[reg_no_src]);
+ }
+ return true;
+}
+
+/**
+ * Encode extending register of byte to register of qword
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src tho no of src register
+ * @param is_signed the data is signed or unsigned
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+extend_r8_to_r64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
+ bool is_signed)
+{
+ if (is_signed) {
+ a.movsx(regs_i64[reg_no_dst], regs_i8[reg_no_src]);
+ }
+ else {
+ a.movzx(regs_i64[reg_no_dst], regs_i8[reg_no_src]);
+ }
+ return true;
+}
+
+/**
+ * Encode extending register of word to register of qword
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src tho no of src register
+ * @param is_signed the data is signed or unsigned
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+extend_r16_to_r64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
+ bool is_signed)
+{
+ if (is_signed) {
+ a.movsx(regs_i64[reg_no_dst], regs_i16[reg_no_src]);
+ }
+ else {
+ a.movzx(regs_i64[reg_no_dst], regs_i16[reg_no_src]);
+ }
+ return true;
+}
+
+/**
+ * Encode extending register of dword to register of qword
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src tho no of src register
+ * @param is_signed the data is signed or unsigned
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+extend_r32_to_r64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
+ bool is_signed)
+{
+ if (is_signed) {
+ a.movsxd(regs_i64[reg_no_dst], regs_i32[reg_no_src]);
+ }
+ else {
+ /*
+ * The upper 32-bit will be zero-extended, ref to Intel document,
+ * 3.4.1.1 General-Purpose Registers: 32-bit operands generate
+ * a 32-bit result, zero-extended to a 64-bit result in the
+ * destination general-purpose register
+ */
+ a.mov(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ }
+ return true;
+}
+
+static bool
+mov_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src);
+
+static bool
+mov_r_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src);
+
+static void
+mov_r_to_r(x86::Assembler &a, uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src)
+{
+ if (kind_dst == JIT_REG_KIND_I32)
+ mov_r_to_r_i32(a, reg_no_dst, reg_no_src);
+ else if (kind_dst == JIT_REG_KIND_I64)
+ mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
+ else if (kind_dst == JIT_REG_KIND_F32) {
+ /* TODO */
+ bh_assert(0);
+ }
+ else if (kind_dst == JIT_REG_KIND_F64) {
+ /* TODO */
+ bh_assert(0);
+ }
+ else {
+ bh_assert(0);
+ }
+}
+
+/**
+ * Encode moving memory to a register
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * skipped by float and double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param is_signed whether the data is signed or unsigned
+ * @param reg_no_dst the index of dest register
+ * @param m_src the memory operand which contains the source data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_m_to_r(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst, bool is_signed,
+ int32 reg_no_dst, x86::Mem &m_src)
+{
+ if (kind_dst == JIT_REG_KIND_I32) {
+ switch (bytes_dst) {
+ case 1:
+ case 2:
+ if (is_signed)
+ a.movsx(regs_i32[reg_no_dst], m_src);
+ else
+ a.movzx(regs_i32[reg_no_dst], m_src);
+ break;
+ case 4:
+ a.mov(regs_i32[reg_no_dst], m_src);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+ else if (kind_dst == JIT_REG_KIND_I64) {
+ switch (bytes_dst) {
+ case 1:
+ case 2:
+ if (is_signed)
+ a.movsx(regs_i64[reg_no_dst], m_src);
+ else
+ a.movzx(regs_i64[reg_no_dst], m_src);
+ break;
+ case 4:
+ if (is_signed)
+ a.movsxd(regs_i64[reg_no_dst], m_src);
+ else
+ /*
+ * The upper 32-bit will be zero-extended, ref to Intel
+ * document, 3.4.1.1 General-Purpose Registers: 32-bit
+ * operands generate a 32-bit result, zero-extended to
+ * a 64-bit result in the destination general-purpose
+ * register
+ */
+ a.mov(regs_i32[reg_no_dst], m_src);
+ break;
+ case 8:
+ a.mov(regs_i64[reg_no_dst], m_src);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+ else if (kind_dst == JIT_REG_KIND_F32) {
+ a.movss(regs_float[reg_no_dst], m_src);
+ }
+ else if (kind_dst == JIT_REG_KIND_F64) {
+ a.movsd(regs_float[reg_no_dst], m_src);
+ }
+ return true;
+}
+
+/**
+ * Encode moving register to memory
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * skipped by float and double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param is_signed whether the data is signed or unsigned
+ * @param m_dst the dest memory operand
+ * @param reg_no_src the index of dest register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_r_to_m(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ x86::Mem &m_dst, int32 reg_no_src)
+{
+ if (kind_dst == JIT_REG_KIND_I32) {
+ bh_assert(reg_no_src < 16);
+ switch (bytes_dst) {
+ case 1:
+ a.mov(m_dst, regs_i8[reg_no_src]);
+ break;
+ case 2:
+ a.mov(m_dst, regs_i16[reg_no_src]);
+ break;
+ case 4:
+ a.mov(m_dst, regs_i32[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+ else if (kind_dst == JIT_REG_KIND_I64) {
+ bh_assert(reg_no_src < 16);
+ switch (bytes_dst) {
+ case 1:
+ a.mov(m_dst, regs_i8[reg_no_src]);
+ break;
+ case 2:
+ a.mov(m_dst, regs_i16[reg_no_src]);
+ break;
+ case 4:
+ a.mov(m_dst, regs_i32[reg_no_src]);
+ break;
+ case 8:
+ a.mov(m_dst, regs_i64[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+ else if (kind_dst == JIT_REG_KIND_F32) {
+ a.movss(m_dst, regs_float[reg_no_src]);
+ }
+ else if (kind_dst == JIT_REG_KIND_F64) {
+ a.movsd(m_dst, regs_float[reg_no_src]);
+ }
+ return true;
+}
+
+/**
+ * Encode moving immediate data to memory
+ *
+ * @param m dst memory
+ * @param imm src immediate data
+ *
+ * @return new stream
+ */
+static bool
+mov_imm_to_m(x86::Assembler &a, x86::Mem &m_dst, Imm imm_src, uint32 bytes_dst)
+{
+ if (bytes_dst == 8) {
+ int64 value = imm_src.value();
+ if (value >= INT32_MIN && value <= INT32_MAX) {
+ imm_src.setValue((int32)value);
+ a.mov(m_dst, imm_src);
+ }
+ else {
+ /* There is no instruction `MOV m64, imm64`, we use
+ two instructions to implement it */
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm_src);
+ a.mov(m_dst, regs_i64[REG_I64_FREE_IDX]);
+ }
+ }
+ else
+ a.mov(m_dst, imm_src);
+ return true;
+}
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+/**
+ * Encode exchange register with memory
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * skipped by float and double
+ * @param kind_dst the kind of data to move, could only be I32 or I64
+ * @param m_dst the dest memory operand
+ * @param reg_no_src the index of dest register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+xchg_r_to_m(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ x86::Mem &m_dst, int32 reg_no_src)
+{
+ bh_assert((kind_dst == JIT_REG_KIND_I32 && bytes_dst <= 4)
+ || kind_dst == JIT_REG_KIND_I64);
+ bh_assert(reg_no_src < 16);
+ switch (bytes_dst) {
+ case 1:
+ a.xchg(m_dst, regs_i8[reg_no_src]);
+ break;
+ case 2:
+ a.xchg(m_dst, regs_i16[reg_no_src]);
+ break;
+ case 4:
+ a.xchg(m_dst, regs_i32[reg_no_src]);
+ break;
+ case 8:
+ a.xchg(m_dst, regs_i64[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ return true;
+}
+#endif
+/**
+ * Encode loading register data from memory with imm base and imm offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param is_signed the data is signed or unsigned
+ * @param reg_no_dst the index of dest register
+ * @param base the base address of the memory
+ * @param offset the offset address of the memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+ld_r_from_base_imm_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, bool is_signed, int32 reg_no_dst,
+ int32 base, int32 offset)
+{
+ x86::Mem m((uintptr_t)(base + offset), bytes_dst);
+ return mov_m_to_r(a, bytes_dst, kind_dst, is_signed, reg_no_dst, m);
+}
+
+/**
+ * Encode loading register data from memory with imm base and register offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param is_signed the data is signed or unsigned
+ * @param reg_no_dst the index of dest register
+ * @param base the base address of the memory
+ * @param reg_no_offset the no of register which stores the offset of the memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+ld_r_from_base_imm_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, bool is_signed, int32 reg_no_dst,
+ int32 base, int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_offset], base, bytes_dst);
+ return mov_m_to_r(a, bytes_dst, kind_dst, is_signed, reg_no_dst, m);
+}
+
+/**
+ * Encode loading register data from memory with register base and imm offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param is_signed the data is signed or unsigned
+ * @param reg_no_dst the index of dest register
+ * @param reg_no_base the no of register which stores the base of the memory
+ * @param offset the offset address of the memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+ld_r_from_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, bool is_signed, int32 reg_no_dst,
+ int32 reg_no_base, int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return mov_m_to_r(a, bytes_dst, kind_dst, is_signed, reg_no_dst, m);
+}
+
+/**
+ * Encode loading register data from memory with register base and register
+ * offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param is_signed the data is signed or unsigned
+ * @param reg_no_dst the index of dest register
+ * @param reg_no_base the no of register which stores the base of the memory
+ * @param reg_no_offset the no of register which stores the offset of the memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+ld_r_from_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ bool is_signed, int32 reg_no_dst, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return mov_m_to_r(a, bytes_dst, kind_dst, is_signed, reg_no_dst, m);
+}
+
+/**
+ * Encode storing register data to memory with imm base and imm offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param reg_no_src the index of src register
+ * @param base the base address of the dst memory
+ * @param offset the offset address of the dst memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_r_to_base_imm_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_src, int32 base,
+ int32 offset, bool atomic)
+{
+ x86::Mem m((uintptr_t)(base + offset), bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+#endif
+ return mov_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+}
+
+/**
+ * Encode storing register data to memory with imm base and register offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param reg_no_src the index of src register
+ * @param base the base address of the dst memory
+ * @param reg_no_offset the no of register which stores the offset of the dst
+ * memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_r_to_base_imm_offset_r(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ int32 reg_no_src, int32 base, int32 reg_no_offset,
+ bool atomic)
+{
+ x86::Mem m(regs_i64[reg_no_offset], base, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+#endif
+ return mov_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+}
+
+/**
+ * Encode storing register data to memory with register base and imm offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param reg_no_src the index of src register
+ * @param reg_no_base the no of register which stores the base of the dst memory
+ * @param offset the offset address of the dst memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_r_to_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ int32 reg_no_src, int32 reg_no_base, int32 offset,
+ bool atomic)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+#endif
+ return mov_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+}
+
+/**
+ * Encode storing register data to memory with register base and register offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64), skipped by
+ * float/double
+ * @param kind_dst the kind of data to move, could be I32, I64, F32 or F64
+ * @param reg_no_src the index of src register
+ * @param reg_no_base the no of register which stores the base of the dst memory
+ * @param reg_no_offset the no of register which stores the offset of the dst
+ * memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_r_to_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 reg_no_offset, bool atomic)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic)
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+#endif
+ return mov_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src);
+}
+
+static void
+imm_set_value(Imm &imm, void *data, uint32 bytes)
+{
+ switch (bytes) {
+ case 1:
+ imm.setValue(*(uint8 *)data);
+ break;
+ case 2:
+ imm.setValue(*(uint16 *)data);
+ break;
+ case 4:
+ imm.setValue(*(uint32 *)data);
+ break;
+ case 8:
+ imm.setValue(*(uint64 *)data);
+ break;
+ default:
+ bh_assert(0);
+ }
+}
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+static uint32
+mov_imm_to_free_reg(x86::Assembler &a, Imm &imm, uint32 bytes)
+{
+ uint32 reg_no;
+
+ switch (bytes) {
+ case 1:
+ reg_no = REG_I8_FREE_IDX;
+ a.mov(regs_i8[reg_no], imm);
+ break;
+ case 2:
+ reg_no = REG_I16_FREE_IDX;
+ a.mov(regs_i16[reg_no], imm);
+ break;
+ case 4:
+ reg_no = REG_I32_FREE_IDX;
+ a.mov(regs_i32[reg_no], imm);
+ break;
+ case 8:
+ reg_no = REG_I64_FREE_IDX;
+ a.mov(regs_i64[reg_no], imm);
+ break;
+ default:
+ bh_assert(0);
+ }
+
+ return reg_no;
+}
+#endif
+
+/**
+ * Encode storing int32 imm data to memory with imm base and imm offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param data_src the src immediate data
+ * @param base the base address of dst memory
+ * @param offset the offset address of dst memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_imm_to_base_imm_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ void *data_src, int32 base, int32 offset,
+ bool atomic)
+{
+ x86::Mem m((uintptr_t)(base + offset), bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ if (atomic) {
+ return xchg_r_to_m(a, bytes_dst, JIT_REG_KIND_I64, m, reg_no_src);
+ }
+#endif
+ return mov_imm_to_m(a, m, imm, bytes_dst);
+}
+
+/**
+ * Encode storing int32 imm data to memory with imm base and reg offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param data_src the src immediate data
+ * @param base the base address of dst memory
+ * @param reg_no_offset the no of register that stores the offset address
+ * of dst memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_imm_to_base_imm_offset_r(x86::Assembler &a, uint32 bytes_dst, void *data_src,
+ int32 base, int32 reg_no_offset, bool atomic)
+{
+ x86::Mem m(regs_i64[reg_no_offset], base, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ if (atomic) {
+ return xchg_r_to_m(a, bytes_dst, JIT_REG_KIND_I64, m, reg_no_src);
+ }
+#endif
+ return mov_imm_to_m(a, m, imm, bytes_dst);
+}
+
+/**
+ * Encode storing int32 imm data to memory with reg base and imm offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param data_src the src immediate data
+ * @param reg_no_base the no of register that stores the base address
+ * of dst memory
+ * @param offset the offset address of dst memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_imm_to_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst, void *data_src,
+ int32 reg_no_base, int32 offset, bool atomic)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ if (atomic) {
+ return xchg_r_to_m(a, bytes_dst, JIT_REG_KIND_I64, m, reg_no_src);
+ }
+#endif
+ return mov_imm_to_m(a, m, imm, bytes_dst);
+}
+
+/**
+ * Encode storing int32 imm data to memory with reg base and reg offset
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param data_src the src immediate data
+ * @param reg_no_base the no of register that stores the base address
+ * of dst memory
+ * @param reg_no_offset the no of register that stores the offset address
+ * of dst memory
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+st_imm_to_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst, void *data_src,
+ int32 reg_no_base, int32 reg_no_offset, bool atomic)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ if (atomic) {
+ return xchg_r_to_m(a, bytes_dst, JIT_REG_KIND_I64, m, reg_no_src);
+ }
+#endif
+ return mov_imm_to_m(a, m, imm, bytes_dst);
+}
+
+/**
+ * Encode moving immediate int32 data to register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst register
+ * @param data the immediate data to move
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_imm_to_r_i32(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ Imm imm(data);
+ a.mov(regs_i32[reg_no], imm);
+ return true;
+}
+
+/**
+ * Encode moving int32 data from src register to dst register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ if (reg_no_dst != reg_no_src)
+ a.mov(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode moving immediate int64 data to register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst register
+ * @param data the immediate data to move
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_imm_to_r_i64(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ Imm imm(data);
+ a.mov(regs_i64[reg_no], imm);
+ return true;
+}
+
+/**
+ * Encode moving int64 data from src register to dst register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_r_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ if (reg_no_dst != reg_no_src)
+ a.mov(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode moving immediate float data to register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst register
+ * @param data the immediate data to move
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_imm_to_r_f32(x86::Assembler &a, int32 reg_no, float data)
+{
+ /* imm -> gp -> xmm */
+ cast_float_to_integer v = { .f = data };
+ Imm imm(v.i);
+ a.mov(regs_i32[REG_I32_FREE_IDX], imm);
+ a.movd(regs_float[reg_no], regs_i32[REG_I32_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode moving float data from src register to dst register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_r_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ if (reg_no_dst != reg_no_src) {
+ a.movss(regs_float[reg_no_dst], regs_float[reg_no_src]);
+ }
+ return true;
+}
+
+/**
+ * Encode moving immediate double data to register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst register
+ * @param data the immediate data to move
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_imm_to_r_f64(x86::Assembler &a, int32 reg_no, double data)
+{
+ cast_double_to_integer v = { .d = data };
+ Imm imm(v.i);
+ a.mov(regs_i64[REG_I32_FREE_IDX], imm);
+ /* REG_I32_FREE_IDX == REG_I64_FREE_IDX */
+ a.movq(regs_float[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode moving double data from src register to dst register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+mov_r_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ if (reg_no_dst != reg_no_src) {
+ a.movsd(regs_float[reg_no_dst], regs_float[reg_no_src]);
+ }
+ return true;
+}
+
+/* Let compiler do the conversation job as much as possible */
+
+/**
+ * Encoding convert int8 immediate data to int32 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to int32
+ * @param data the src int8 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i8_to_r_i32(x86::Assembler &a, int32 reg_no, int8 data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (int32)data);
+}
+
+/**
+ * encoding convert int8 register to int32 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i8_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return extend_r8_to_r32(a, reg_no_dst, reg_no_src, true);
+}
+
+/**
+ * encoding convert int8 immediate data to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to int64
+ * @param data the src int8 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i8_to_r_i64(x86::Assembler &a, int32 reg_no, int8 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int64)data);
+}
+
+/**
+ * encoding convert int8 register to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i8_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return extend_r8_to_r64(a, reg_no_dst, reg_no_src, true);
+}
+
+/**
+ * Encoding convert int16 immediate data to int32 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to int32
+ * @param data the src int16 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i16_to_r_i32(x86::Assembler &a, int32 reg_no, int16 data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (int32)data);
+}
+
+/**
+ * encoding convert int16 register to int32 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i16_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return extend_r16_to_r32(a, reg_no_dst, reg_no_src, true);
+}
+
+/**
+ * encoding convert int16 immediate data to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to int64
+ * @param data the src int16 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i16_to_r_i64(x86::Assembler &a, int32 reg_no, int16 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int64)data);
+}
+
+/**
+ * encoding convert int16 register to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i16_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return extend_r16_to_r64(a, reg_no_dst, reg_no_src, true);
+}
+
+/**
+ * Encoding convert int32 immediate data to int8 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to int8
+ * @param data the src int32 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_i8(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ /* (int32)(int8)data will do sign-extension */
+ /* (int32)(uint32)(int8)data is longer */
+ return mov_imm_to_r_i32(a, reg_no, data & 0x000000FF);
+}
+
+/**
+ * Encoding convert int32 immediate data to int8 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register, need to be converted to int8
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_i8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i32(a, reg_no_dst, reg_no_src);
+ a.and_(regs_i32[reg_no_dst], 0x000000FF);
+ return true;
+}
+
+/**
+ * Encoding convert int32 immediate data to uint8 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to uint8
+ * @param data the src int32 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_u8(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (uint8)data);
+}
+
+/**
+ * Encoding convert int32 immediate data to uint8 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register, need to be converted to uint8
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_u8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return convert_r_i32_to_r_i8(a, reg_no_dst, reg_no_src);
+}
+
+/**
+ * Encoding convert int32 immediate data to int16 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to int16
+ * @param data the src int32 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_i16(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ /* (int32)(int16)data will do sign-extension */
+ /* (int32)(uint32)(int16)data is longer */
+ return mov_imm_to_r_i32(a, reg_no, data & 0x0000FFFF);
+}
+
+/**
+ * Encoding convert int32 immediate data to int16 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register, need to be converted to int16
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_i16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i32(a, reg_no_dst, reg_no_src);
+ a.and_(regs_i32[reg_no_dst], 0x0000FFFF);
+ return true;
+}
+
+/**
+ * Encoding convert int32 immediate data to uint16 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to uint16
+ * @param data the src int32 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_u16(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (uint16)data);
+}
+
+/**
+ * Encoding convert int32 immediate data to uint16 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register, need to be converted to uint16
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_u16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return convert_r_i32_to_r_i16(a, reg_no_dst, reg_no_src);
+}
+
+/**
+ * Encoding convert int32 immediate data to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the dst register, need to be converted to uint64
+ * @param data the src int32 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_i64(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int64)data);
+}
+
+/**
+ * Encoding convert int32 register data to int64 register with signed extension
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the dst register, need to be converted to uint64
+ * @param reg_no_src the src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return extend_r32_to_r64(a, reg_no_dst, reg_no_src, true);
+}
+
+/**
+ * Encode converting int32 register data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst float register
+ * @param reg_no_src the no of src int32 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvtsi2ss(regs_float[reg_no_dst], regs_i32[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting int32 immediate data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst float register
+ * @param data the src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_f32(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ mov_imm_to_r_i32(a, REG_I32_FREE_IDX, data);
+ return convert_r_i32_to_r_f32(a, reg_no, REG_I32_FREE_IDX);
+}
+
+/**
+ * Encode converting int32 register data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst double register
+ * @param reg_no_src the no of src int32 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i32_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvtsi2sd(regs_float[reg_no_dst], regs_i32[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting int32 immediate data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst double register
+ * @param data the src immediate int32 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i32_to_r_f64(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ mov_imm_to_r_i32(a, REG_I32_FREE_IDX, data);
+ return convert_r_i32_to_r_f64(a, reg_no, REG_I32_FREE_IDX);
+}
+
+/**
+ * Encode converting int64 immediate data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate int64 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i64_to_r_i32(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int32)data);
+}
+
+/**
+ * Encode converting int64 register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i64_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
+ a.and_(regs_i64[reg_no_dst], 0x00000000FFFFFFFFLL);
+ return true;
+}
+
+/**
+ * Encode converting int64 immediate data to int8 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate int64 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i64_to_r_i8(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int8)data);
+}
+
+/**
+ * Encode converting int64 register data to int8 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int8 register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i64_to_r_i8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
+ a.and_(regs_i64[reg_no_dst], 0x00000000000000FFLL);
+ return true;
+}
+
+/**
+ * Encode converting int64 immediate data to int16 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate int64 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i64_to_r_i16(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int16)data);
+}
+
+/**
+ * Encode converting int64 register data to int16 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int16 register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i64_to_r_i16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
+ a.and_(regs_i64[reg_no_dst], 0x000000000000FFFFLL);
+ return true;
+}
+
+/**
+ * Encode converting uint32 immediate data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int64 register
+ * @param data the src immediate uint32 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_u32_to_r_i64(x86::Assembler &a, int32 reg_no, uint32 data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int64)(uint64)data);
+}
+
+/**
+ * Encode converting uint32 register data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst uint32 register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_u32_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ return extend_r32_to_r64(a, reg_no_dst, reg_no_src, false);
+}
+
+/**
+ * Encode converting uint32 immediate data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst float register
+ * @param data the src immediate uint32 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_u32_to_r_f32(x86::Assembler &a, int32 reg_no, uint32 data)
+{
+ mov_imm_to_r_i64(a, REG_I64_FREE_IDX, (int64)(uint64)data);
+ a.cvtsi2ss(regs_float[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode converting uint32 register data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst uint32 register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_u32_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ extend_r32_to_r64(a, REG_I64_FREE_IDX, reg_no_src, false);
+ a.cvtsi2ss(regs_float[reg_no_dst], regs_i64[REG_I64_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode converting uint32 immediate data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst double register
+ * @param data the src immediate uint32 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_u32_to_r_f64(x86::Assembler &a, int32 reg_no, uint32 data)
+{
+ mov_imm_to_r_i64(a, REG_I64_FREE_IDX, (int64)(uint64)data);
+ a.cvtsi2sd(regs_float[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode converting uint32 register data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst uint32 register
+ * @param reg_no_src the no of src double register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_u32_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ extend_r32_to_r64(a, REG_I64_FREE_IDX, reg_no_src, false);
+ a.cvtsi2sd(regs_float[reg_no_dst], regs_i64[REG_I64_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode converting int64 register data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst float register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i64_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvtsi2ss(regs_float[reg_no_dst], regs_i64[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting int64 immediate data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst float register
+ * @param data the src immediate int64 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i64_to_r_f32(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ mov_imm_to_r_i64(a, REG_I64_FREE_IDX, data);
+ return convert_r_i64_to_r_f32(a, reg_no, REG_I64_FREE_IDX);
+}
+
+/**
+ * Encode converting int64 register data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst double register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_i64_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvtsi2sd(regs_float[reg_no_dst], regs_i64[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting int64 immediate data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst double register
+ * @param data the src immediate int64 data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_i64_to_r_f64(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ mov_imm_to_r_i64(a, REG_I64_FREE_IDX, data);
+ return convert_r_i64_to_r_f64(a, reg_no, REG_I64_FREE_IDX);
+}
+
+/**
+ * Encode converting float immediate data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate float data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f32_to_r_i32(x86::Assembler &a, int32 reg_no, float data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (int32)data);
+}
+
+/**
+ * Encode converting float register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f32_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvttss2si(regs_i32[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting float immediate data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate float data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f32_to_r_u32(x86::Assembler &a, int32 reg_no, float data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (uint32)data);
+}
+
+/**
+ * Encode converting float register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f32_to_r_u32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvttss2si(regs_i64[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting float immediate data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int64 register
+ * @param data the src immediate float data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f32_to_r_i64(x86::Assembler &a, int32 reg_no, float data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int64)data);
+}
+
+/**
+ * Encode converting float register data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int64 register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f32_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvttss2si(regs_i64[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting float immediate data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst double register
+ * @param data the src immediate float data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f32_to_r_f64(x86::Assembler &a, int32 reg_no, float data)
+{
+ return mov_imm_to_r_f64(a, reg_no, (double)data);
+}
+
+/**
+ * Encode converting float register data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst double register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f32_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvtss2sd(regs_float[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting double immediate data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate double data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f64_to_r_i32(x86::Assembler &a, int32 reg_no, double data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (int32)data);
+}
+
+/**
+ * Encode converting double register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src double register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f64_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvttsd2si(regs_i32[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting double immediate data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int64 register
+ * @param data the src immediate double data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f64_to_r_i64(x86::Assembler &a, int32 reg_no, double data)
+{
+ return mov_imm_to_r_i64(a, reg_no, (int64)data);
+}
+
+/**
+ * Encode converting double register data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int64 register
+ * @param reg_no_src the no of src double register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f64_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvttsd2si(regs_i64[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting double immediate data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst float register
+ * @param data the src immediate double data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f64_to_r_f32(x86::Assembler &a, int32 reg_no, double data)
+{
+ return mov_imm_to_r_f32(a, reg_no, (float)data);
+}
+
+/**
+ * Encode converting double register data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst float register
+ * @param reg_no_src the no of src double register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f64_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvtsd2ss(regs_float[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode converting double immediate data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate double data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_imm_f64_to_r_u32(x86::Assembler &a, int32 reg_no, double data)
+{
+ return mov_imm_to_r_i32(a, reg_no, (uint32)data);
+}
+
+/**
+ * Encode converting double register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src double register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+convert_r_f64_to_r_u32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.cvttsd2si(regs_i64[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode making negative from int32 immediate data to int32 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst register
+ * @param data the src int32 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_imm_to_r_i32(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ Imm imm(-data);
+ a.mov(regs_i32[reg_no], imm);
+ return true;
+}
+
+/**
+ * Encode making negative from int32 register to int32 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i32(a, reg_no_dst, reg_no_src);
+ a.neg(regs_i32[reg_no_dst]);
+ return true;
+}
+
+/**
+ * Encode making negative from int64 immediate data to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst register
+ * @param data the src int64 immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_imm_to_r_i64(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ Imm imm(-data);
+ a.mov(regs_i64[reg_no], imm);
+ return true;
+}
+
+/**
+ * Encode making negative from int64 register to int64 register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_r_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
+ a.neg(regs_i64[reg_no_dst]);
+ return true;
+}
+
+/**
+ * Encode making negative from float immediate data to float register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst float register
+ * @param data the src float immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_imm_to_r_f32(x86::Assembler &a, int32 reg_no, float data)
+{
+ bh_assert(0);
+ (void)a;
+ (void)reg_no;
+ (void)data;
+ return false;
+}
+
+/**
+ * Encode making negative from float register to float register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst register
+ * @param reg_no_src the no of src register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_r_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ bh_assert(0);
+ (void)a;
+ (void)reg_no_dst;
+ (void)reg_no_src;
+ return false;
+}
+
+/**
+ * Encode making negative from double immediate data to double register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst double register
+ * @param data the src double immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_imm_to_r_f64(x86::Assembler &a, int32 reg_no, double data)
+{
+ bh_assert(0);
+ (void)a;
+ (void)reg_no;
+ (void)data;
+ return false;
+}
+
+/**
+ * Encode making negative from double register to double register
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst double register
+ * @param reg_no_src the no of src double register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_r_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ bh_assert(0);
+ (void)a;
+ (void)reg_no_dst;
+ (void)reg_no_src;
+ return false;
+}
+
+static COND_OP
+not_cond(COND_OP op)
+{
+ COND_OP not_list[] = { NE, EQ, LES, LTS, GES, GTS, LEU, LTU, GEU, GTU };
+
+ bh_assert(op <= LEU);
+ return not_list[op];
+}
+
+/**
+ * Encode int32 alu operation of reg and data, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no the no of register, as first operand, and save result
+ * @param data the immediate data, as the second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_imm_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no_src, int32 data)
+{
+ Imm imm(data);
+
+ switch (op) {
+ case ADD:
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
+ if (data == 1)
+ a.inc(regs_i32[reg_no_dst]);
+ else if (data == -1)
+ a.dec(regs_i32[reg_no_dst]);
+ else if (data != 0)
+ a.add(regs_i32[reg_no_dst], imm);
+ break;
+ case SUB:
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
+ if (data == -1)
+ a.inc(regs_i32[reg_no_dst]);
+ else if (data == 1)
+ a.dec(regs_i32[reg_no_dst]);
+ else if (data != 0)
+ a.sub(regs_i32[reg_no_dst], imm);
+ break;
+ case MUL:
+ if (data == 0)
+ a.xor_(regs_i32[reg_no_dst], regs_i32[reg_no_dst]);
+ else if (data == -1) {
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
+ a.neg(regs_i32[reg_no_dst]);
+ }
+ else if (data == 1) {
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
+ }
+ else if (data > 0 && (data & (data - 1)) == 0x0) {
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
+ data = (int32)local_log2(data);
+ imm.setValue(data);
+ a.shl(regs_i32[reg_no_dst], imm);
+ }
+ else {
+ a.imul(regs_i32[reg_no_dst], regs_i32[reg_no_src], imm);
+ }
+ break;
+ case DIV_S:
+ case REM_S:
+ bh_assert(reg_no_src == REG_EAX_IDX);
+ if (op == DIV_S) {
+ bh_assert(reg_no_dst == REG_EAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_EDX_IDX);
+ }
+ a.mov(regs_i32[REG_I32_FREE_IDX], imm);
+ /* signed extend eax to edx:eax */
+ a.cdq();
+ a.idiv(regs_i32[REG_I32_FREE_IDX]);
+ break;
+ case DIV_U:
+ case REM_U:
+ bh_assert(reg_no_src == REG_EAX_IDX);
+ if (op == DIV_U) {
+ bh_assert(reg_no_dst == REG_EAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_EDX_IDX);
+ }
+ a.mov(regs_i32[REG_I32_FREE_IDX], imm);
+ /* unsigned extend eax to edx:eax */
+ a.xor_(regs_i32[REG_EDX_IDX], regs_i32[REG_EDX_IDX]);
+ a.div(regs_i32[REG_I32_FREE_IDX]);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Encode int32 alu operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register, as first operand, and save result
+ * @param reg_no_src the no of register, as the second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_r_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst, int32 reg_no1_src,
+ int32 reg_no2_src)
+{
+ switch (op) {
+ case ADD:
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no1_src);
+ a.add(regs_i32[reg_no_dst], regs_i32[reg_no2_src]);
+ }
+ else
+ a.add(regs_i32[reg_no2_src], regs_i32[reg_no1_src]);
+ break;
+ case SUB:
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no1_src);
+ a.sub(regs_i32[reg_no_dst], regs_i32[reg_no2_src]);
+ }
+ else {
+ a.sub(regs_i32[reg_no2_src], regs_i32[reg_no1_src]);
+ a.neg(regs_i32[reg_no2_src]);
+ }
+ break;
+ case MUL:
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r(a, JIT_REG_KIND_I32, reg_no_dst, reg_no1_src);
+ a.imul(regs_i32[reg_no_dst], regs_i32[reg_no2_src]);
+ }
+ else
+ a.imul(regs_i32[reg_no2_src], regs_i32[reg_no1_src]);
+ break;
+ case DIV_S:
+ case REM_S:
+ bh_assert(reg_no1_src == REG_EAX_IDX);
+ if (op == DIV_S) {
+ bh_assert(reg_no_dst == REG_EAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_EDX_IDX);
+ if (reg_no2_src == REG_EDX_IDX) {
+ /* convert `REM_S edx, eax, edx` into
+ `mov esi, edx` and `REM_S edx eax, rsi` to
+ avoid overwritting edx when a.cdq() */
+ a.mov(regs_i32[REG_I32_FREE_IDX], regs_i32[REG_EDX_IDX]);
+ reg_no2_src = REG_I32_FREE_IDX;
+ }
+ }
+ /* signed extend eax to edx:eax */
+ a.cdq();
+ a.idiv(regs_i32[reg_no2_src]);
+ break;
+ case DIV_U:
+ case REM_U:
+ bh_assert(reg_no1_src == REG_EAX_IDX);
+ if (op == DIV_U) {
+ bh_assert(reg_no_dst == REG_EAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_EDX_IDX);
+ if (reg_no2_src == REG_EDX_IDX) {
+ /* convert `REM_U edx, eax, edx` into
+ `mov esi, edx` and `REM_U edx eax, rsi` to
+ avoid overwritting edx when unsigned extend
+ eax to edx:eax */
+ a.mov(regs_i32[REG_I32_FREE_IDX], regs_i32[REG_EDX_IDX]);
+ reg_no2_src = REG_I32_FREE_IDX;
+ }
+ }
+ /* unsigned extend eax to edx:eax */
+ a.xor_(regs_i32[REG_EDX_IDX], regs_i32[REG_EDX_IDX]);
+ a.div(regs_i32[reg_no2_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Encode int32 alu operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_imm_to_r_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 data1_src, int32 data2_src)
+{
+ Imm imm;
+ int32 data = 0;
+
+ switch (op) {
+ case ADD:
+ data = data1_src + data2_src;
+ break;
+ case SUB:
+ data = data1_src - data2_src;
+ break;
+ case MUL:
+ data = data1_src * data2_src;
+ break;
+ case DIV_S:
+ data = data1_src / data2_src;
+ break;
+ case REM_S:
+ data = data1_src % data2_src;
+ break;
+ case DIV_U:
+ data = (uint32)data1_src / (uint32)data2_src;
+ break;
+ case REM_U:
+ data = (uint32)data1_src % (uint32)data2_src;
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ imm.setValue(data);
+ a.mov(regs_i32[reg_no_dst], imm);
+ return true;
+}
+
+/**
+ * Encode int32 alu operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_r_to_r_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 data1_src, int32 reg_no2_src)
+{
+ if (op == ADD || op == MUL)
+ return alu_r_r_imm_i32(a, op, reg_no_dst, reg_no2_src, data1_src);
+ else if (op == SUB) {
+ if (!alu_r_r_imm_i32(a, op, reg_no_dst, reg_no2_src, data1_src))
+ return false;
+ a.neg(regs_i32[reg_no_dst]);
+ return true;
+ }
+ else {
+ if (reg_no_dst != reg_no2_src) {
+ if (!mov_imm_to_r_i32(a, reg_no_dst, data1_src)
+ || !alu_r_r_r_i32(a, op, reg_no_dst, reg_no_dst, reg_no2_src))
+ return false;
+ return true;
+ }
+ else {
+ if (!mov_imm_to_r_i32(a, REG_I32_FREE_IDX, data1_src)
+ || !alu_r_r_r_i32(a, op, reg_no_dst, REG_I32_FREE_IDX,
+ reg_no2_src))
+ return false;
+ return true;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Encode int32 alu operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_imm_to_r_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 data2_src)
+{
+ return alu_r_r_imm_i32(a, op, reg_no_dst, reg_no1_src, data2_src);
+}
+
+/**
+ * Encode int32 alu operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_to_r_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ return alu_r_r_r_i32(a, op, reg_no_dst, reg_no1_src, reg_no2_src);
+}
+
+/**
+ * Encode int64 alu operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register, as first operand, and save result
+ * @param reg_no_src the no of register, as the second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_r_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst, int32 reg_no1_src,
+ int32 reg_no2_src)
+{
+ switch (op) {
+ case ADD:
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
+ a.add(regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
+ }
+ else
+ a.add(regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
+ break;
+ case SUB:
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
+ a.sub(regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
+ }
+ else {
+ a.sub(regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
+ a.neg(regs_i64[reg_no2_src]);
+ }
+ break;
+ case MUL:
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
+ a.imul(regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
+ }
+ else
+ a.imul(regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
+ break;
+ case DIV_S:
+ case REM_S:
+ bh_assert(reg_no1_src == REG_RAX_IDX);
+ if (op == DIV_S) {
+ bh_assert(reg_no_dst == REG_RAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_RDX_IDX);
+ }
+ /* signed extend rax to rdx:rax */
+ a.cqo();
+ a.idiv(regs_i64[reg_no2_src]);
+ break;
+ case DIV_U:
+ case REM_U:
+ bh_assert(reg_no1_src == REG_RAX_IDX);
+ if (op == DIV_U) {
+ bh_assert(reg_no_dst == REG_RAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_RDX_IDX);
+ }
+ /* unsigned extend rax to rdx:rax */
+ a.xor_(regs_i64[REG_RDX_IDX], regs_i64[REG_RDX_IDX]);
+ a.div(regs_i64[reg_no2_src]);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Encode int64 alu operation of reg and data, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no the no of register, as first operand, and save result
+ * @param data the immediate data, as the second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_imm_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no_src, int64 data)
+{
+ Imm imm(data);
+
+ switch (op) {
+ case ADD:
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
+ if (data == 1)
+ a.inc(regs_i64[reg_no_dst]);
+ else if (data == -1)
+ a.dec(regs_i64[reg_no_dst]);
+ else if (data != 0) {
+ if (data >= INT32_MIN && data <= INT32_MAX) {
+ imm.setValue((int32)data);
+ a.add(regs_i64[reg_no_dst], imm);
+ }
+ else {
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.add(regs_i64[reg_no_dst], regs_i64[REG_I64_FREE_IDX]);
+ }
+ }
+ break;
+ case SUB:
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
+ if (data == -1)
+ a.inc(regs_i64[reg_no_dst]);
+ else if (data == 1)
+ a.dec(regs_i64[reg_no_dst]);
+ else if (data != 0) {
+ if (data >= INT32_MIN && data <= INT32_MAX) {
+ imm.setValue((int32)data);
+ a.sub(regs_i64[reg_no_dst], imm);
+ }
+ else {
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.sub(regs_i64[reg_no_dst], regs_i64[REG_I64_FREE_IDX]);
+ }
+ }
+ break;
+ case MUL:
+ if (data == 0)
+ a.xor_(regs_i64[reg_no_dst], regs_i64[reg_no_dst]);
+ else if (data == -1) {
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
+ a.neg(regs_i64[reg_no_dst]);
+ }
+ else if (data == 1) {
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
+ }
+ else if (data > 0 && (data & (data - 1)) == 0x0) {
+ mov_r_to_r(a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
+ data = (int64)local_log2l(data);
+ imm.setValue(data);
+ a.shl(regs_i64[reg_no_dst], imm);
+ }
+ else if (INT32_MIN <= data && data <= INT32_MAX) {
+ a.imul(regs_i64[reg_no_dst], regs_i64[reg_no_src], imm);
+ }
+ else {
+ mov_imm_to_r_i64(
+ a, reg_no_dst == reg_no_src ? REG_I64_FREE_IDX : reg_no_dst,
+ data);
+ alu_r_r_r_i64(a, op, reg_no_dst,
+ reg_no_dst == reg_no_src ? REG_I64_FREE_IDX
+ : reg_no_dst,
+ reg_no_src);
+ }
+ break;
+ case DIV_S:
+ case REM_S:
+ bh_assert(reg_no_src == REG_RAX_IDX);
+ if (op == DIV_S) {
+ bh_assert(reg_no_dst == REG_RAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_RDX_IDX);
+ }
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ /* signed extend rax to rdx:rax */
+ a.cqo();
+ a.idiv(regs_i64[REG_I64_FREE_IDX]);
+ break;
+ case DIV_U:
+ case REM_U:
+ bh_assert(reg_no_src == REG_RAX_IDX);
+ if (op == DIV_U) {
+ bh_assert(reg_no_dst == REG_RAX_IDX);
+ }
+ else {
+ bh_assert(reg_no_dst == REG_RDX_IDX);
+ }
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ /* unsigned extend rax to rdx:rax */
+ a.xor_(regs_i64[REG_RDX_IDX], regs_i64[REG_RDX_IDX]);
+ a.div(regs_i64[REG_I64_FREE_IDX]);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Encode int64 alu operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_imm_to_r_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int64 data1_src, int64 data2_src)
+{
+ Imm imm;
+ int64 data = 0;
+
+ switch (op) {
+ case ADD:
+ data = data1_src + data2_src;
+ break;
+ case SUB:
+ data = data1_src - data2_src;
+ break;
+ case MUL:
+ data = data1_src * data2_src;
+ break;
+ case DIV_S:
+ data = data1_src / data2_src;
+ break;
+ case REM_S:
+ data = data1_src % data2_src;
+ break;
+ case DIV_U:
+ data = (uint64)data1_src / (uint64)data2_src;
+ break;
+ case REM_U:
+ data = (uint64)data1_src % (uint64)data2_src;
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ imm.setValue(data);
+ a.mov(regs_i64[reg_no_dst], imm);
+ return true;
+}
+
+/**
+ * Encode int64 alu operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_r_to_r_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int64 data1_src, int32 reg_no2_src)
+{
+ if (op == ADD || op == MUL)
+ return alu_r_r_imm_i64(a, op, reg_no_dst, reg_no2_src, data1_src);
+ else if (op == SUB) {
+ if (!alu_r_r_imm_i64(a, op, reg_no_dst, reg_no2_src, data1_src))
+ return false;
+ a.neg(regs_i64[reg_no_dst]);
+ return true;
+ }
+ else {
+ if (reg_no_dst != reg_no2_src) {
+ if (!mov_imm_to_r_i64(a, reg_no_dst, data1_src)
+ || !alu_r_r_r_i64(a, op, reg_no_dst, reg_no_dst, reg_no2_src))
+ return false;
+ return true;
+ }
+ else {
+ if (!mov_imm_to_r_i64(a, REG_I64_FREE_IDX, data1_src)
+ || !alu_r_r_r_i64(a, op, reg_no_dst, REG_I64_FREE_IDX,
+ reg_no2_src))
+ return false;
+ return true;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Encode int64 alu operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_imm_to_r_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int64 data2_src)
+{
+ return alu_r_r_imm_i64(a, op, reg_no_dst, reg_no1_src, data2_src);
+}
+
+/**
+ * Encode int64 alu operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_to_r_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ return alu_r_r_r_i64(a, op, reg_no_dst, reg_no1_src, reg_no2_src);
+}
+
+/**
+ * Encode float alu operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_imm_to_r_f32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ float data1_src, float data2_src)
+{
+ Imm imm;
+ float data = 0;
+
+ switch (op) {
+ case ADD:
+ {
+ data = data1_src + data2_src;
+ break;
+ }
+ case SUB:
+ {
+ data = data1_src - data2_src;
+ break;
+ }
+ case MUL:
+ {
+ data = data1_src * data2_src;
+ break;
+ }
+ case DIV_S:
+ {
+ data = data1_src / data2_src;
+ break;
+ }
+ case MAX:
+ {
+ data = fmaxf(data1_src, data2_src);
+ break;
+ }
+ case MIN:
+ {
+ data = fminf(data1_src, data2_src);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ return mov_imm_to_r_f32(a, reg_no_dst, data);
+}
+
+static bool
+alu_r_m_float(x86::Assembler &a, ALU_OP op, int32 reg_no, x86::Mem &m,
+ bool is_f32)
+{
+ switch (op) {
+ case ADD:
+ {
+ if (is_f32)
+ a.addss(regs_float[reg_no], m);
+ else
+ a.addsd(regs_float[reg_no], m);
+ break;
+ }
+ case SUB:
+ {
+ if (is_f32)
+ a.subss(regs_float[reg_no], m);
+ else
+ a.subsd(regs_float[reg_no], m);
+ break;
+ }
+ case MUL:
+ {
+ if (is_f32)
+ a.mulss(regs_float[reg_no], m);
+ else
+ a.mulsd(regs_float[reg_no], m);
+ break;
+ }
+ case DIV_S:
+ {
+ if (is_f32)
+ a.divss(regs_float[reg_no], m);
+ else
+ a.divsd(regs_float[reg_no], m);
+ break;
+ }
+ case MAX:
+ {
+ if (is_f32)
+ a.maxss(regs_float[reg_no], m);
+ else
+ a.maxsd(regs_float[reg_no], m);
+ break;
+ }
+ case MIN:
+ {
+ if (is_f32)
+ a.minss(regs_float[reg_no], m);
+ else
+ a.minsd(regs_float[reg_no], m);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Encode float alu operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_r_to_r_f32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ float data1_src, int32 reg_no2_src)
+{
+ const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+ /* xmm -> m128 */
+ x86::Mem cache = x86::xmmword_ptr(regs_i64[hreg_info->exec_env_hreg_index],
+ offsetof(WASMExecEnv, jit_cache));
+ a.movups(cache, regs_float[reg_no2_src]);
+
+ /* imm -> gp -> xmm */
+ mov_imm_to_r_f32(a, reg_no_dst, data1_src);
+
+ return alu_r_m_float(a, op, reg_no_dst, cache, true);
+}
+
+/**
+ * Encode float alu operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_imm_to_r_f32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, float data2_src)
+{
+ const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+ /* imm -> m32 */
+ x86::Mem cache = x86::dword_ptr(regs_i64[hreg_info->exec_env_hreg_index],
+ offsetof(WASMExecEnv, jit_cache));
+ cast_float_to_integer v = { .f = data2_src };
+ Imm imm(v.i);
+ mov_imm_to_m(a, cache, imm, 4);
+
+ mov_r_to_r_f32(a, reg_no_dst, reg_no1_src);
+ return alu_r_m_float(a, op, reg_no_dst, cache, true);
+}
+
+/**
+ * Encode float alu operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_to_r_f32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ bool store_result = false;
+
+ /**
+ * - op r0,r0,r1. do nothing since instructions always store results in
+ * the first register
+ *
+ * - op r1,r0,r1. use FREE_REG to cache and replace r0, and then store
+ * results in r1
+ *
+ * - op r0,r1,r2. use r0 to cache and replace r1, and accept the result
+ * naturally
+ **/
+ if (reg_no_dst == reg_no2_src) {
+ store_result = true;
+ reg_no_dst = REG_F32_FREE_IDX;
+ }
+ mov_r_to_r_f32(a, reg_no_dst, reg_no1_src);
+
+ switch (op) {
+ case ADD:
+ {
+ a.addss(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case SUB:
+ {
+ a.subss(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case MUL:
+ {
+ a.mulss(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case DIV_S:
+ {
+ a.divss(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case MAX:
+ {
+ a.maxss(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case MIN:
+ {
+ a.minss(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ if (store_result)
+ mov_r_to_r_f32(a, reg_no2_src, REG_F32_FREE_IDX);
+
+ return true;
+}
+
+/**
+ * Encode double alu operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_imm_to_r_f64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ double data1_src, double data2_src)
+{
+ Imm imm;
+ double data = 0;
+
+ switch (op) {
+ case ADD:
+ {
+ data = data1_src + data2_src;
+ break;
+ }
+ case SUB:
+ {
+ data = data1_src - data2_src;
+ break;
+ }
+ case MUL:
+ {
+ data = data1_src * data2_src;
+ break;
+ }
+ case DIV_S:
+ {
+ data = data1_src / data2_src;
+ break;
+ }
+ case MAX:
+ {
+ data = fmax(data1_src, data2_src);
+ break;
+ }
+ case MIN:
+ {
+ data = fmin(data1_src, data2_src);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ return mov_imm_to_r_f64(a, reg_no_dst, data);
+}
+
+/**
+ * Encode double alu operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_imm_r_to_r_f64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ double data1_src, int32 reg_no2_src)
+{
+ const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+ /* xmm -> m128 */
+ x86::Mem cache = x86::qword_ptr(regs_i64[hreg_info->exec_env_hreg_index],
+ offsetof(WASMExecEnv, jit_cache));
+ a.movupd(cache, regs_float[reg_no2_src]);
+
+ /* imm -> gp -> xmm */
+ mov_imm_to_r_f64(a, reg_no_dst, data1_src);
+
+ return alu_r_m_float(a, op, reg_no_dst, cache, false);
+}
+
+/**
+ * Encode double alu operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_imm_to_r_f64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, double data2_src)
+{
+ const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+ /* imm -> m64 */
+ x86::Mem cache = x86::qword_ptr(regs_i64[hreg_info->exec_env_hreg_index],
+ offsetof(WASMExecEnv, jit_cache));
+ cast_double_to_integer v = { .d = data2_src };
+ Imm imm(v.i);
+ mov_imm_to_m(a, cache, imm, 8);
+
+ mov_r_to_r_f64(a, reg_no_dst, reg_no1_src);
+ return alu_r_m_float(a, op, reg_no_dst, cache, false);
+}
+
+/**
+ * Encode double alu operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of ALU operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+alu_r_r_to_r_f64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ bool store_result = false;
+
+ /**
+ * - op r0,r0,r1. do nothing since instructions always store results in
+ * the first register
+ *
+ * - op r1,r0,r1. use FREE_REG to cache and replace r0, and then store
+ * results in r1
+ *
+ * - op r0,r1,r2. use r0 to cache and replace r1, and accept the result
+ * naturally
+ **/
+ if (reg_no_dst == reg_no2_src) {
+ store_result = true;
+ reg_no_dst = REG_F64_FREE_IDX;
+ }
+ mov_r_to_r_f64(a, reg_no_dst, reg_no1_src);
+
+ switch (op) {
+ case ADD:
+ {
+ a.addsd(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case SUB:
+ {
+ a.subsd(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case MUL:
+ {
+ a.mulsd(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case DIV_S:
+ {
+ a.divsd(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case MAX:
+ {
+ a.maxsd(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ case MIN:
+ {
+ a.minsd(regs_float[reg_no_dst], regs_float[reg_no2_src]);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ if (store_result)
+ mov_r_to_r_f64(a, reg_no2_src, REG_F64_FREE_IDX);
+
+ return true;
+}
+
+/**
+ * Encode int32 bit operation of reg and data, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no the no of register, as first operand, and save result
+ * @param data the immediate data, as the second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_imm_i32(x86::Assembler &a, BIT_OP op, int32 reg_no, int32 data)
+{
+ Imm imm(data);
+
+ switch (op) {
+ case OR:
+ if (data != 0)
+ a.or_(regs_i32[reg_no], imm);
+ break;
+ case XOR:
+ if (data == -1)
+ a.not_(regs_i32[reg_no]);
+ else if (data != 0)
+ a.xor_(regs_i32[reg_no], imm);
+ break;
+ case AND:
+ if (data != -1)
+ a.and_(regs_i32[reg_no], imm);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ return true;
+}
+
+/**
+ * Encode int32 bit operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register, as first operand, and save result
+ * @param reg_no_src the no of register, as second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_r_i32(x86::Assembler &a, BIT_OP op, int32 reg_no_dst, int32 reg_no_src)
+{
+ switch (op) {
+ case OR:
+ a.or_(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ break;
+ case XOR:
+ a.xor_(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ break;
+ case AND:
+ a.and_(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ return true;
+}
+
+/**
+ * Encode int32 bit operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_imm_imm_to_r_i32(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 data1_src, int32 data2_src)
+{
+ Imm imm;
+
+ switch (op) {
+ case OR:
+ imm.setValue(data1_src | data2_src);
+ break;
+ case XOR:
+ imm.setValue(data1_src ^ data2_src);
+ break;
+ case AND:
+ imm.setValue(data1_src & data2_src);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ a.mov(regs_i32[reg_no_dst], imm);
+ return true;
+}
+
+/**
+ * Encode int32 bit operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_imm_r_to_r_i32(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 data1_src, int32 reg_no2_src)
+{
+ if (op == AND && data1_src == 0)
+ a.xor_(regs_i32[reg_no_dst], regs_i32[reg_no_dst]);
+ else if (op == OR && data1_src == -1) {
+ Imm imm(-1);
+ a.mov(regs_i32[reg_no_dst], imm);
+ }
+ else {
+ mov_r_to_r_i32(a, reg_no_dst, reg_no2_src);
+ return bit_r_imm_i32(a, op, reg_no_dst, data1_src);
+ }
+ return true;
+}
+
+/**
+ * Encode int32 bit operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_imm_to_r_i32(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 data2_src)
+{
+ return bit_imm_r_to_r_i32(a, op, reg_no_dst, data2_src, reg_no1_src);
+}
+
+/**
+ * Encode int32 bit operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_r_to_r_i32(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r_i32(a, reg_no_dst, reg_no1_src);
+ return bit_r_r_i32(a, op, reg_no_dst, reg_no2_src);
+ }
+ else
+ return bit_r_r_i32(a, op, reg_no_dst, reg_no1_src);
+ return false;
+}
+
+/**
+ * Encode int64 bit operation of reg and data, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no the no of register, as first operand, and save result
+ * @param data the immediate data, as the second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_imm_i64(x86::Assembler &a, BIT_OP op, int32 reg_no, int64 data)
+{
+ Imm imm(data);
+
+ switch (op) {
+ case OR:
+ if (data != 0) {
+ if (data >= INT32_MIN && data <= INT32_MAX) {
+ imm.setValue((int32)data);
+ a.or_(regs_i64[reg_no], imm);
+ }
+ else {
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.or_(regs_i64[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ }
+ }
+ break;
+ case XOR:
+ if (data == -1LL)
+ a.not_(regs_i64[reg_no]);
+ else if (data != 0) {
+ if (data >= INT32_MIN && data <= INT32_MAX) {
+ imm.setValue((int32)data);
+ a.xor_(regs_i64[reg_no], imm);
+ }
+ else {
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.xor_(regs_i64[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ }
+ }
+ break;
+ case AND:
+ if (data != -1LL) {
+ if (data >= INT32_MIN && data <= INT32_MAX) {
+ imm.setValue((int32)data);
+ a.and_(regs_i64[reg_no], imm);
+ }
+ else {
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.and_(regs_i64[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ }
+ }
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ return true;
+}
+
+/**
+ * Encode int64 bit operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register, as first operand, and save result
+ * @param reg_no_src the no of register, as second operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_r_i64(x86::Assembler &a, BIT_OP op, int32 reg_no_dst, int32 reg_no_src)
+{
+ switch (op) {
+ case OR:
+ a.or_(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ break;
+ case XOR:
+ a.xor_(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ break;
+ case AND:
+ a.and_(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ return true;
+}
+
+/**
+ * Encode int64 bit operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_imm_imm_to_r_i64(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 data1_src, int64 data2_src)
+{
+ Imm imm;
+
+ switch (op) {
+ case OR:
+ imm.setValue(data1_src | data2_src);
+ break;
+ case XOR:
+ imm.setValue(data1_src ^ data2_src);
+ break;
+ case AND:
+ imm.setValue(data1_src & data2_src);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ a.mov(regs_i64[reg_no_dst], imm);
+ return true;
+}
+
+/**
+ * Encode int64 bit operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_imm_r_to_r_i64(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int64 data1_src, int32 reg_no2_src)
+{
+ if (op == AND && data1_src == 0)
+ a.xor_(regs_i64[reg_no_dst], regs_i64[reg_no_dst]);
+ else if (op == OR && data1_src == -1LL) {
+ Imm imm(-1LL);
+ a.mov(regs_i64[reg_no_dst], imm);
+ }
+ else {
+ mov_r_to_r_i64(a, reg_no_dst, reg_no2_src);
+ return bit_r_imm_i64(a, op, reg_no_dst, data1_src);
+ }
+ return true;
+}
+
+/**
+ * Encode int64 bit operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_imm_to_r_i64(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int64 data2_src)
+{
+ return bit_imm_r_to_r_i64(a, op, reg_no_dst, data2_src, reg_no1_src);
+}
+
+/**
+ * Encode int64 bit operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BIT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bit_r_r_to_r_i64(x86::Assembler &a, BIT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ if (reg_no_dst != reg_no2_src) {
+ mov_r_to_r_i64(a, reg_no_dst, reg_no1_src);
+ return bit_r_r_i64(a, op, reg_no_dst, reg_no2_src);
+ }
+ else
+ return bit_r_r_i64(a, op, reg_no_dst, reg_no1_src);
+ return false;
+}
+
+/**
+ * Encode int32 shift operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of SHIFT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_imm_imm_to_r_i32(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int32 data1_src, int32 data2_src)
+{
+ int32 data;
+ switch (op) {
+ case SHL:
+ {
+ data = data1_src << data2_src;
+ break;
+ }
+ case SHRS:
+ {
+ data = data1_src >> data2_src;
+ break;
+ }
+ case SHRU:
+ {
+ data = ((uint32)data1_src) >> data2_src;
+ break;
+ }
+ case ROTL:
+ {
+ data = (data1_src << data2_src)
+ | (((uint32)data1_src) >> (32 - data2_src));
+ break;
+ }
+ case ROTR:
+ {
+ data = (((uint32)data1_src) >> data2_src)
+ | (data1_src << (32 - data2_src));
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return mov_imm_to_r_i32(a, reg_no_dst, data);
+fail:
+ return false;
+}
+
+/**
+ * Encode int32 shift operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of SHIFT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_imm_r_to_r_i32(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int32 data1_src, int32 reg_no2_src)
+{
+ /* Should have been optimized by previous lower */
+ bh_assert(0);
+ (void)a;
+ (void)op;
+ (void)reg_no_dst;
+ (void)data1_src;
+ (void)reg_no2_src;
+ return false;
+}
+
+/**
+ * Encode int32 shift operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of SHIFT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_r_imm_to_r_i32(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 data2_src)
+{
+ /* SHL/SHA/SHR r/m32, imm8 */
+ Imm imm((uint8)data2_src);
+
+ mov_r_to_r_i32(a, reg_no_dst, reg_no1_src);
+ switch (op) {
+ case SHL:
+ {
+ a.shl(regs_i32[reg_no_dst], imm);
+ break;
+ }
+ case SHRS:
+ {
+ a.sar(regs_i32[reg_no_dst], imm);
+ break;
+ }
+ case SHRU:
+ {
+ a.shr(regs_i32[reg_no_dst], imm);
+ break;
+ }
+ case ROTL:
+ {
+ a.rol(regs_i32[reg_no_dst], imm);
+ break;
+ }
+ case ROTR:
+ {
+ a.ror(regs_i32[reg_no_dst], imm);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode int32 shift operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of shift operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_r_r_to_r_i32(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ /* should be CL */
+ if (reg_no2_src != REG_ECX_IDX)
+ return false;
+
+ mov_r_to_r_i32(a, reg_no_dst, reg_no1_src);
+
+ switch (op) {
+ case SHL:
+ {
+ a.shl(regs_i32[reg_no_dst], x86::cl);
+ break;
+ }
+ case SHRS:
+ {
+ a.sar(regs_i32[reg_no_dst], x86::cl);
+ break;
+ }
+ case SHRU:
+ {
+ a.shr(regs_i32[reg_no_dst], x86::cl);
+ break;
+ }
+ case ROTL:
+ {
+ a.rol(regs_i32[reg_no_dst], x86::cl);
+ break;
+ }
+ case ROTR:
+ {
+ a.ror(regs_i32[reg_no_dst], x86::cl);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode int64 shift operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of SHIFT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_imm_imm_to_r_i64(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int64 data1_src, int64 data2_src)
+{
+ int64 data;
+
+ switch (op) {
+ case SHL:
+ {
+ data = data1_src << data2_src;
+ break;
+ }
+ case SHRS:
+ {
+ data = data1_src >> data2_src;
+ break;
+ }
+ case SHRU:
+ {
+ data = ((uint64)data1_src) >> data2_src;
+ break;
+ }
+ case ROTL:
+ {
+ data = (data1_src << data2_src)
+ | (((uint64)data1_src) >> (64LL - data2_src));
+ break;
+ }
+ case ROTR:
+ {
+ data = (((uint64)data1_src) >> data2_src)
+ | (data1_src << (64LL - data2_src));
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return mov_imm_to_r_i64(a, reg_no_dst, data);
+fail:
+ return false;
+}
+
+/**
+ * Encode int64 shift operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of SHIFT operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_imm_r_to_r_i64(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int64 data1_src, int32 reg_no2_src)
+{
+ /* Should have been optimized by previous lower */
+ bh_assert(0);
+ (void)a;
+ (void)op;
+ (void)reg_no_dst;
+ (void)data1_src;
+ (void)reg_no2_src;
+ return false;
+}
+
+/**
+ * Encode int64 shift operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of SHIFT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_r_imm_to_r_i64(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int64 data2_src)
+{
+ /* SHL/SHA/SHR r/m64, imm8 */
+ Imm imm((uint8)data2_src);
+
+ mov_r_to_r_i64(a, reg_no_dst, reg_no1_src);
+ switch (op) {
+ case SHL:
+ {
+ a.shl(regs_i64[reg_no_dst], imm);
+ break;
+ }
+ case SHRS:
+ {
+ a.sar(regs_i64[reg_no_dst], imm);
+ break;
+ }
+ case SHRU:
+ {
+ a.shr(regs_i64[reg_no_dst], imm);
+ break;
+ }
+ case ROTL:
+ {
+ a.rol(regs_i64[reg_no_dst], imm);
+ break;
+ }
+ case ROTR:
+ {
+ a.ror(regs_i64[reg_no_dst], imm);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode int64 shift operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of shift operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+shift_r_r_to_r_i64(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
+ int32 reg_no1_src, int32 reg_no2_src)
+{
+ /* should be CL */
+ if (reg_no2_src != REG_ECX_IDX)
+ return false;
+
+ mov_r_to_r_i64(a, reg_no_dst, reg_no1_src);
+
+ switch (op) {
+ case SHL:
+ {
+ a.shl(regs_i64[reg_no_dst], x86::cl);
+ break;
+ }
+ case SHRS:
+ {
+ a.sar(regs_i64[reg_no_dst], x86::cl);
+ break;
+ }
+ case SHRU:
+ {
+ a.shr(regs_i64[reg_no_dst], x86::cl);
+ break;
+ }
+ case ROTL:
+ {
+ a.rol(regs_i64[reg_no_dst], x86::cl);
+ break;
+ }
+ case ROTR:
+ {
+ a.ror(regs_i64[reg_no_dst], x86::cl);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode int32 cmp operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_imm_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 data1_src,
+ int32 data2_src)
+{
+ Imm imm(data1_src);
+ a.mov(regs_i32[REG_I32_FREE_IDX], imm);
+ imm.setValue(data2_src);
+ a.cmp(regs_i32[REG_I32_FREE_IDX], imm);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int32 cmp operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 data1_src,
+ int32 reg_no2_src)
+{
+ Imm imm(data1_src);
+ a.mov(regs_i32[REG_I32_FREE_IDX], imm);
+ a.cmp(regs_i32[REG_I32_FREE_IDX], regs_i32[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int32 cmp operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_imm_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ int32 data2_src)
+{
+ Imm imm(data2_src);
+ a.cmp(regs_i32[reg_no1_src], imm);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int32 cmp operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ int32 reg_no2_src)
+{
+ a.cmp(regs_i32[reg_no1_src], regs_i32[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int64 cmp operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_imm_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 data1_src,
+ int32 data2_src)
+{
+ Imm imm(data1_src);
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ imm.setValue(data2_src);
+ a.cmp(regs_i64[REG_I64_FREE_IDX], imm);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int64 cmp operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_r_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int64 data1_src,
+ int32 reg_no2_src)
+{
+ Imm imm(data1_src);
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.cmp(regs_i64[REG_I64_FREE_IDX], regs_i64[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int64 cmp operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_imm_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ int64 data2_src)
+{
+ Imm imm(data2_src);
+
+ if (data2_src >= INT32_MIN && data2_src <= INT32_MAX) {
+ imm.setValue((int32)data2_src);
+ a.cmp(regs_i64[reg_no1_src], imm);
+ }
+ else {
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.cmp(regs_i64[reg_no1_src], regs_i64[REG_I64_FREE_IDX]);
+ }
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode int64 cmp operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_r_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ int32 reg_no2_src)
+{
+ a.cmp(regs_i64[reg_no1_src], regs_i64[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode float cmp operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_r_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ int32 reg_no2_src)
+{
+ a.comiss(regs_float[reg_no1_src], regs_float[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode float cmp operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_imm_to_r_f32(x86::Assembler &a, int32 reg_no_dst, float data1_src,
+ float data2_src)
+{
+ /* should have been optimized in the frontend */
+ bh_assert(0);
+ (void)a;
+ (void)reg_no_dst;
+ (void)data1_src;
+ (void)data2_src;
+ return false;
+}
+
+/**
+ * Encode float cmp operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_r_to_r_f32(x86::Assembler &a, int32 reg_no_dst, float data1_src,
+ int32 reg_no2_src)
+{
+ mov_imm_to_r_f32(a, REG_F32_FREE_IDX, data1_src);
+ a.comiss(regs_float[REG_F32_FREE_IDX], regs_float[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode float cmp operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_imm_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ float data2_src)
+{
+ mov_imm_to_r_f32(a, REG_F32_FREE_IDX, data2_src);
+ a.comiss(regs_float[reg_no1_src], regs_float[REG_F32_FREE_IDX]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode double cmp operation of reg and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_r_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ int32 reg_no2_src)
+{
+ a.comisd(regs_float[reg_no1_src], regs_float[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode double cmp operation of imm and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_imm_to_r_f64(x86::Assembler &a, int32 reg_no_dst, double data1_src,
+ double data2_src)
+{
+ /* should have been optimized in the frontend */
+ bh_assert(0);
+ (void)a;
+ (void)reg_no_dst;
+ (void)data1_src;
+ (void)data2_src;
+ return false;
+}
+
+/**
+ * Encode double cmp operation of imm and reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param data1_src the first src immediate data
+ * @param reg_no2_src the reg no of second src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_imm_r_to_r_f64(x86::Assembler &a, int32 reg_no_dst, double data1_src,
+ int32 reg_no2_src)
+{
+ mov_imm_to_r_f64(a, REG_F64_FREE_IDX, data1_src);
+ a.comisd(regs_float[REG_F64_FREE_IDX], regs_float[reg_no2_src]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode double cmp operation of reg and imm, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of cmp operation
+ * @param reg_no_dst the no of register
+ * @param reg_no1_src the reg no of first src register data
+ * @param data2_src the second src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cmp_r_imm_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
+ double data2_src)
+{
+ mov_imm_to_r_f64(a, REG_F64_FREE_IDX, data2_src);
+ a.comisd(regs_float[reg_no1_src], regs_float[REG_F64_FREE_IDX]);
+ (void)reg_no_dst;
+ return true;
+}
+
+/**
+ * Encode insn ld: LD_type r0, r1, r2
+ * @param kind the data kind, such as I32, I64, F32 and F64
+ * @param bytes_dst the byte number of dst data
+ * @param is_signed the data is signed or unsigned
+ */
+#define LD_R_R_R(kind, bytes_dst, is_signed) \
+ do { \
+ int32 reg_no_dst = 0, reg_no_base = 0, reg_no_offset = 0; \
+ int32 base = 0, offset = 0; \
+ bool _ret = false; \
+ \
+ if (jit_reg_is_const(r1)) { \
+ CHECK_KIND(r1, JIT_REG_KIND_I32); \
+ } \
+ else { \
+ CHECK_KIND(r1, JIT_REG_KIND_I64); \
+ } \
+ if (jit_reg_is_const(r2)) { \
+ CHECK_KIND(r2, JIT_REG_KIND_I32); \
+ } \
+ else { \
+ CHECK_KIND(r2, JIT_REG_KIND_I64); \
+ } \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ if (jit_reg_is_const(r1)) \
+ base = jit_cc_get_const_I32(cc, r1); \
+ else { \
+ reg_no_base = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_base, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r2)) \
+ offset = jit_cc_get_const_I32(cc, r2); \
+ else { \
+ reg_no_offset = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_offset, jit_reg_kind(r2)); \
+ } \
+ \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = ld_r_from_base_imm_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, is_signed, reg_no_dst, \
+ base, offset); \
+ else \
+ _ret = ld_r_from_base_imm_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, is_signed, reg_no_dst, \
+ base, reg_no_offset); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = ld_r_from_base_r_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, is_signed, reg_no_dst, \
+ reg_no_base, offset); \
+ else \
+ _ret = ld_r_from_base_r_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, is_signed, reg_no_dst, \
+ reg_no_base, reg_no_offset); \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode insn sd: ST_type r0, r1, r2
+ * @param kind the data kind, such as I32, I64, F32 and F64
+ * @param bytes_dst the byte number of dst data
+ * @param atomic whether it's atomic store
+ */
+#define ST_R_R_R(kind, type, bytes_dst, atomic) \
+ do { \
+ type data_src = 0; \
+ int32 reg_no_src = 0, reg_no_base = 0, reg_no_offset = 0; \
+ int32 base = 0, offset = 0; \
+ bool _ret = false; \
+ \
+ if (jit_reg_is_const(r1)) { \
+ CHECK_KIND(r1, JIT_REG_KIND_I32); \
+ } \
+ else { \
+ CHECK_KIND(r1, JIT_REG_KIND_I64); \
+ } \
+ if (jit_reg_is_const(r2)) { \
+ CHECK_KIND(r2, JIT_REG_KIND_I32); \
+ } \
+ else { \
+ CHECK_KIND(r2, JIT_REG_KIND_I64); \
+ } \
+ \
+ if (jit_reg_is_const(r0)) \
+ data_src = jit_cc_get_const_##kind(cc, r0); \
+ else { \
+ reg_no_src = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_src, jit_reg_kind(r0)); \
+ } \
+ if (jit_reg_is_const(r1)) \
+ base = jit_cc_get_const_I32(cc, r1); \
+ else { \
+ reg_no_base = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_base, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r2)) \
+ offset = jit_cc_get_const_I32(cc, r2); \
+ else { \
+ reg_no_offset = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_offset, jit_reg_kind(r2)); \
+ } \
+ \
+ if (jit_reg_is_const(r0)) { \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = st_imm_to_base_imm_offset_imm( \
+ a, bytes_dst, &data_src, base, offset, atomic); \
+ else \
+ _ret = st_imm_to_base_imm_offset_r( \
+ a, bytes_dst, &data_src, base, reg_no_offset, atomic); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = st_imm_to_base_r_offset_imm( \
+ a, bytes_dst, &data_src, reg_no_base, offset, atomic); \
+ else \
+ _ret = st_imm_to_base_r_offset_r(a, bytes_dst, &data_src, \
+ reg_no_base, reg_no_offset, \
+ atomic); \
+ } \
+ else if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = st_r_to_base_imm_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_src, base, \
+ offset, atomic); \
+ else \
+ _ret = st_r_to_base_imm_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_src, base, \
+ reg_no_offset, atomic); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = st_r_to_base_r_offset_imm(a, bytes_dst, \
+ JIT_REG_KIND_##kind, reg_no_src, \
+ reg_no_base, offset, atomic); \
+ else \
+ _ret = st_r_to_base_r_offset_r(a, bytes_dst, JIT_REG_KIND_##kind, \
+ reg_no_src, reg_no_base, \
+ reg_no_offset, atomic); \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode insn mov: MOV r0, r1
+ * @param kind the data kind, such as I32, I64, F32 and F64
+ * @param Type the data type, such as int32, int64, float32, and float64
+ * @param type the abbreviation of data type, such as i32, i64, f32, and f64
+ * @param bytes_dst the byte number of dst data
+ */
+#define MOV_R_R(kind, Type, type) \
+ do { \
+ bool _ret = false; \
+ int32 reg_no_dst = 0, reg_no_src = 0; \
+ CHECK_EQKIND(r0, r1); \
+ \
+ CHECK_NCONST(r0); \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ \
+ if (jit_reg_is_const(r1)) { \
+ Type data = jit_cc_get_const_##kind(cc, r1); \
+ _ret = mov_imm_to_r_##type(a, reg_no_dst, data); \
+ } \
+ else { \
+ reg_no_src = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src, jit_reg_kind(r1)); \
+ _ret = mov_r_to_r_##type(a, reg_no_dst, reg_no_src); \
+ } \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode mov insn, MOV r0, r1
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_mov(JitCompContext *cc, x86::Assembler &a, JitReg r0, JitReg r1)
+{
+ switch (jit_reg_kind(r0)) {
+ case JIT_REG_KIND_I32:
+ MOV_R_R(I32, int32, i32);
+ break;
+ case JIT_REG_KIND_I64:
+ MOV_R_R(I64, int64, i64);
+ break;
+ case JIT_REG_KIND_F32:
+ MOV_R_R(F32, float32, f32);
+ break;
+ case JIT_REG_KIND_F64:
+ MOV_R_R(F64, float64, f64);
+ break;
+ default:
+ LOG_VERBOSE("Invalid reg type of mov: %d\n", jit_reg_kind(r0));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode insn neg: NEG r0, r1
+ * @param kind the data kind, such as I32, I64, F32 and F64
+ * @param Type the data type, such as int32, int64, float32, and float64
+ * @param type the abbreviation of data type, such as i32, i64, f32, and f64
+ */
+#define NEG_R_R(kind, Type, type) \
+ do { \
+ bool _ret = false; \
+ int32 reg_no_dst = 0, reg_no_src = 0; \
+ CHECK_EQKIND(r0, r1); \
+ \
+ CHECK_NCONST(r0); \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ \
+ if (jit_reg_is_const(r1)) { \
+ Type data = jit_cc_get_const_##kind(cc, r1); \
+ _ret = neg_imm_to_r_##type(a, reg_no_dst, data); \
+ } \
+ else { \
+ reg_no_src = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src, jit_reg_kind(r1)); \
+ _ret = neg_r_to_r_##type(a, reg_no_dst, reg_no_src); \
+ } \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode neg insn, NEG r0, r1
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_neg(JitCompContext *cc, x86::Assembler &a, JitReg r0, JitReg r1)
+{
+ switch (jit_reg_kind(r0)) {
+ case JIT_REG_KIND_I32:
+ NEG_R_R(I32, int32, i32);
+ break;
+ case JIT_REG_KIND_I64:
+ NEG_R_R(I64, int64, i64);
+ break;
+ case JIT_REG_KIND_F32:
+ NEG_R_R(F32, float32, f32);
+ break;
+ case JIT_REG_KIND_F64:
+ NEG_R_R(F64, float64, f64);
+ break;
+ default:
+ LOG_VERBOSE("Invalid reg type of neg: %d\n", jit_reg_kind(r0));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode insn convert: I32TOI8 r0, r1, or I32TOI16, I32TOF32, F32TOF64, etc.
+ * @param kind0 the dst JIT_REG_KIND, such as I32, I64, F32 and F64
+ * @param kind1 the src JIT_REG_KIND, such as I32, I64, F32 and F64
+ * @param type0 the dst data type, such as i8, u8, i16, u16, i32, f32, i64, f32,
+ * f64
+ * @param type1 the src data type, such as i8, u8, i16, u16, i32, f32, i64, f32,
+ * f64
+ */
+#define CONVERT_R_R(kind0, kind1, type0, type1, Type1) \
+ do { \
+ bool _ret = false; \
+ int32 reg_no_dst = 0, reg_no_src = 0; \
+ CHECK_KIND(r0, JIT_REG_KIND_##kind0); \
+ CHECK_KIND(r1, JIT_REG_KIND_##kind1); \
+ \
+ CHECK_NCONST(r0); \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ \
+ if (jit_reg_is_const(r1)) { \
+ Type1 data = jit_cc_get_const_##kind1(cc, r1); \
+ _ret = convert_imm_##type1##_to_r_##type0(a, reg_no_dst, data); \
+ } \
+ else { \
+ reg_no_src = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src, jit_reg_kind(r1)); \
+ _ret = \
+ convert_r_##type1##_to_r_##type0(a, reg_no_dst, reg_no_src); \
+ } \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode insn alu: ADD/SUB/MUL/DIV/REM r0, r1, r2
+ * @param kind the data kind, such as I32, I64, F32 and F64
+ * @param Type the data type, such as int32, int64, float32, and float64
+ * @param type the abbreviation of data type, such as i32, i64, f32, and f64
+ * @param op the opcode of alu
+ */
+#define ALU_R_R_R(kind, Type, type, op) \
+ do { \
+ Type data1, data2; \
+ int32 reg_no_dst = 0, reg_no_src1 = 0, reg_no_src2 = 0; \
+ bool _ret = false; \
+ \
+ CHECK_EQKIND(r0, r1); \
+ CHECK_EQKIND(r0, r2); \
+ memset(&data1, 0, sizeof(Type)); \
+ memset(&data2, 0, sizeof(Type)); \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ if (jit_reg_is_const(r1)) \
+ data1 = jit_cc_get_const_##kind(cc, r1); \
+ else { \
+ reg_no_src1 = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src1, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r2)) \
+ data2 = jit_cc_get_const_##kind(cc, r2); \
+ else { \
+ reg_no_src2 = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_src2, jit_reg_kind(r2)); \
+ } \
+ \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = \
+ alu_imm_imm_to_r_##type(a, op, reg_no_dst, data1, data2); \
+ else \
+ _ret = alu_imm_r_to_r_##type(a, op, reg_no_dst, data1, \
+ reg_no_src2); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = \
+ alu_r_imm_to_r_##type(a, op, reg_no_dst, reg_no_src1, data2); \
+ else \
+ _ret = alu_r_r_to_r_##type(a, op, reg_no_dst, reg_no_src1, \
+ reg_no_src2); \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode alu insn, ADD/SUB/MUL/DIV/REM r0, r1, r2
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param op the opcode of alu operations
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the first src operand info
+ * @param r2 src jit register that contains the second src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_alu(JitCompContext *cc, x86::Assembler &a, ALU_OP op, JitReg r0,
+ JitReg r1, JitReg r2)
+{
+ switch (jit_reg_kind(r0)) {
+ case JIT_REG_KIND_I32:
+ ALU_R_R_R(I32, int32, i32, op);
+ break;
+ case JIT_REG_KIND_I64:
+ ALU_R_R_R(I64, int64, i64, op);
+ break;
+ case JIT_REG_KIND_F32:
+ ALU_R_R_R(F32, float32, f32, op);
+ break;
+ case JIT_REG_KIND_F64:
+ ALU_R_R_R(F64, float64, f64, op);
+ break;
+ default:
+ LOG_VERBOSE("Invalid reg type of alu: %d\n", jit_reg_kind(r0));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode insn bit: AND/OR/XOR r0, r1, r2
+ * @param kind the data kind, such as I32, I64
+ * @param Type the data type, such as int32, int64
+ * @param type the abbreviation of data type, such as i32, i64
+ * @param op the opcode of bit operation
+ */
+#define BIT_R_R_R(kind, Type, type, op) \
+ do { \
+ Type data1, data2; \
+ int32 reg_no_dst = 0, reg_no_src1 = 0, reg_no_src2 = 0; \
+ bool _ret = false; \
+ \
+ CHECK_EQKIND(r0, r1); \
+ CHECK_EQKIND(r0, r2); \
+ memset(&data1, 0, sizeof(Type)); \
+ memset(&data2, 0, sizeof(Type)); \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ if (jit_reg_is_const(r1)) \
+ data1 = jit_cc_get_const_##kind(cc, r1); \
+ else { \
+ reg_no_src1 = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src1, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r2)) \
+ data2 = jit_cc_get_const_##kind(cc, r2); \
+ else { \
+ reg_no_src2 = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_src2, jit_reg_kind(r2)); \
+ } \
+ \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = \
+ bit_imm_imm_to_r_##type(a, op, reg_no_dst, data1, data2); \
+ else \
+ _ret = bit_imm_r_to_r_##type(a, op, reg_no_dst, data1, \
+ reg_no_src2); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = \
+ bit_r_imm_to_r_##type(a, op, reg_no_dst, reg_no_src1, data2); \
+ else \
+ _ret = bit_r_r_to_r_##type(a, op, reg_no_dst, reg_no_src1, \
+ reg_no_src2); \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode bit insn, AND/OR/XOR r0, r1, r2
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param op the opcode of bit operations
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the first src operand info
+ * @param r2 src jit register that contains the second src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_bit(JitCompContext *cc, x86::Assembler &a, BIT_OP op, JitReg r0,
+ JitReg r1, JitReg r2)
+{
+ switch (jit_reg_kind(r0)) {
+ case JIT_REG_KIND_I32:
+ BIT_R_R_R(I32, int32, i32, op);
+ break;
+ case JIT_REG_KIND_I64:
+ BIT_R_R_R(I64, int64, i64, op);
+ break;
+ default:
+ LOG_VERBOSE("Invalid reg type of bit: %d\n", jit_reg_kind(r0));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode insn shift: SHL/SHRS/SHRU r0, r1, r2
+ * @param kind the data kind, such as I32, I64
+ * @param Type the data type, such as int32, int64
+ * @param type the abbreviation of data type, such as i32, i64
+ * @param op the opcode of shift operation
+ */
+#define SHIFT_R_R_R(kind, Type, type, op) \
+ do { \
+ Type data1, data2; \
+ int32 reg_no_dst = 0, reg_no_src1 = 0, reg_no_src2 = 0; \
+ bool _ret = false; \
+ \
+ CHECK_EQKIND(r0, r1); \
+ CHECK_KIND(r2, JIT_REG_KIND_##kind); \
+ memset(&data1, 0, sizeof(Type)); \
+ memset(&data2, 0, sizeof(Type)); \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ if (jit_reg_is_const(r1)) \
+ data1 = jit_cc_get_const_##kind(cc, r1); \
+ else { \
+ reg_no_src1 = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src1, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r2)) \
+ data2 = jit_cc_get_const_##kind(cc, r2); \
+ else { \
+ reg_no_src2 = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_src2, jit_reg_kind(r2)); \
+ } \
+ \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = shift_imm_imm_to_r_##type(a, op, reg_no_dst, data1, \
+ data2); \
+ else \
+ _ret = shift_imm_r_to_r_##type(a, op, reg_no_dst, data1, \
+ reg_no_src2); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = shift_r_imm_to_r_##type(a, op, reg_no_dst, reg_no_src1, \
+ data2); \
+ else \
+ _ret = shift_r_r_to_r_##type(a, op, reg_no_dst, reg_no_src1, \
+ reg_no_src2); \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode shift insn, SHL/SHRS/SHRU r0, r1, r2
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param op the opcode of shift operations
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the first src operand info
+ * @param r2 src jit register that contains the second src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_shift(JitCompContext *cc, x86::Assembler &a, SHIFT_OP op, JitReg r0,
+ JitReg r1, JitReg r2)
+{
+ switch (jit_reg_kind(r0)) {
+ case JIT_REG_KIND_I32:
+ SHIFT_R_R_R(I32, int32, i32, op);
+ break;
+ case JIT_REG_KIND_I64:
+ SHIFT_R_R_R(I64, int64, i64, op);
+ break;
+ default:
+ LOG_VERBOSE("Invalid reg type of shift: %d\n", jit_reg_kind(r0));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode int32 bitcount operation of reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BITCOUNT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no_src the reg no of first src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bitcount_r_to_r_i32(x86::Assembler &a, BITCOUNT_OP op, int32 reg_no_dst,
+ int32 reg_no_src)
+{
+ switch (op) {
+ case CLZ:
+ a.lzcnt(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ break;
+ case CTZ:
+ a.tzcnt(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ break;
+ case POPCNT:
+ a.popcnt(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Encode int64 bitcount operation of reg, and save result to reg
+ *
+ * @param a the assembler to emit the code
+ * @param op the opcode of BITCOUNT operation
+ * @param reg_no_dst the no of register
+ * @param reg_no_src the reg no of first src register data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+bitcount_r_to_r_i64(x86::Assembler &a, BITCOUNT_OP op, int32 reg_no_dst,
+ int32 reg_no_src)
+{
+ switch (op) {
+ case CLZ:
+ a.lzcnt(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ break;
+ case CTZ:
+ a.tzcnt(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ break;
+ case POPCNT:
+ a.popcnt(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Encode insn bitcount: CLZ/CTZ/POPCNT r0, r1
+ * @param kind the data kind, such as I32, I64
+ * @param Type the data type, such as int32, int64
+ * @param type the abbreviation of data type, such as i32, i64
+ * @param op the opcode of bit operation
+ */
+#define BITCOUNT_R_R(kind, Type, type, op) \
+ do { \
+ int32 reg_no_dst = 0, reg_no_src = 0; \
+ \
+ CHECK_EQKIND(r0, r1); \
+ CHECK_NCONST(r0); \
+ CHECK_NCONST(r1); \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ reg_no_src = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src, jit_reg_kind(r1)); \
+ if (!bitcount_r_to_r_##type(a, op, reg_no_dst, reg_no_src)) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode bitcount insn, CLZ/CTZ/POPCNT r0, r1
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param op the opcode of bitcount operations
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_bitcount(JitCompContext *cc, x86::Assembler &a, BITCOUNT_OP op, JitReg r0,
+ JitReg r1)
+{
+ switch (jit_reg_kind(r0)) {
+ case JIT_REG_KIND_I32:
+ BITCOUNT_R_R(I32, int32, i32, op);
+ break;
+ case JIT_REG_KIND_I64:
+ BITCOUNT_R_R(I64, int64, i64, op);
+ break;
+ default:
+ LOG_VERBOSE("Invalid reg type of bit: %d\n", jit_reg_kind(r0));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode insn cmp: CMP r0, r1, r2
+ * @param kind the data kind, such as I32, I64, F32 and F64
+ * @param Type the data type, such as int32, int64, float32, and float64
+ * @param type the abbreviation of data type, such as i32, i64, f32, and f64
+ */
+#define CMP_R_R_R(kind, Type, type) \
+ do { \
+ Type data1, data2; \
+ int32 reg_no_dst = 0, reg_no_src1 = 0, reg_no_src2 = 0; \
+ bool _ret = false; \
+ \
+ CHECK_KIND(r0, JIT_REG_KIND_I32); \
+ CHECK_KIND(r1, JIT_REG_KIND_##kind); \
+ CHECK_EQKIND(r1, r2); \
+ memset(&data1, 0, sizeof(Type)); \
+ memset(&data2, 0, sizeof(Type)); \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ if (jit_reg_is_const(r1)) \
+ data1 = jit_cc_get_const_##kind(cc, r1); \
+ else { \
+ reg_no_src1 = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src1, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r2)) \
+ data2 = jit_cc_get_const_##kind(cc, r2); \
+ else { \
+ reg_no_src2 = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_src2, jit_reg_kind(r2)); \
+ } \
+ \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r2)) \
+ _ret = cmp_imm_imm_to_r_##type(a, reg_no_dst, data1, data2); \
+ else \
+ _ret = \
+ cmp_imm_r_to_r_##type(a, reg_no_dst, data1, reg_no_src2); \
+ } \
+ else if (jit_reg_is_const(r2)) \
+ _ret = cmp_r_imm_to_r_##type(a, reg_no_dst, reg_no_src1, data2); \
+ else \
+ _ret = \
+ cmp_r_r_to_r_##type(a, reg_no_dst, reg_no_src1, reg_no_src2); \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode cmp insn, CMP r0, r1, r2
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 condition jit register
+ * @param r2 src jit register that contains the first src operand info
+ * @param r3 src jit register that contains the second src operand info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_cmp(JitCompContext *cc, x86::Assembler &a, JitReg r0, JitReg r1,
+ JitReg r2)
+{
+ switch (jit_reg_kind(r1)) {
+ case JIT_REG_KIND_I32:
+ CMP_R_R_R(I32, int32, i32);
+ cc->last_cmp_on_fp = false;
+ break;
+ case JIT_REG_KIND_I64:
+ CMP_R_R_R(I64, int64, i64);
+ cc->last_cmp_on_fp = false;
+ break;
+ case JIT_REG_KIND_F32:
+ CMP_R_R_R(F32, float32, f32);
+ cc->last_cmp_on_fp = true;
+ break;
+ case JIT_REG_KIND_F64:
+ CMP_R_R_R(F64, float64, f64);
+ cc->last_cmp_on_fp = true;
+ break;
+ default:
+ cc->last_cmp_on_fp = false;
+ LOG_VERBOSE("Invalid reg type of cmp: %d\n", jit_reg_kind(r1));
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode detecting the cmp flags in reg, and jmp to the relative address
+ * according to the condition opcode
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param op the condition opcode to jmp
+ * @param offset the relative offset to jmp when the contidtion meeted
+ *
+ * @return return the next address of native code after encoded
+ */
+static bool
+cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, COND_OP op,
+ int32 offset)
+{
+ Imm target(INT32_MAX);
+ char *stream;
+ bool fp_cmp = cc->last_cmp_on_fp;
+
+ bh_assert(!fp_cmp || (fp_cmp && (op == GTS || op == GES)));
+
+ switch (op) {
+ case EQ:
+ {
+ a.je(target);
+ break;
+ }
+ case NE:
+ {
+ a.jne(target);
+ break;
+ }
+ case GTS:
+ {
+ if (fp_cmp) {
+ a.ja(target);
+ }
+ else {
+ a.jg(target);
+ }
+ break;
+ }
+ case LES:
+ {
+ a.jng(target);
+ break;
+ }
+ case GES:
+ {
+ if (fp_cmp) {
+ a.jae(target);
+ }
+ else {
+ a.jnl(target);
+ }
+ break;
+ }
+ case LTS:
+ {
+ a.jl(target);
+ break;
+ }
+ case GTU:
+ {
+ a.ja(target);
+ break;
+ }
+ case LEU:
+ {
+ a.jna(target);
+ break;
+ }
+ case GEU:
+ {
+ a.jae(target);
+ break;
+ }
+ case LTU:
+ {
+ a.jb(target);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ break;
+ }
+ }
+
+ JitErrorHandler *err_handler = (JitErrorHandler *)a.code()->errorHandler();
+
+ if (!err_handler->err) {
+ /* The offset written by asmjit is always 0, we patch it again */
+ stream = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size() - 6;
+ *(int32 *)(stream + 2) = offset;
+ }
+ return true;
+}
+
+/**
+ * Encode select insn, SELECT r0, r1, r2, r3
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the first src operand info
+ * @param r2 src jit register that contains the second src operand info
+ *
+ * @return true if success, false if failed
+ */
+/* TODO: optimize with setcc */
+static bool
+lower_select(JitCompContext *cc, x86::Assembler &a, COND_OP op, JitReg r0,
+ JitReg r1, JitReg r2, JitReg r3)
+{
+ JitErrorHandler err_handler;
+ Environment env(Arch::kX64);
+ CodeHolder code1, code2;
+ char *stream_mov1, *stream_mov2;
+ uint32 size_mov1, size_mov2;
+
+ code1.init(env);
+ code1.setErrorHandler(&err_handler);
+ x86::Assembler a1(&code1);
+
+ code2.init(env);
+ code2.setErrorHandler(&err_handler);
+ x86::Assembler a2(&code2);
+
+ CHECK_NCONST(r0);
+ CHECK_NCONST(r1);
+ CHECK_KIND(r1, JIT_REG_KIND_I32);
+
+ if (r0 == r3 && r0 != r2 && !cc->last_cmp_on_fp) {
+ JitReg r_tmp;
+
+ /* For i32/i64, exchange r2 and r3 to make r0 equal to r2,
+ so as to decrease possible execution instructions.
+ For f32/f64 comparison, should not change the order as
+ the result of comparison with NaN may be different. */
+ r_tmp = r2;
+ r2 = r3;
+ r3 = r_tmp;
+ op = not_cond(op);
+ }
+
+ if (!lower_mov(cc, a1, r0, r2))
+ GOTO_FAIL;
+
+ if (!lower_mov(cc, a2, r0, r3))
+ GOTO_FAIL;
+
+ stream_mov1 = (char *)a1.code()->sectionById(0)->buffer().data();
+ size_mov1 = a1.code()->sectionById(0)->buffer().size();
+ stream_mov2 = (char *)a2.code()->sectionById(0)->buffer().data();
+ size_mov2 = a2.code()->sectionById(0)->buffer().size();
+
+ if (r0 != r2) {
+ a.embedDataArray(TypeId::kInt8, stream_mov1, size_mov1);
+ }
+
+ if (r3 && r0 != r3) {
+ if (!cmp_r_and_jmp_relative(cc, a, op, (int32)size_mov2))
+ return false;
+ a.embedDataArray(TypeId::kInt8, stream_mov2, size_mov2);
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/* jmp to dst label */
+#define JMP_TO_LABEL(label_dst, label_src) \
+ do { \
+ if (label_is_ahead(cc, label_dst, label_src)) { \
+ JitErrorHandler *err_handler = \
+ (JitErrorHandler *)a.code()->errorHandler(); \
+ int32 _offset; \
+ char *stream; \
+ Imm imm(INT32_MAX); \
+ a.jmp(imm); \
+ if (!err_handler->err) { \
+ /* The offset written by asmjit is always 0, we patch it \
+ again, 6 is the size of jmp instruciton */ \
+ stream = (char *)a.code()->sectionById(0)->buffer().data() \
+ + a.code()->sectionById(0)->buffer().size() - 6; \
+ _offset = label_offsets[label_dst] \
+ - a.code()->sectionById(0)->buffer().size(); \
+ *(int32 *)(stream + 2) = _offset; \
+ } \
+ } \
+ else { \
+ if (!jmp_from_label_to_label(a, jmp_info_list, label_dst, \
+ label_src)) \
+ GOTO_FAIL; \
+ } \
+ } while (0)
+
+/**
+ * Encode branch insn, BEQ/BNE/../BLTU r0, r1, r2
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param r0 dst jit register that contains the dst operand info
+ * @param r1 src jit register that contains the first src operand info
+ * @param r2 src jit register that contains the second src operand info
+ * @param is_last_insn if current insn is the last insn of current block
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_branch(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list,
+ int32 label_src, COND_OP op, JitReg r0, JitReg r1, JitReg r2,
+ bool is_last_insn)
+{
+ int32 label_dst;
+
+ CHECK_NCONST(r0);
+ CHECK_KIND(r0, JIT_REG_KIND_I32);
+ CHECK_KIND(r1, JIT_REG_KIND_L32);
+
+ CHECK_REG_NO(jit_reg_no(r0), jit_reg_kind(r0));
+
+ label_dst = jit_reg_no(r1);
+ if (label_dst < (int32)jit_cc_label_num(cc) - 1 && is_last_insn
+ && label_is_neighboring(cc, label_src, label_dst)
+ && !cc->last_cmp_on_fp) {
+ JitReg r_tmp;
+
+ r_tmp = r1;
+ r1 = r2;
+ r2 = r_tmp;
+ op = not_cond(op);
+ }
+
+ if (!cmp_r_and_jmp_label(cc, a, jmp_info_list, label_src, op, r1, r2,
+ is_last_insn))
+ GOTO_FAIL;
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode lookupswitch with key of immediate data
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param label_offsets the offsets of each label
+ * @param label_src the index of src label
+ * @param key the entry key
+ * @param opnd the lookup switch operand
+ * @param is_last_insn if current insn is the last insn of current block
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lookupswitch_imm(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list,
+ uint32 *label_offsets, int32 label_src, int32 key,
+ const JitOpndLookupSwitch *opnd, bool is_last_insn)
+{
+ uint32 i;
+ int32 label_dst;
+
+ for (i = 0; i < opnd->match_pairs_num; i++)
+ if (key == opnd->match_pairs[i].value) {
+ label_dst = jit_reg_no(opnd->match_pairs[i].target);
+ if (!(is_last_insn
+ && label_is_neighboring(cc, label_src, label_dst))) {
+ JMP_TO_LABEL(label_dst, label_src);
+ }
+ return true;
+ }
+
+ if (opnd->default_target) {
+ label_dst = jit_reg_no(opnd->default_target);
+ if (!(is_last_insn && label_is_neighboring(cc, label_src, label_dst))) {
+ JMP_TO_LABEL(label_dst, label_src);
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode detecting lookupswitch entry register and jumping to matched label
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param label_offsets the offsets of each label
+ * @param label_src the index of src label
+ * @param reg_no the no of entry register
+ * @param opnd the lookup switch operand
+ * @param is_last_insn if current insn is the last insn of current block
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lookupswitch_r(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list,
+ uint32 *label_offsets, int32 label_src, int32 reg_no,
+ const JitOpndLookupSwitch *opnd, bool is_last_insn)
+{
+ JmpInfo *node;
+ Imm imm;
+ x86::Mem m;
+ uint32 i;
+ int32 label_dst = 0;
+ char *stream;
+
+ if (opnd->match_pairs_num < 10) {
+ /* For small count of branches, it is better to compare
+ the key with branch value and jump one by one */
+ for (i = 0; i < opnd->match_pairs_num; i++) {
+ imm.setValue(opnd->match_pairs[i].value);
+ a.cmp(regs_i32[reg_no], imm);
+
+ node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
+ if (!node)
+ GOTO_FAIL;
+
+ node->type = JMP_DST_LABEL_REL;
+ node->label_src = label_src;
+ node->dst_info.label_dst = jit_reg_no(opnd->match_pairs[i].target);
+ node->offset = a.code()->sectionById(0)->buffer().size() + 2;
+ bh_list_insert(jmp_info_list, node);
+
+ imm.setValue(INT32_MAX);
+ a.je(imm);
+ }
+
+ if (opnd->default_target) {
+ label_dst = jit_reg_no(opnd->default_target);
+ if (!(is_last_insn
+ && label_is_neighboring(cc, label_src, label_dst)))
+ JMP_TO_LABEL(label_dst, label_src);
+ }
+ }
+ else {
+ /* For bigger count of branches, use indirect jump */
+ /* unsigned extend to rsi */
+ a.mov(regs_i32[REG_I32_FREE_IDX], regs_i32[reg_no]);
+ imm.setValue(opnd->match_pairs_num);
+ a.cmp(regs_i64[REG_I64_FREE_IDX], imm);
+
+ /* Jump to default label if rsi >= br_count */
+ stream = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+ imm.setValue(INT32_MAX);
+ a.jb(imm);
+ *(uint32 *)(stream + 2) = 6;
+
+ node = (JmpInfo *)jit_calloc(sizeof(JmpInfo));
+ if (!node)
+ goto fail;
+
+ node->type = JMP_DST_LABEL_REL;
+ node->label_src = label_src;
+ node->dst_info.label_dst = jit_reg_no(opnd->default_target);
+ node->offset = a.code()->sectionById(0)->buffer().size() + 2;
+ bh_list_insert(jmp_info_list, node);
+
+ imm.setValue(INT32_MAX);
+ a.jmp(imm);
+
+ node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
+ if (!node)
+ GOTO_FAIL;
+
+ node->type = JMP_LOOKUPSWITCH_BASE;
+ node->offset = a.code()->sectionById(0)->buffer().size() + 2;
+ bh_list_insert(jmp_info_list, node);
+
+ /* LookupSwitch table base addr */
+ imm.setValue(INT64_MAX);
+ a.mov(regs_i64[reg_no], imm);
+
+ /* jmp *(base_addr + rsi * 8) */
+ m = x86::ptr(regs_i64[reg_no], regs_i64[REG_I64_FREE_IDX], 3);
+ a.jmp(m);
+
+ /* Store each dst label absolute address */
+ for (i = 0; i < opnd->match_pairs_num; i++) {
+ node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
+ if (!node)
+ GOTO_FAIL;
+
+ node->type = JMP_DST_LABEL_ABS;
+ node->dst_info.label_dst = jit_reg_no(opnd->match_pairs[i].target);
+ node->offset = a.code()->sectionById(0)->buffer().size();
+ bh_list_insert(jmp_info_list, node);
+
+ a.embedUInt64(UINT64_MAX);
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode lookupswitch insn, LOOKUPSWITCH opnd
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param label_offsets the offsets of each label
+ * @param label_src the index of src label
+ * @param opnd the lookup switch operand
+ * @param is_last_insn if current insn is the last insn of current block
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_lookupswitch(JitCompContext *cc, x86::Assembler &a,
+ bh_list *jmp_info_list, uint32 *label_offsets,
+ int32 label_src, const JitOpndLookupSwitch *opnd,
+ bool is_last_insn)
+{
+ JitReg r0 = opnd->value;
+ int32 key, reg_no;
+
+ CHECK_KIND(r0, JIT_REG_KIND_I32);
+ CHECK_KIND(opnd->default_target, JIT_REG_KIND_L32);
+
+ if (jit_reg_is_const(r0)) {
+ key = jit_cc_get_const_I32(cc, r0);
+ if (!lookupswitch_imm(cc, a, jmp_info_list, label_offsets, label_src,
+ key, opnd, is_last_insn))
+ GOTO_FAIL;
+ }
+ else {
+ reg_no = jit_reg_no(r0);
+ CHECK_I32_REG_NO(reg_no);
+ if (!lookupswitch_r(cc, a, jmp_info_list, label_offsets, label_src,
+ reg_no, opnd, is_last_insn))
+ GOTO_FAIL;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode callnative insn, CALLNATIVE r0, r1, ...
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param insn current insn info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_callnative(JitCompContext *cc, x86::Assembler &a, JitInsn *insn)
+{
+ void (*func_ptr)(void);
+ JitReg ret_reg, func_reg, arg_reg;
+ /* the index of callee saved registers in regs_i64 */
+ uint8 regs_arg_idx[] = { REG_RDI_IDX, REG_RSI_IDX, REG_RDX_IDX,
+ REG_RCX_IDX, REG_R8_IDX, REG_R9_IDX };
+ Imm imm;
+ uint32 i, opnd_num;
+ int32 integer_reg_index = 0, floatpoint_reg_index = 0;
+
+ ret_reg = *(jit_insn_opndv(insn, 0));
+ func_reg = *(jit_insn_opndv(insn, 1));
+ CHECK_KIND(func_reg, JIT_REG_KIND_I64);
+ CHECK_CONST(func_reg);
+
+ func_ptr = (void (*)(void))jit_cc_get_const_I64(cc, func_reg);
+
+ opnd_num = jit_insn_opndv_num(insn);
+ for (i = 0; i < opnd_num - 2; i++) {
+ /*TODO: if arguments number is greater than 6 */
+ bh_assert(integer_reg_index < 6);
+ bh_assert(floatpoint_reg_index < 6);
+
+ arg_reg = *(jit_insn_opndv(insn, i + 2));
+ switch (jit_reg_kind(arg_reg)) {
+ case JIT_REG_KIND_I32:
+ {
+ int32 reg_no = regs_arg_idx[integer_reg_index++];
+ CHECK_I64_REG_NO(reg_no);
+ if (jit_reg_is_const(arg_reg)) {
+ mov_imm_to_r_i64(a, reg_no,
+ (int64)jit_cc_get_const_I32(cc, arg_reg));
+ }
+ else {
+ int32 arg_reg_no = jit_reg_no(arg_reg);
+ CHECK_I32_REG_NO(arg_reg_no);
+ extend_r32_to_r64(a, reg_no, arg_reg_no, true);
+ }
+ break;
+ }
+ case JIT_REG_KIND_I64:
+ {
+ int32 reg_no = regs_arg_idx[integer_reg_index++];
+ CHECK_I64_REG_NO(reg_no);
+ if (jit_reg_is_const(arg_reg)) {
+ mov_imm_to_r_i64(a, reg_no,
+ jit_cc_get_const_I64(cc, arg_reg));
+ }
+ else {
+ int32 arg_reg_no = jit_reg_no(arg_reg);
+ CHECK_I64_REG_NO(arg_reg_no);
+ mov_r_to_r_i64(a, reg_no, arg_reg_no);
+ }
+ break;
+ }
+ case JIT_REG_KIND_F32:
+ {
+ CHECK_F32_REG_NO((int32)floatpoint_reg_index);
+ if (jit_reg_is_const(arg_reg)) {
+ mov_imm_to_r_f32(a, floatpoint_reg_index,
+ jit_cc_get_const_F32(cc, arg_reg));
+ }
+ else {
+ int32 arg_reg_no = jit_reg_no(arg_reg);
+ CHECK_F32_REG_NO(arg_reg_no);
+ mov_r_to_r_f32(a, floatpoint_reg_index, arg_reg_no);
+ }
+ floatpoint_reg_index++;
+ break;
+ }
+ case JIT_REG_KIND_F64:
+ {
+ CHECK_F64_REG_NO((int32)floatpoint_reg_index);
+ if (jit_reg_is_const(arg_reg)) {
+ mov_imm_to_r_f64(a, floatpoint_reg_index,
+ jit_cc_get_const_F64(cc, arg_reg));
+ }
+ else {
+ int32 arg_reg_no = jit_reg_no(arg_reg);
+ CHECK_F64_REG_NO(arg_reg_no);
+ mov_r_to_r_f64(a, floatpoint_reg_index, arg_reg_no);
+ }
+ floatpoint_reg_index++;
+ break;
+ }
+ default:
+ {
+
+ bh_assert(0);
+ goto fail;
+ }
+ }
+ }
+
+ imm.setValue((uint64)func_ptr);
+ a.mov(regs_i64[REG_RAX_IDX], imm);
+ a.call(regs_i64[REG_RAX_IDX]);
+
+ if (ret_reg) {
+ uint32 ret_reg_no = jit_reg_no(ret_reg);
+ if (jit_reg_kind(ret_reg) == JIT_REG_KIND_I64) {
+ CHECK_I64_REG_NO(ret_reg_no);
+ /* mov res, rax */
+ mov_r_to_r_i64(a, ret_reg_no, REG_RAX_IDX);
+ }
+ else if (jit_reg_kind(ret_reg) == JIT_REG_KIND_F64) {
+ CHECK_F64_REG_NO(ret_reg_no);
+ /* mov res, xmm0_f64 */
+ mov_r_to_r_f64(a, ret_reg_no, 0);
+ }
+ else {
+ bh_assert((jit_reg_kind(ret_reg) == JIT_REG_KIND_I32
+ && ret_reg_no == REG_EAX_IDX)
+ || (jit_reg_kind(ret_reg) == JIT_REG_KIND_F32
+ && ret_reg_no == 0));
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Encode callbc insn, CALLBC r0, r1, r2
+ *
+ * @param cc the compiler context
+ * @param a the assembler to emit the code
+ * @param jmp_info_list the jmp info list
+ * @param label_src the index of src label
+ * @param insn current insn info
+ *
+ * @return true if success, false if failed
+ */
+static bool
+lower_callbc(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list,
+ int32 label_src, JitInsn *insn)
+{
+ JmpInfo *node;
+ Imm imm;
+ JitReg edx_hreg = jit_reg_new(JIT_REG_KIND_I32, REG_EDX_IDX);
+ JitReg rdx_hreg = jit_reg_new(JIT_REG_KIND_I64, REG_RDX_IDX);
+ JitReg xmm0_f32_hreg = jit_reg_new(JIT_REG_KIND_F32, 0);
+ JitReg xmm0_f64_hreg = jit_reg_new(JIT_REG_KIND_F64, 0);
+ JitReg ret_reg = *(jit_insn_opnd(insn, 0));
+ JitReg func_reg = *(jit_insn_opnd(insn, 2));
+ JitReg func_idx = *(jit_insn_opnd(insn, 3));
+ JitReg src_reg;
+ int32 func_reg_no;
+
+ /* Load return_jitted_addr from stack */
+ x86::Mem m(x86::rbp, cc->jitted_return_address_offset);
+
+ CHECK_KIND(func_reg, JIT_REG_KIND_I64);
+ func_reg_no = jit_reg_no(func_reg);
+ CHECK_I64_REG_NO(func_reg_no);
+
+ CHECK_KIND(func_idx, JIT_REG_KIND_I32);
+ if (jit_reg_is_const(func_idx)) {
+ imm.setValue(jit_cc_get_const_I32(cc, func_idx));
+ a.mov(regs_i64[REG_RDX_IDX], imm);
+ }
+ else {
+ a.movzx(regs_i64[REG_RDX_IDX], regs_i32[jit_reg_no(func_idx)]);
+ }
+
+ node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
+ if (!node)
+ GOTO_FAIL;
+
+ node->type = JMP_END_OF_CALLBC;
+ node->label_src = label_src;
+ node->offset = a.code()->sectionById(0)->buffer().size() + 2;
+ bh_list_insert(jmp_info_list, node);
+
+ /* Set next jited addr to glue_ret_jited_addr, 0 will be replaced with
+ actual offset after actual code cache is allocated */
+ imm.setValue(INT64_MAX);
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.mov(m, regs_i64[REG_I64_FREE_IDX]);
+ a.jmp(regs_i64[func_reg_no]);
+
+ if (ret_reg) {
+ switch (jit_reg_kind(ret_reg)) {
+ case JIT_REG_KIND_I32:
+ src_reg = edx_hreg;
+ break;
+ case JIT_REG_KIND_I64:
+ src_reg = rdx_hreg;
+ break;
+ case JIT_REG_KIND_F32:
+ src_reg = xmm0_f32_hreg;
+ break;
+ case JIT_REG_KIND_F64:
+ src_reg = xmm0_f64_hreg;
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ if (!lower_mov(cc, a, ret_reg, src_reg))
+ return false;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+lower_returnbc(JitCompContext *cc, x86::Assembler &a, JitInsn *insn)
+{
+ JitReg edx_hreg = jit_reg_new(JIT_REG_KIND_I32, REG_EDX_IDX);
+ JitReg rdx_hreg = jit_reg_new(JIT_REG_KIND_I64, REG_RDX_IDX);
+ JitReg xmm0_f32_hreg = jit_reg_new(JIT_REG_KIND_F32, 0);
+ JitReg xmm0_f64_hreg = jit_reg_new(JIT_REG_KIND_F64, 0);
+ JitReg act_reg = *(jit_insn_opnd(insn, 0));
+ JitReg ret_reg = *(jit_insn_opnd(insn, 1));
+ JitReg dst_reg;
+ int32 act;
+
+ CHECK_CONST(act_reg);
+ CHECK_KIND(act_reg, JIT_REG_KIND_I32);
+
+ act = jit_cc_get_const_I32(cc, act_reg);
+
+ if (ret_reg) {
+ switch (jit_reg_kind(ret_reg)) {
+ case JIT_REG_KIND_I32:
+ dst_reg = edx_hreg;
+ break;
+ case JIT_REG_KIND_I64:
+ dst_reg = rdx_hreg;
+ break;
+ case JIT_REG_KIND_F32:
+ dst_reg = xmm0_f32_hreg;
+ break;
+ case JIT_REG_KIND_F64:
+ dst_reg = xmm0_f64_hreg;
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ if (!lower_mov(cc, a, dst_reg, ret_reg))
+ return false;
+ }
+
+ {
+ /* eax = act */
+ Imm imm(act);
+ a.mov(x86::eax, imm);
+
+ x86::Mem m(x86::rbp, cc->jitted_return_address_offset);
+ a.jmp(m);
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+lower_return(JitCompContext *cc, x86::Assembler &a, JitInsn *insn)
+{
+ JitReg act_reg = *(jit_insn_opnd(insn, 0));
+ int32 act;
+
+ CHECK_CONST(act_reg);
+ CHECK_KIND(act_reg, JIT_REG_KIND_I32);
+
+ act = jit_cc_get_const_I32(cc, act_reg);
+ {
+ /* eax = act */
+ Imm imm(act);
+ a.mov(x86::eax, imm);
+
+ imm.setValue((uintptr_t)code_block_return_to_interp_from_jitted);
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.jmp(regs_i64[REG_I64_FREE_IDX]);
+ }
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * Replace all the jmp address pre-saved when the code cache hasn't been
+ * allocated with actual address after code cache allocated
+ *
+ * @param cc compiler context containting the allocated code cacha info
+ * @param jmp_info_list the jmp info list
+ */
+static void
+patch_jmp_info_list(JitCompContext *cc, bh_list *jmp_info_list)
+{
+ JmpInfo *jmp_info, *jmp_info_next;
+ JitReg reg_dst;
+ char *stream;
+
+ jmp_info = (JmpInfo *)bh_list_first_elem(jmp_info_list);
+
+ while (jmp_info) {
+ jmp_info_next = (JmpInfo *)bh_list_elem_next(jmp_info);
+
+ stream = (char *)cc->jitted_addr_begin + jmp_info->offset;
+
+ if (jmp_info->type == JMP_DST_LABEL_REL) {
+ /* Jmp with relative address */
+ reg_dst =
+ jit_reg_new(JIT_REG_KIND_L32, jmp_info->dst_info.label_dst);
+ *(int32 *)stream =
+ (int32)((uintptr_t)*jit_annl_jitted_addr(cc, reg_dst)
+ - (uintptr_t)stream)
+ - 4;
+ }
+ else if (jmp_info->type == JMP_DST_LABEL_ABS) {
+ /* Jmp with absolute address */
+ reg_dst =
+ jit_reg_new(JIT_REG_KIND_L32, jmp_info->dst_info.label_dst);
+ *(uintptr_t *)stream =
+ (uintptr_t)*jit_annl_jitted_addr(cc, reg_dst);
+ }
+ else if (jmp_info->type == JMP_END_OF_CALLBC) {
+ /* 7 is the size of mov and jmp instruction */
+ *(uintptr_t *)stream = (uintptr_t)stream + sizeof(uintptr_t) + 7;
+ }
+ else if (jmp_info->type == JMP_LOOKUPSWITCH_BASE) {
+ /* 11 is the size of 8-byte addr and 3-byte jmp instruction */
+ *(uintptr_t *)stream = (uintptr_t)stream + 11;
+ }
+
+ jmp_info = jmp_info_next;
+ }
+}
+
+/* Free the jmp info list */
+static void
+free_jmp_info_list(bh_list *jmp_info_list)
+{
+ void *cur_node = bh_list_first_elem(jmp_info_list);
+
+ while (cur_node) {
+ void *next_node = bh_list_elem_next(cur_node);
+
+ bh_list_remove(jmp_info_list, cur_node);
+ jit_free(cur_node);
+ cur_node = next_node;
+ }
+}
+
+/**
+ * Encode cast int32 immediate data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst float register
+ * @param data the src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_imm_i32_to_r_f32(x86::Assembler &a, int32 reg_no, int32 data)
+{
+ Imm imm(data);
+ a.mov(regs_i32[REG_I32_FREE_IDX], imm);
+ a.movd(regs_float[reg_no], regs_i32[REG_I32_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode cast int32 register data to float register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst float register
+ * @param reg_no_src the no of src int32 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_r_i32_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.movd(regs_float[reg_no_dst], regs_i32[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode cast int64 immediate data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst double register
+ * @param data the src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_imm_i64_to_r_f64(x86::Assembler &a, int32 reg_no, int64 data)
+{
+ Imm imm(data);
+ a.mov(regs_i64[REG_I64_FREE_IDX], imm);
+ a.movq(regs_float[reg_no], regs_i64[REG_I64_FREE_IDX]);
+ return true;
+}
+
+/**
+ * Encode cast int64 register data to double register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst double register
+ * @param reg_no_src the no of src int64 register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_r_i64_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.movq(regs_float[reg_no_dst], regs_i64[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode cast float immediate data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int32 register
+ * @param data the src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_imm_f32_to_r_i32(x86::Assembler &a, int32 reg_no, float data)
+{
+ cast_float_to_integer v = { .f = data };
+ return mov_imm_to_r_i32(a, reg_no, v.i);
+}
+
+/**
+ * Encode cast float register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_r_f32_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.movd(regs_i32[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode cast double immediate data to int64 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no the no of dst int64 register
+ * @param data the src immediate data
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_imm_f64_to_r_i64(x86::Assembler &a, int32 reg_no, double data)
+{
+ cast_double_to_integer v = { .d = data };
+ return mov_imm_to_r_i64(a, reg_no, v.i);
+}
+
+/**
+ * Encode cast float register data to int32 register data
+ *
+ * @param a the assembler to emit the code
+ * @param reg_no_dst the no of dst int32 register
+ * @param reg_no_src the no of src float register
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+cast_r_f64_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
+{
+ a.movq(regs_i64[reg_no_dst], regs_float[reg_no_src]);
+ return true;
+}
+
+/**
+ * Encode insn cast: F32CASTI32,
+ * @param kind0 the dst JIT_REG_KIND, such as I32, I64, F32 and F64
+ * @param kind1 the src JIT_REG_KIND, such as I32, I64, F32 and F64
+ * @param type0 the dst data type, such as i8, u8, i16, u16, i32, f32, i64, f32,
+ * f64
+ * @param type1 the src data type, such as i8, u8, i16, u16, i32, f32, i64, f32,
+ * f64
+ */
+#define CAST_R_R(kind0, kind1, type0, type1, Type1) \
+ do { \
+ bool _ret = false; \
+ int32 reg_no_dst = 0, reg_no_src = 0; \
+ CHECK_KIND(r0, JIT_REG_KIND_##kind0); \
+ CHECK_KIND(r1, JIT_REG_KIND_##kind1); \
+ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, JIT_REG_KIND_##kind0); \
+ if (jit_reg_is_const(r1)) { \
+ Type1 data = jit_cc_get_const_##kind1(cc, r1); \
+ _ret = cast_imm_##type1##_to_r_##type0(a, reg_no_dst, data); \
+ } \
+ else { \
+ reg_no_src = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src, JIT_REG_KIND_##kind1); \
+ _ret = cast_r_##type1##_to_r_##type0(a, reg_no_dst, reg_no_src); \
+ } \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+
+/**
+ * Encode extend certain bytes in the src register to a I32 or I64 kind value in
+ * dst register
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to extend to, could be I32, I64
+ * @param reg_no_src the index of register hold src value
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+extend_r_to_r(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ int32 reg_no_src, int32 reg_no_dst)
+{
+ if (kind_dst == JIT_REG_KIND_I32) {
+ bh_assert(reg_no_src < 16 && reg_no_dst < 16);
+ switch (bytes_dst) {
+ case 1:
+ extend_r8_to_r32(a, reg_no_dst, reg_no_src, false);
+ break;
+ case 2:
+ extend_r16_to_r32(a, reg_no_dst, reg_no_src, false);
+ break;
+ case 4:
+ mov_r_to_r_i32(a, reg_no_dst, reg_no_src);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+ else if (kind_dst == JIT_REG_KIND_I64) {
+ bh_assert(reg_no_src < 16 && reg_no_dst < 16);
+ switch (bytes_dst) {
+ case 1:
+ extend_r8_to_r64(a, reg_no_dst, reg_no_src, false);
+ break;
+ case 2:
+ extend_r16_to_r64(a, reg_no_dst, reg_no_src, false);
+ break;
+ case 4:
+ extend_r32_to_r64(a, reg_no_dst, reg_no_src, false);
+ break;
+ case 8:
+ mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+ else {
+ bh_assert(0);
+ }
+ return true;
+}
+
+/**
+ * Encode atomic compare and exchange, when calling this function,
+ * value for comparison should be already moved in register
+ * al/ax/eax/rax
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to move, could be I32, I64
+ * @param m_dst the dest memory operand
+ * @param reg_no_xchg the index of register hold exchange value
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+at_cmpxchg(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst,
+ int32 reg_no_xchg, x86::Mem &m_dst)
+{
+ bh_assert((kind_dst == JIT_REG_KIND_I32 && bytes_dst <= 4)
+ || kind_dst == JIT_REG_KIND_I64);
+ bh_assert(reg_no_xchg < 16);
+ switch (bytes_dst) {
+ case 1:
+ a.lock().cmpxchg(m_dst, regs_i8[reg_no_xchg]);
+ break;
+ case 2:
+ a.lock().cmpxchg(m_dst, regs_i16[reg_no_xchg]);
+ break;
+ case 4:
+ a.lock().cmpxchg(m_dst, regs_i32[reg_no_xchg]);
+ break;
+ case 8:
+ a.lock().cmpxchg(m_dst, regs_i64[reg_no_xchg]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Encode atomic compare and exchange: load value into a register from
+ * memory with reg base and reg offset, compare (expected) reg data with the
+ * loaded value, if equal, store the (replacement) reg data to the same
+ * memory, else, do nothing. Either way, returns the loaded value
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_xchg the no of register that stores the conditionally
+ * replacement value
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory
+ * @param reg_no_offset the no of register that stores the offset address
+ * of src&dst memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_cmpxchg_r_ra_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_xchg,
+ int32 reg_no_base, int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return at_cmpxchg(a, bytes_dst, kind_dst, reg_no_xchg, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, REG_RAX_IDX);
+}
+
+/**
+ * Encode atomic compare and exchange: load value into a register from
+ * memory with reg base and imm offset, compare (expected) reg data with the
+ * loaded value, if equal, store the (replacement) reg data to the same
+ * memory, else, do nothing. Either way, returns the loaded value
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_xchg the no of register that stores the conditionally
+ * replacement value
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_cmpxchg_r_ra_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_xchg,
+ int32 reg_no_base, int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return at_cmpxchg(a, bytes_dst, kind_dst, reg_no_xchg, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, REG_RAX_IDX);
+}
+
+/**
+ * Encode atomic compare and exchange: load value into a register from
+ * memory with reg base and reg offset, compare (expected) reg data with the
+ * loaded value, if equal, store the (replacement) imm data to the same
+ * memory, else, do nothing. Either way, returns the loaded value
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param data_xchg the immediate data for exchange(conditionally replacment
+ * value)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory
+ * @param reg_no_offset the no of register that stores the offset address
+ * of src&dst memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_cmpxchg_imm_ra_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, void *data_xchg,
+ int32 reg_no_base, int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_xchg, bytes_dst);
+ uint32 reg_no_xchg = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_cmpxchg(a, bytes_dst, kind_dst, reg_no_xchg, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, REG_RAX_IDX);
+}
+
+/**
+ * Encode atomic compare and exchange: load value into a register from
+ * memory with reg base and imm offset, compare (expected) reg data with the
+ * loaded value, if equal, store the (replacement) imm data to the same
+ * memory, else, do nothing. Either way, returns the loaded value
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param data_xchg the immediate data for exchange(conditionally replacment
+ * value)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_cmpxchg_imm_ra_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, void *data_xchg,
+ int32 reg_no_base, int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_xchg, bytes_dst);
+ uint32 reg_no_xchg = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_cmpxchg(a, bytes_dst, kind_dst, reg_no_xchg, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, REG_RAX_IDX);
+}
+
+/**
+ * Encode insn cmpxchg: CMPXCHG_type r0, r1, r2, r3, r4
+ * @param kind the data kind, can only be I32 or I64
+ * @param bytes_dst the byte number of dst data
+ */
+#define CMPXCHG_R_R_R_R_R(kind, type, bytes_dst) \
+ do { \
+ type data_xchg = 0; \
+ int32 reg_no_xchg = 0, reg_no_cmp = 0, reg_no_base = 0, \
+ reg_no_offset = 0; \
+ int32 offset = 0; \
+ bool _ret = false; \
+ if (jit_reg_is_const(r3)) { \
+ CHECK_KIND(r3, JIT_REG_KIND_I32); \
+ } \
+ else { \
+ CHECK_KIND(r3, JIT_REG_KIND_I64); \
+ } \
+ /* r1: expected value(it must in register a) \
+ * r2: memory base addr can't be const */ \
+ CHECK_NCONST(r1); \
+ reg_no_cmp = jit_reg_no(r1); \
+ bh_assert(reg_no_cmp == REG_EAX_IDX || reg_no_cmp == REG_RAX_IDX); \
+ CHECK_REG_NO(reg_no_cmp, jit_reg_kind(r1)); \
+ CHECK_NCONST(r2); \
+ reg_no_base = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_base, jit_reg_kind(r2)); \
+ /* r0: replacement value r3: offset can be const */ \
+ if (jit_reg_is_const(r0)) \
+ data_xchg = jit_cc_get_const_##kind(cc, r0); \
+ else { \
+ reg_no_xchg = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_xchg, jit_reg_kind(r0)); \
+ } \
+ if (jit_reg_is_const(r3)) \
+ offset = jit_cc_get_const_I32(cc, r3); \
+ else { \
+ reg_no_offset = jit_reg_no(r3); \
+ CHECK_REG_NO(reg_no_offset, jit_reg_kind(r3)); \
+ } \
+ \
+ if (jit_reg_is_const(r0)) { \
+ if (jit_reg_is_const(r3)) \
+ _ret = at_cmpxchg_imm_ra_base_r_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, &data_xchg, \
+ reg_no_base, offset); \
+ else \
+ _ret = at_cmpxchg_imm_ra_base_r_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, &data_xchg, \
+ reg_no_base, reg_no_offset); \
+ } \
+ else { \
+ if (jit_reg_is_const(r3)) \
+ _ret = at_cmpxchg_r_ra_base_r_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_xchg, \
+ reg_no_base, offset); \
+ else \
+ _ret = at_cmpxchg_r_ra_base_r_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_xchg, \
+ reg_no_base, reg_no_offset); \
+ } \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode negate a value in the register
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to move, could be I32, I64
+ * @param reg_no_src the index of register hold src value
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+neg_r(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst, int32 reg_no_src)
+{
+ bh_assert((kind_dst == JIT_REG_KIND_I32 && bytes_dst <= 4)
+ || kind_dst == JIT_REG_KIND_I64);
+ bh_assert(reg_no_src < 16);
+ switch (bytes_dst) {
+ case 1:
+ a.neg(regs_i8[reg_no_src]);
+ break;
+ case 2:
+ a.neg(regs_i16[reg_no_src]);
+ break;
+ case 4:
+ a.neg(regs_i32[reg_no_src]);
+ break;
+ case 8:
+ a.neg(regs_i64[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Encode atomic exchange and add
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to move, could be I32, I64
+ * @param reg_no_src the index of register hold operand value of add operation
+ * @param m_dst the dest memory operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+at_xadd(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst, int32 reg_no_src,
+ x86::Mem &m_dst)
+{
+ bh_assert((kind_dst == JIT_REG_KIND_I32 && bytes_dst <= 4)
+ || kind_dst == JIT_REG_KIND_I64);
+ bh_assert(reg_no_src < 16);
+ switch (bytes_dst) {
+ case 1:
+ a.lock().xadd(m_dst, regs_i8[reg_no_src]);
+ break;
+ case 2:
+ a.lock().xadd(m_dst, regs_i16[reg_no_src]);
+ break;
+ case 4:
+ a.lock().xadd(m_dst, regs_i32[reg_no_src]);
+ break;
+ case 8:
+ a.lock().xadd(m_dst, regs_i64[reg_no_src]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Encode atomic rmw add: load value into a register from memory
+ * with reg base and reg offset, add loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(first operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(second operand&store back)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_add_imm_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw add: load value into a register from memory
+ * with reg base and reg offset, add loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_add_imm_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw add: load value into a register from memory
+ * with reg base and imm offset, add loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_add_r_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw add: load value into a register from memory
+ * with reg base and reg offset, add loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_add_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw sub: load value into a register from memory
+ * with reg base and reg offset, sub loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(first operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(second operand&store back)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_sub_imm_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return neg_r(a, bytes_dst, kind_dst, reg_no_src)
+ && at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw sub: load value into a register from memory
+ * with reg base and reg offset, sub loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_sub_imm_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return neg_r(a, bytes_dst, kind_dst, reg_no_src)
+ && at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw sub: load value into a register from memory
+ * with reg base and imm offset, sub loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_sub_r_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return neg_r(a, bytes_dst, kind_dst, reg_no_src)
+ && at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw sub: load value into a register from memory
+ * with reg base and reg offset, sub loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_sub_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return neg_r(a, bytes_dst, kind_dst, reg_no_src)
+ && at_xadd(a, bytes_dst, kind_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xchg: load value into a register from memory
+ * with reg base and reg offset, exchange loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(first operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(second operand&store back)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xchg_imm_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xchg: load value into a register from memory
+ * with reg base and reg offset, exchange loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xchg_imm_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xchg: load value into a register from memory
+ * with reg base and imm offset, exchange loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xchg_r_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xchg: load value into a register from memory
+ * with reg base and reg offset, exchange loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xchg_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return xchg_r_to_m(a, bytes_dst, kind_dst, m, reg_no_src)
+ && extend_r_to_r(a, bytes_dst, kind_dst, reg_no_src, reg_no_dst);
+}
+
+/**
+ * Encode insn rmw logical operation: generate a loop to make sure it's atomic
+ * @param bin_op the operation, can be and/or/xor
+ * @param kind the data kind, can only be I32 or I64
+ * @param bytes_dst the byte number of dst data
+ */
+#define AT_RMW_LOGICAL_LOOP(bin_op, kind, bytes_dst) \
+ do { \
+ bh_assert((kind_dst == JIT_REG_KIND_I32 && bytes_dst <= 4) \
+ || kind_dst == JIT_REG_KIND_I64); \
+ bh_assert(reg_no_src < 16 && reg_no_dst < 16); \
+ /* read original value in memory(operand 1) to rax(expected) */ \
+ mov_m_to_r(a, bytes_dst, kind_dst, false, REG_RAX_IDX, m_dst); \
+ Label loop = a.newLabel(); \
+ /* check whether loop is valid, and bind the loop label \
+ * to the current position in the code. */ \
+ if (!loop.isValid() || a.bind(loop) != kErrorOk) \
+ return false; \
+ /* move operand 1 to temp reg rb */ \
+ mov_r_to_r(a, kind_dst, REG_RBX_IDX, REG_RAX_IDX); \
+ /* actual logical operation with operand 2, result save to rbx */ \
+ switch (bytes_dst) { \
+ case 1: \
+ a.bin_op##_(regs_i8[REG_RBX_IDX], regs_i8[reg_no_src]); \
+ break; \
+ case 2: \
+ a.bin_op##_(regs_i16[REG_RBX_IDX], regs_i16[reg_no_src]); \
+ break; \
+ case 4: \
+ a.bin_op##_(regs_i32[REG_RBX_IDX], regs_i32[reg_no_src]); \
+ break; \
+ case 8: \
+ a.bin_op##_(regs_i64[REG_RBX_IDX], regs_i64[reg_no_src]); \
+ break; \
+ default: \
+ bh_assert(0); \
+ return false; \
+ } \
+ /* cmp with read value in RAX, try to change with result value in RBX \
+ * REG, if change successfully, mem data is changed and exit loop(ZF \
+ * is set) if not, loop again(ZF is clear) and tries to do logical ops \
+ * atomically */ \
+ at_cmpxchg(a, bytes_dst, kind_dst, REG_RBX_IDX, m_dst); \
+ a.jne(loop); \
+ return true; \
+ } while (0)
+
+/**
+ * Encode atomic logical binary operation: and
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to move, could be I32, I64
+ * @param reg_no_dst the index of dest register
+ * @param reg_no_src the index of register hold operand value of add operation
+ * @param m_dst the dest memory operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+at_and(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, x86::Mem &m_dst)
+{
+ AT_RMW_LOGICAL_LOOP(and, kind_dst, bytes_dst);
+}
+
+/**
+ * Encode atomic logical binary operation: or
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to move, could be I32, I64
+ * @param reg_no_dst the index of dest register
+ * @param reg_no_src the index of register hold operand value of add operation
+ * @param m_dst the dest memory operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+at_or(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, x86::Mem &m_dst)
+{
+ AT_RMW_LOGICAL_LOOP(or, kind_dst, bytes_dst);
+}
+/**
+ * Encode atomic logical binary operation: xor
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data,
+ * could be 1(byte), 2(short), 4(int32), 8(int64),
+ * @param kind_dst the kind of data to move, could be I32, I64
+ * @param reg_no_dst the index of dest register
+ * @param reg_no_src the index of register hold operand value of add operation
+ * @param m_dst the dest memory operand
+ *
+ * @return true if success, false otherwise
+ */
+static bool
+at_xor(x86::Assembler &a, uint32 bytes_dst, uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, x86::Mem &m_dst)
+{
+ AT_RMW_LOGICAL_LOOP(xor, kind_dst, bytes_dst);
+}
+
+/**
+ * Encode atomic rmw and: load value into a register from memory with reg base
+ * and reg offset, bitwise and loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(first operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(second operand&store back)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_and_imm_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_and(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw and: load value into a register from memory with reg base
+ * and reg offset, bitwise and loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_and_imm_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_and(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw and: load value into a register from memory with reg base
+ * and imm offset, bitwise and value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_and_r_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return at_and(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw and: load value into a register from memory with reg base
+ * and reg offset, bitwise and loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_and_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return at_and(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw or: load value into a register from memory with reg base
+ * and reg offset, bitwise or loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(first operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(second operand&store back)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_or_imm_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base, int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_or(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw or: load value into a register from memory with reg base
+ * and reg offset, bitwise or loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_or_imm_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst, void *data_src,
+ int32 reg_no_base, int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_or(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw or: load value into a register from memory with reg base
+ * and imm offset, bitwise or loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_or_r_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base, int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return at_or(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw or: load value into a register from memory with reg base
+ * and reg offset, bitwise or loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_or_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst, int32 reg_no_src,
+ int32 reg_no_base, int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return at_or(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xor: load value into a register from memory with reg base
+ * and reg offset, bitwise xor loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(first operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(second operand&store back)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xor_imm_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_xor(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xor: load value into a register from memory with reg base
+ * and reg offset, bitwise xor loaded value with imm data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param data_src the immediate data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xor_imm_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ void *data_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ Imm imm;
+ imm_set_value(imm, data_src, bytes_dst);
+ uint32 reg_no_src = mov_imm_to_free_reg(a, imm, bytes_dst);
+ return at_xor(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xor: load value into a register from memory with reg base
+ * and imm offset, bitwise xor exchange loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back location)
+ * @param offset the offset address of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xor_r_base_r_offset_imm(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], offset, bytes_dst);
+ return at_xor(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode atomic rmw xor: load value into a register from memory with reg base
+ * and reg offset, bitwise xor loaded value with reg data, store back
+ *
+ * @param a the assembler to emit the code
+ * @param bytes_dst the bytes number of the data to actual operated on(load,
+ * compare, replacement) could be 1(byte), 2(short), 4(int32), 8(int64)
+ * @param reg_no_dst the no of register that stores the returned value
+ * @param reg_no_src the no of register store the src data(second operand)
+ * @param reg_no_base the no of register that stores the base address
+ * of src&dst memory(first operand&store back)
+ * @param reg_no_offset the no of register that stores the offset of the memory
+ * @return true if success, false otherwise
+ */
+static bool
+at_rmw_xor_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
+ uint32 kind_dst, int32 reg_no_dst,
+ int32 reg_no_src, int32 reg_no_base,
+ int32 reg_no_offset)
+{
+ x86::Mem m(regs_i64[reg_no_base], regs_i64[reg_no_offset], 0, 0, bytes_dst);
+ return at_xor(a, bytes_dst, kind_dst, reg_no_dst, reg_no_src, m)
+ && extend_r_to_r(a, bytes_dst, kind_dst, REG_RAX_IDX, reg_no_dst);
+}
+
+/**
+ * Encode insn rmw RMW_type r0, r1, r2, r3
+ * @param bin_op the operation, can be add/sub/xchg/and/or/xor
+ * @param kind the data kind, can only be I32 or I64
+ * @param bytes_dst the byte number of dst data
+ */
+#define AT_RMW_R_R_R_R(bin_op, kind, type, bytes_dst) \
+ do { \
+ type data_src = 0; \
+ int32 reg_no_dst = 0, reg_no_src = 0, reg_no_base = 0, \
+ reg_no_offset = 0; \
+ int32 offset = 0; \
+ bool _ret = false; \
+ if (jit_reg_is_const(r3)) { \
+ CHECK_KIND(r3, JIT_REG_KIND_I32); \
+ } \
+ else { \
+ CHECK_KIND(r3, JIT_REG_KIND_I64); \
+ } \
+ /* r0: read/return value r2: memory base addr can't be const */ \
+ /* already check it's not const in LOAD_4ARGS(); */ \
+ reg_no_dst = jit_reg_no(r0); \
+ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
+ /* mem_data base address has to be non-const */ \
+ CHECK_NCONST(r2); \
+ reg_no_base = jit_reg_no(r2); \
+ CHECK_REG_NO(reg_no_base, jit_reg_kind(r2)); \
+ /* r1: source operand value r3: offset can be const */ \
+ if (jit_reg_is_const(r1)) \
+ data_src = jit_cc_get_const_##kind(cc, r1); \
+ else { \
+ reg_no_src = jit_reg_no(r1); \
+ CHECK_REG_NO(reg_no_src, jit_reg_kind(r1)); \
+ } \
+ if (jit_reg_is_const(r3)) \
+ offset = jit_cc_get_const_I32(cc, r3); \
+ else { \
+ reg_no_offset = jit_reg_no(r3); \
+ CHECK_REG_NO(reg_no_offset, jit_reg_kind(r3)); \
+ } \
+ \
+ if (jit_reg_is_const(r1)) { \
+ if (jit_reg_is_const(r3)) \
+ _ret = at_rmw_##bin_op##_imm_base_r_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_dst, &data_src, \
+ reg_no_base, offset); \
+ else \
+ _ret = at_rmw_##bin_op##_imm_base_r_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_dst, &data_src, \
+ reg_no_base, reg_no_offset); \
+ } \
+ else { \
+ if (jit_reg_is_const(r3)) \
+ _ret = at_rmw_##bin_op##_r_base_r_offset_imm( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_dst, reg_no_src, \
+ reg_no_base, offset); \
+ else \
+ _ret = at_rmw_##bin_op##_r_base_r_offset_r( \
+ a, bytes_dst, JIT_REG_KIND_##kind, reg_no_dst, reg_no_src, \
+ reg_no_base, reg_no_offset); \
+ } \
+ if (!_ret) \
+ GOTO_FAIL; \
+ } while (0)
+
+/**
+ * Encode insn mfence
+ **/
+static void
+fence(x86::Assembler &a)
+{
+ a.mfence();
+}
+
+/**
+ * Encode insn fence
+ */
+#define FENCE() fence(a)
+
+#endif
+
+bool
+jit_codegen_gen_native(JitCompContext *cc)
+{
+ bool atomic;
+ JitBasicBlock *block;
+ JitInsn *insn;
+ JitReg r0, r1, r2, r3, r4;
+ JmpInfo jmp_info_head;
+ bh_list *jmp_info_list = (bh_list *)&jmp_info_head;
+ uint32 label_index, label_num, i;
+ uint32 *label_offsets = NULL, code_size;
+#if CODEGEN_DUMP != 0
+ uint32 code_offset = 0;
+#endif
+ bool return_value = false, is_last_insn;
+ void **jitted_addr;
+ char *code_buf, *stream;
+
+ JitErrorHandler err_handler;
+ Environment env(Arch::kX64);
+ CodeHolder code;
+ code.init(env);
+ code.setErrorHandler(&err_handler);
+ x86::Assembler a(&code);
+
+ if (BH_LIST_SUCCESS != bh_list_init(jmp_info_list)) {
+ jit_set_last_error(cc, "init jmp info list failed");
+ return false;
+ }
+
+ label_num = jit_cc_label_num(cc);
+
+ if (!(label_offsets =
+ (uint32 *)jit_calloc(((uint32)sizeof(uint32)) * label_num))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ goto fail;
+ }
+
+ for (i = 0; i < label_num; i++) {
+ if (i == 0)
+ label_index = 0;
+ else if (i == label_num - 1)
+ label_index = 1;
+ else
+ label_index = i + 1;
+
+ label_offsets[label_index] = code.sectionById(0)->buffer().size();
+
+ block = *jit_annl_basic_block(
+ cc, jit_reg_new(JIT_REG_KIND_L32, label_index));
+
+#if CODEGEN_DUMP != 0
+ os_printf("\nL%d:\n\n", label_index);
+#endif
+
+ JIT_FOREACH_INSN(block, insn)
+ {
+ is_last_insn = (insn->next == block) ? true : false;
+
+#if CODEGEN_DUMP != 0
+ os_printf("\n");
+ jit_dump_insn(cc, insn);
+#endif
+ switch (insn->opcode) {
+ case JIT_OP_MOV:
+ LOAD_2ARGS();
+ if (!lower_mov(cc, a, r0, r1))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_I8TOI32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I32, i32, i8, int8);
+ break;
+
+ case JIT_OP_I8TOI64:
+ LOAD_2ARGS();
+ CONVERT_R_R(I64, I32, i64, i8, int8);
+ break;
+
+ case JIT_OP_I16TOI32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I32, i32, i16, int16);
+ break;
+
+ case JIT_OP_I16TOI64:
+ LOAD_2ARGS();
+ CONVERT_R_R(I64, I32, i64, i16, int16);
+ break;
+
+ case JIT_OP_I32TOI8:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I32, i8, i32, int32);
+ break;
+
+ case JIT_OP_I32TOU8:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I32, u8, i32, int32);
+ break;
+
+ case JIT_OP_I32TOI16:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I32, i16, i32, int32);
+ break;
+
+ case JIT_OP_I32TOU16:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I32, u16, i32, int32);
+ break;
+
+ case JIT_OP_I32TOI64:
+ LOAD_2ARGS();
+ CONVERT_R_R(I64, I32, i64, i32, int32);
+ break;
+
+ case JIT_OP_U32TOI64:
+ LOAD_2ARGS();
+ CONVERT_R_R(I64, I32, i64, u32, int32);
+ break;
+
+ case JIT_OP_I32TOF32:
+ LOAD_2ARGS();
+ CONVERT_R_R(F32, I32, f32, i32, int32);
+ break;
+
+ case JIT_OP_U32TOF32:
+ LOAD_2ARGS();
+ CONVERT_R_R(F32, I32, f32, u32, uint32);
+ break;
+
+ case JIT_OP_I32TOF64:
+ LOAD_2ARGS();
+ CONVERT_R_R(F64, I32, f64, i32, int32);
+ break;
+
+ case JIT_OP_U32TOF64:
+ LOAD_2ARGS();
+ CONVERT_R_R(F64, I32, f64, u32, uint32);
+ break;
+
+ case JIT_OP_I64TOI8:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I64, i8, i64, int64);
+ break;
+
+ case JIT_OP_I64TOI16:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I64, i16, i64, int64);
+ break;
+
+ case JIT_OP_I64TOI32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, I64, i32, i64, int64);
+ break;
+
+ case JIT_OP_I64TOF32:
+ LOAD_2ARGS();
+ CONVERT_R_R(F32, I64, f32, i64, int64);
+ break;
+
+ case JIT_OP_I64TOF64:
+ LOAD_2ARGS();
+ CONVERT_R_R(F64, I64, f64, i64, int64);
+ break;
+
+ case JIT_OP_F32TOI32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, F32, i32, f32, float32);
+ break;
+
+ case JIT_OP_F32TOI64:
+ LOAD_2ARGS();
+ CONVERT_R_R(I64, F32, i64, f32, float32);
+ break;
+
+ case JIT_OP_F32TOF64:
+ LOAD_2ARGS();
+ CONVERT_R_R(F64, F32, f64, f32, float32);
+ break;
+
+ case JIT_OP_F32TOU32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, F32, u32, f32, float32);
+ break;
+
+ case JIT_OP_F64TOI32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, F64, i32, f64, float64);
+ break;
+
+ case JIT_OP_F64TOI64:
+ LOAD_2ARGS();
+ CONVERT_R_R(I64, F64, i64, f64, float64);
+ break;
+
+ case JIT_OP_F64TOF32:
+ LOAD_2ARGS();
+ CONVERT_R_R(F32, F64, f32, f64, float64);
+ break;
+
+ case JIT_OP_F64TOU32:
+ LOAD_2ARGS();
+ CONVERT_R_R(I32, F64, u32, f64, float64);
+ break;
+
+ case JIT_OP_NEG:
+ LOAD_2ARGS();
+ if (!lower_neg(cc, a, r0, r1))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_ADD:
+ case JIT_OP_SUB:
+ case JIT_OP_MUL:
+ case JIT_OP_DIV_S:
+ case JIT_OP_REM_S:
+ case JIT_OP_DIV_U:
+ case JIT_OP_REM_U:
+ LOAD_3ARGS();
+ if (!lower_alu(cc, a,
+ (ALU_OP)(ADD + (insn->opcode - JIT_OP_ADD)),
+ r0, r1, r2))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_SHL:
+ case JIT_OP_SHRS:
+ case JIT_OP_SHRU:
+ case JIT_OP_ROTL:
+ case JIT_OP_ROTR:
+ LOAD_3ARGS();
+ if (!lower_shift(
+ cc, a,
+ (SHIFT_OP)(SHL + (insn->opcode - JIT_OP_SHL)), r0,
+ r1, r2))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_OR:
+ case JIT_OP_XOR:
+ case JIT_OP_AND:
+ LOAD_3ARGS();
+ if (!lower_bit(cc, a,
+ (BIT_OP)(OR + (insn->opcode - JIT_OP_OR)),
+ r0, r1, r2))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_CLZ:
+ case JIT_OP_CTZ:
+ case JIT_OP_POPCNT:
+ LOAD_2ARGS();
+ if (!lower_bitcount(
+ cc, a,
+ (BITCOUNT_OP)(CLZ + (insn->opcode - JIT_OP_CLZ)),
+ r0, r1))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_CMP:
+ LOAD_3ARGS();
+ if (!lower_cmp(cc, a, r0, r1, r2))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_SELECTEQ:
+ case JIT_OP_SELECTNE:
+ case JIT_OP_SELECTGTS:
+ case JIT_OP_SELECTGES:
+ case JIT_OP_SELECTLTS:
+ case JIT_OP_SELECTLES:
+ case JIT_OP_SELECTGTU:
+ case JIT_OP_SELECTGEU:
+ case JIT_OP_SELECTLTU:
+ case JIT_OP_SELECTLEU:
+ LOAD_4ARGS();
+ if (!lower_select(
+ cc, a,
+ (COND_OP)(EQ + (insn->opcode - JIT_OP_SELECTEQ)),
+ r0, r1, r2, r3))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_LDEXECENV:
+ LOAD_1ARG();
+ CHECK_KIND(r0, JIT_REG_KIND_I32);
+ /* TODO */
+ break;
+
+ case JIT_OP_LDJITINFO:
+ LOAD_1ARG();
+ CHECK_KIND(r0, JIT_REG_KIND_I32);
+ /* TODO */
+ break;
+
+ case JIT_OP_LDI8:
+ LOAD_3ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ LD_R_R_R(I32, 1, true);
+ else
+ LD_R_R_R(I64, 1, true);
+ break;
+
+ case JIT_OP_LDU8:
+ LOAD_3ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ LD_R_R_R(I32, 1, false);
+ else
+ LD_R_R_R(I64, 1, false);
+ break;
+
+ case JIT_OP_LDI16:
+ LOAD_3ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ LD_R_R_R(I32, 2, true);
+ else
+ LD_R_R_R(I64, 2, true);
+ break;
+
+ case JIT_OP_LDU16:
+ LOAD_3ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ LD_R_R_R(I32, 2, false);
+ else
+ LD_R_R_R(I64, 2, false);
+ break;
+
+ case JIT_OP_LDI32:
+ LOAD_3ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ LD_R_R_R(I32, 4, true);
+ else
+ LD_R_R_R(I64, 4, true);
+ break;
+
+ case JIT_OP_LDU32:
+ LOAD_3ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ LD_R_R_R(I32, 4, false);
+ else
+ LD_R_R_R(I64, 4, false);
+ break;
+
+ case JIT_OP_LDI64:
+ case JIT_OP_LDU64:
+ case JIT_OP_LDPTR:
+ LOAD_3ARGS();
+ LD_R_R_R(I64, 8, false);
+ break;
+
+ case JIT_OP_LDF32:
+ LOAD_3ARGS();
+ LD_R_R_R(F32, 4, false);
+ break;
+
+ case JIT_OP_LDF64:
+ LOAD_3ARGS();
+ LD_R_R_R(F64, 8, false);
+ break;
+
+ case JIT_OP_STI8:
+ LOAD_3ARGS_NO_ASSIGN();
+ atomic = insn->flags_u8 & 0x1;
+ ST_R_R_R(I32, int32, 1, atomic);
+ break;
+
+ case JIT_OP_STI16:
+ LOAD_3ARGS_NO_ASSIGN();
+ atomic = insn->flags_u8 & 0x1;
+ ST_R_R_R(I32, int32, 2, atomic);
+ break;
+
+ case JIT_OP_STI32:
+ LOAD_3ARGS_NO_ASSIGN();
+ atomic = insn->flags_u8 & 0x1;
+ ST_R_R_R(I32, int32, 4, atomic);
+ break;
+
+ case JIT_OP_STI64:
+ LOAD_3ARGS_NO_ASSIGN();
+ atomic = insn->flags_u8 & 0x1;
+ ST_R_R_R(I64, int64, 8, atomic);
+ break;
+
+ case JIT_OP_STPTR:
+ LOAD_3ARGS_NO_ASSIGN();
+ ST_R_R_R(I64, int64, 8, false);
+ break;
+
+ case JIT_OP_STF32:
+ LOAD_3ARGS_NO_ASSIGN();
+ ST_R_R_R(F32, float32, 4, false);
+ break;
+
+ case JIT_OP_STF64:
+ LOAD_3ARGS_NO_ASSIGN();
+ ST_R_R_R(F64, float64, 8, false);
+ break;
+
+ case JIT_OP_JMP:
+ LOAD_1ARG();
+ CHECK_KIND(r0, JIT_REG_KIND_L32);
+ if (!(is_last_insn
+ && label_is_neighboring(cc, label_index,
+ jit_reg_no(r0))))
+ JMP_TO_LABEL(jit_reg_no(r0), label_index);
+ break;
+
+ case JIT_OP_BEQ:
+ case JIT_OP_BNE:
+ case JIT_OP_BGTS:
+ case JIT_OP_BGES:
+ case JIT_OP_BLTS:
+ case JIT_OP_BLES:
+ case JIT_OP_BGTU:
+ case JIT_OP_BGEU:
+ case JIT_OP_BLTU:
+ case JIT_OP_BLEU:
+ LOAD_3ARGS();
+ if (!lower_branch(
+ cc, a, jmp_info_list, label_index,
+ (COND_OP)(EQ + (insn->opcode - JIT_OP_BEQ)), r0, r1,
+ r2, is_last_insn))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_LOOKUPSWITCH:
+ {
+ JitOpndLookupSwitch *opnd = jit_insn_opndls(insn);
+ if (!lower_lookupswitch(cc, a, jmp_info_list, label_offsets,
+ label_index, opnd, is_last_insn))
+ GOTO_FAIL;
+ break;
+ }
+
+ case JIT_OP_CALLNATIVE:
+ if (!lower_callnative(cc, a, insn))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_CALLBC:
+ if (!lower_callbc(cc, a, jmp_info_list, label_index, insn))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_RETURNBC:
+ if (!lower_returnbc(cc, a, insn))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_RETURN:
+ if (!lower_return(cc, a, insn))
+ GOTO_FAIL;
+ break;
+
+ case JIT_OP_I32CASTF32:
+ LOAD_2ARGS();
+ CAST_R_R(F32, I32, f32, i32, int32);
+ break;
+
+ case JIT_OP_I64CASTF64:
+ LOAD_2ARGS();
+ CAST_R_R(F64, I64, f64, i64, int64);
+ break;
+
+ case JIT_OP_F32CASTI32:
+ LOAD_2ARGS();
+ CAST_R_R(I32, F32, i32, f32, float);
+ break;
+
+ case JIT_OP_F64CASTI64:
+ LOAD_2ARGS();
+ CAST_R_R(I64, F64, i64, f64, double);
+ break;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case JIT_OP_AT_CMPXCHGU8:
+ LOAD_4ARGS_NO_ASSIGN();
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ CMPXCHG_R_R_R_R_R(I32, int32, 1);
+ else
+ CMPXCHG_R_R_R_R_R(I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_CMPXCHGU16:
+ LOAD_4ARGS_NO_ASSIGN();
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ CMPXCHG_R_R_R_R_R(I32, int32, 2);
+ else
+ CMPXCHG_R_R_R_R_R(I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_CMPXCHGI32:
+ LOAD_4ARGS_NO_ASSIGN();
+ CMPXCHG_R_R_R_R_R(I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_CMPXCHGU32:
+ LOAD_4ARGS_NO_ASSIGN();
+ CMPXCHG_R_R_R_R_R(I64, int32, 4);
+ break;
+
+ case JIT_OP_AT_CMPXCHGI64:
+ LOAD_4ARGS_NO_ASSIGN();
+ CMPXCHG_R_R_R_R_R(I64, int64, 8);
+ break;
+
+ case JIT_OP_AT_ADDU8:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(add, I32, int32, 1);
+ else
+ AT_RMW_R_R_R_R(add, I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_ADDU16:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(add, I32, int32, 2);
+ else
+ AT_RMW_R_R_R_R(add, I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_ADDI32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(add, I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_ADDU32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(add, I64, int64, 4);
+ break;
+
+ case JIT_OP_AT_ADDI64:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(add, I64, int64, 8);
+ break;
+
+ case JIT_OP_AT_SUBU8:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(sub, I32, int32, 1);
+ else
+ AT_RMW_R_R_R_R(sub, I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_SUBU16:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(sub, I32, int32, 2);
+ else
+ AT_RMW_R_R_R_R(sub, I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_SUBI32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(sub, I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_SUBU32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(sub, I64, int64, 4);
+ break;
+
+ case JIT_OP_AT_SUBI64:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(sub, I64, int64, 8);
+ break;
+
+ case JIT_OP_AT_XCHGU8:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(xchg, I32, int32, 1);
+ else
+ AT_RMW_R_R_R_R(xchg, I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_XCHGU16:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(xchg, I32, int32, 2);
+ else
+ AT_RMW_R_R_R_R(xchg, I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_XCHGI32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(xchg, I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_XCHGU32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(xchg, I64, int64, 4);
+ break;
+
+ case JIT_OP_AT_XCHGI64:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(xchg, I64, int64, 8);
+ break;
+
+ case JIT_OP_AT_ANDU8:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(and, I32, int32, 1);
+ else
+ AT_RMW_R_R_R_R(and, I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_ANDU16:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(and, I32, int32, 2);
+ else
+ AT_RMW_R_R_R_R(and, I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_ANDI32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(and, I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_ANDU32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(and, I64, int64, 4);
+ break;
+
+ case JIT_OP_AT_ANDI64:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(and, I64, int64, 8);
+ break;
+
+ case JIT_OP_AT_ORU8:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(or, I32, int32, 1);
+ else
+ AT_RMW_R_R_R_R(or, I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_ORU16:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(or, I32, int32, 2);
+ else
+ AT_RMW_R_R_R_R(or, I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_ORI32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(or, I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_ORU32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(or, I64, int64, 4);
+ break;
+
+ case JIT_OP_AT_ORI64:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(or, I64, int64, 8);
+ break;
+
+ case JIT_OP_AT_XORU8:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(xor, I32, int32, 1);
+ else
+ AT_RMW_R_R_R_R(xor, I64, int64, 1);
+ break;
+
+ case JIT_OP_AT_XORU16:
+ LOAD_4ARGS();
+ bh_assert(jit_reg_kind(r0) == JIT_REG_KIND_I32
+ || jit_reg_kind(r0) == JIT_REG_KIND_I64);
+ if (jit_reg_kind(r0) == JIT_REG_KIND_I32)
+ AT_RMW_R_R_R_R(xor, I32, int32, 2);
+ else
+ AT_RMW_R_R_R_R(xor, I64, int64, 2);
+ break;
+
+ case JIT_OP_AT_XORI32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(xor, I32, int32, 4);
+ break;
+
+ case JIT_OP_AT_XORU32:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(xor, I64, int64, 4);
+ break;
+
+ case JIT_OP_AT_XORI64:
+ LOAD_4ARGS();
+ AT_RMW_R_R_R_R(xor, I64, int64, 8);
+ break;
+
+ case JIT_OP_FENCE:
+ FENCE();
+ break;
+
+#endif
+
+ default:
+ jit_set_last_error_v(cc, "unsupported JIT opcode 0x%2x",
+ insn->opcode);
+ GOTO_FAIL;
+ }
+
+ if (err_handler.err) {
+ jit_set_last_error_v(cc,
+ "failed to generate native code for JIT "
+ "opcode 0x%02x, ErrorCode is %u",
+ insn->opcode, err_handler.err);
+ GOTO_FAIL;
+ }
+
+#if CODEGEN_DUMP != 0
+ dump_native((char *)code.sectionById(0)->buffer().data()
+ + code_offset,
+ code.sectionById(0)->buffer().size() - code_offset);
+ code_offset = code.sectionById(0)->buffer().size();
+#endif
+ }
+ }
+
+ code_buf = (char *)code.sectionById(0)->buffer().data();
+ code_size = code.sectionById(0)->buffer().size();
+ if (!(stream = (char *)jit_code_cache_alloc(code_size))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ goto fail;
+ }
+
+ bh_memcpy_s(stream, code_size, code_buf, code_size);
+ cc->jitted_addr_begin = stream;
+ cc->jitted_addr_end = stream + code_size;
+
+ for (i = 0; i < label_num; i++) {
+ if (i == 0)
+ label_index = 0;
+ else if (i == label_num - 1)
+ label_index = 1;
+ else
+ label_index = i + 1;
+
+ jitted_addr = jit_annl_jitted_addr(
+ cc, jit_reg_new(JIT_REG_KIND_L32, label_index));
+ *jitted_addr = stream + label_offsets[label_index];
+ }
+
+ patch_jmp_info_list(cc, jmp_info_list);
+ return_value = true;
+
+fail:
+
+ jit_free(label_offsets);
+ free_jmp_info_list(jmp_info_list);
+ return return_value;
+}
+
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
+
+#define MAX_REG_INTS 6
+#define MAX_REG_FLOATS 8
+
+void *
+jit_codegen_compile_call_to_llvm_jit(const WASMType *func_type)
+{
+ const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+ x86::Gp reg_lp = x86::r10, reg_res = x86::r12;
+ x86::Gp reg_tmp_i64 = x86::r11, reg_tmp_i32 = x86::r11d;
+ /* the index of integer argument registers */
+ uint8 reg_idx_of_int_args[] = { REG_RDI_IDX, REG_RSI_IDX, REG_RDX_IDX,
+ REG_RCX_IDX, REG_R8_IDX, REG_R9_IDX };
+ uint32 n_ints = 0, n_fps = 0, n_stacks = 0, n_pushed;
+ uint32 int_reg_idx = 0, fp_reg_idx = 0, stack_arg_idx = 0;
+ uint32 off_to_lp = 0, off_to_res = 0, code_size, i;
+ uint32 param_count = func_type->param_count;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_result_count;
+ char *code_buf, *stream;
+ Imm imm;
+
+ JitErrorHandler err_handler;
+ Environment env(Arch::kX64);
+ CodeHolder code;
+ code.init(env);
+ code.setErrorHandler(&err_handler);
+ x86::Assembler a(&code);
+
+ /* Load the llvm jit function pointer */
+ {
+ /* r11 = exec_env->module_inst */
+ x86::Mem m1(regs_i64[hreg_info->exec_env_hreg_index],
+ (uint32)offsetof(WASMExecEnv, module_inst));
+ a.mov(reg_tmp_i64, m1);
+ /* r11 = module_inst->func_ptrs */
+ x86::Mem m2(reg_tmp_i64,
+ (uint32)offsetof(WASMModuleInstance, func_ptrs));
+ a.mov(reg_tmp_i64, m2);
+ /* rax = func_ptrs[func_idx] */
+ x86::Mem m3(reg_tmp_i64, x86::rdx, 3, 0);
+ a.mov(x86::rax, m3);
+ }
+
+ n_ints++; /* exec_env */
+
+ for (i = 0; i < param_count; i++) {
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_I64:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ if (n_ints < MAX_REG_INTS)
+ n_ints++;
+ else
+ n_stacks++;
+ break;
+ case VALUE_TYPE_F32:
+ case VALUE_TYPE_F64:
+ if (n_fps < MAX_REG_FLOATS)
+ n_fps++;
+ else
+ n_stacks++;
+ break;
+ }
+ }
+
+ ext_result_count = result_count > 1 ? result_count - 1 : 0;
+
+ if (ext_result_count > 0) {
+ if (n_ints + ext_result_count <= MAX_REG_INTS) {
+ /* extra result pointers can be stored into int registers */
+ n_ints += ext_result_count;
+ }
+ else {
+ /* part or all extra result pointers must be stored into stack */
+ n_stacks += n_ints + ext_result_count - MAX_REG_INTS;
+ n_ints = MAX_REG_INTS;
+ }
+ }
+
+ n_pushed = n_stacks;
+ if (n_stacks & 1) {
+ /* Align stack on 16 bytes */
+ n_pushed++;
+ }
+ if (n_pushed > 0) {
+ imm.setValue(n_pushed * 8);
+ a.sub(x86::rsp, imm);
+ }
+
+ /* r10 = outs_area->lp */
+ {
+ x86::Mem m(regs_i64[hreg_info->exec_env_hreg_index],
+ (uint32)offsetof(WASMExecEnv, wasm_stack.s.top));
+ a.mov(reg_lp, m);
+ a.add(reg_lp, (uint32)offsetof(WASMInterpFrame, lp));
+ }
+
+ /* rdi = exec_env */
+ a.mov(regs_i64[reg_idx_of_int_args[int_reg_idx++]],
+ regs_i64[hreg_info->exec_env_hreg_index]);
+
+ for (i = 0; i < param_count; i++) {
+ x86::Mem m_src(reg_lp, off_to_lp);
+
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ {
+ if (int_reg_idx < MAX_REG_INTS) {
+ a.mov(regs_i32[reg_idx_of_int_args[int_reg_idx]], m_src);
+ int_reg_idx++;
+ }
+ else {
+ a.mov(reg_tmp_i32, m_src);
+ x86::Mem m_dst(x86::rsp, stack_arg_idx * 8);
+ a.mov(m_dst, reg_tmp_i32);
+ stack_arg_idx++;
+ }
+ off_to_lp += 4;
+ break;
+ }
+ case VALUE_TYPE_I64:
+ {
+ if (int_reg_idx < MAX_REG_INTS) {
+ a.mov(regs_i64[reg_idx_of_int_args[int_reg_idx]], m_src);
+ int_reg_idx++;
+ }
+ else {
+ a.mov(reg_tmp_i64, m_src);
+ x86::Mem m_dst(x86::rsp, stack_arg_idx * 8);
+ a.mov(m_dst, reg_tmp_i64);
+ stack_arg_idx++;
+ }
+ off_to_lp += 8;
+ break;
+ }
+ case VALUE_TYPE_F32:
+ {
+ if (fp_reg_idx < MAX_REG_FLOATS) {
+ a.movss(regs_float[fp_reg_idx], m_src);
+ fp_reg_idx++;
+ }
+ else {
+ a.mov(reg_tmp_i32, m_src);
+ x86::Mem m_dst(x86::rsp, stack_arg_idx * 8);
+ a.mov(m_dst, reg_tmp_i32);
+ stack_arg_idx++;
+ }
+ off_to_lp += 4;
+ break;
+ }
+ case VALUE_TYPE_F64:
+ {
+ if (fp_reg_idx < MAX_REG_FLOATS) {
+ a.movsd(regs_float[fp_reg_idx], m_src);
+ fp_reg_idx++;
+ }
+ else {
+ a.mov(reg_tmp_i64, m_src);
+ x86::Mem m_dst(x86::rsp, stack_arg_idx * 8);
+ a.mov(m_dst, reg_tmp_i64);
+ stack_arg_idx++;
+ }
+ off_to_lp += 8;
+ break;
+ }
+ }
+ }
+
+ if (result_count > 0) {
+ switch (func_type->types[param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ case VALUE_TYPE_F32:
+ off_to_res = 4;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ off_to_res = 8;
+ break;
+ }
+
+ /* r12 = cur_frame->sp */
+ x86::Mem m(x86::rbp, (uint32)offsetof(WASMInterpFrame, sp));
+ a.mov(reg_res, m);
+
+ for (i = 0; i < ext_result_count; i++) {
+ x86::Mem m(reg_res, off_to_res);
+
+ if (int_reg_idx < MAX_REG_INTS) {
+ a.lea(regs_i64[reg_idx_of_int_args[int_reg_idx]], m);
+ int_reg_idx++;
+ }
+ else {
+ a.lea(reg_tmp_i64, m);
+ x86::Mem m_dst(x86::rsp, stack_arg_idx * 8);
+ a.mov(m_dst, reg_tmp_i64);
+ stack_arg_idx++;
+ }
+
+ switch (func_type->types[param_count + 1 + i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ case VALUE_TYPE_F32:
+ off_to_res += 4;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ off_to_res += 8;
+ break;
+ }
+ }
+ }
+
+ bh_assert(int_reg_idx == n_ints);
+ bh_assert(fp_reg_idx == n_fps);
+ bh_assert(stack_arg_idx == n_stacks);
+
+ /* Call the llvm jit function */
+ a.call(x86::rax);
+
+ /* Check if there was exception thrown */
+ {
+ /* r11 = exec_env->module_inst */
+ x86::Mem m1(regs_i64[hreg_info->exec_env_hreg_index],
+ (uint32)offsetof(WASMExecEnv, module_inst));
+ a.mov(reg_tmp_i64, m1);
+ /* module_inst->cur_exception */
+ x86::Mem m2(reg_tmp_i64,
+ (uint32)offsetof(WASMModuleInstance, cur_exception));
+ /* bl = module_inst->cur_exception[0] */
+ a.mov(x86::bl, m2);
+
+ /* cur_exception[0] == 0 ? */
+ Imm imm((uint8)0);
+ a.cmp(x86::bl, imm);
+ /* If yes, jump to `Get function result and return` */
+ imm.setValue(INT32_MAX);
+ a.je(imm);
+
+ char *stream = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+
+ /* If no, set eax to JIT_INTERP_ACTION_THROWN, and
+ jump to code_block_return_to_interp_from_jitted to
+ return to interpreter */
+ imm.setValue(JIT_INTERP_ACTION_THROWN);
+ a.mov(x86::eax, imm);
+ imm.setValue(code_block_return_to_interp_from_jitted);
+ a.mov(x86::rsi, imm);
+ a.jmp(x86::rsi);
+
+ char *stream_new = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+
+ *(int32 *)(stream - 4) = (uint32)(stream_new - stream);
+ }
+
+ /* Get function result and return */
+
+ if (result_count > 0 && func_type->types[param_count] != VALUE_TYPE_F32
+ && func_type->types[param_count] != VALUE_TYPE_F64) {
+ a.mov(x86::rdx, x86::rax);
+ }
+
+ if (off_to_res > 0) {
+ imm.setValue(off_to_res);
+ a.add(reg_res, imm);
+ /* cur_frame->sp = r12 */
+ x86::Mem m(x86::rbp, (uint32)offsetof(WASMInterpFrame, sp));
+ a.mov(m, reg_res);
+ }
+
+ if (n_pushed > 0) {
+ imm.setValue(n_pushed * 8);
+ a.add(x86::rsp, imm);
+ }
+
+ /* Return to the caller */
+ {
+ /* eax = action = JIT_INTERP_ACTION_NORMAL */
+ Imm imm(0);
+ a.mov(x86::eax, imm);
+
+ uint32 jitted_return_addr_offset =
+ jit_frontend_get_jitted_return_addr_offset();
+ x86::Mem m(x86::rbp, jitted_return_addr_offset);
+ a.jmp(m);
+ }
+
+ if (err_handler.err)
+ return NULL;
+
+ code_buf = (char *)code.sectionById(0)->buffer().data();
+ code_size = code.sectionById(0)->buffer().size();
+ stream = (char *)jit_code_cache_alloc(code_size);
+ if (!stream)
+ return NULL;
+
+ bh_memcpy_s(stream, code_size, code_buf, code_size);
+
+#if 0
+ dump_native(stream, code_size);
+#endif
+
+ return stream;
+}
+
+static WASMInterpFrame *
+fast_jit_alloc_frame(WASMExecEnv *exec_env, uint32 param_cell_num,
+ uint32 ret_cell_num)
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ WASMInterpFrame *frame;
+ uint32 size_frame1 = wasm_interp_interp_frame_size(ret_cell_num);
+ uint32 size_frame2 = wasm_interp_interp_frame_size(param_cell_num);
+
+ /**
+ * Check whether we can allocate two frames: the first is an implied
+ * frame to store the function results from jit function to call,
+ * the second is the frame for the jit function
+ */
+ if ((uint8 *)exec_env->wasm_stack.s.top + size_frame1 + size_frame2
+ > exec_env->wasm_stack.s.top_boundary) {
+ wasm_set_exception(module_inst, "wasm operand stack overflow");
+ return NULL;
+ }
+
+ /* Allocate the frame */
+ frame = (WASMInterpFrame *)exec_env->wasm_stack.s.top;
+ exec_env->wasm_stack.s.top += size_frame1;
+
+ frame->function = NULL;
+ frame->ip = NULL;
+ frame->sp = frame->lp;
+ frame->prev_frame = wasm_exec_env_get_cur_frame(exec_env);
+ frame->jitted_return_addr =
+ (uint8 *)code_block_return_to_interp_from_jitted;
+
+ wasm_exec_env_set_cur_frame(exec_env, frame);
+
+ return frame;
+}
+
+void *
+jit_codegen_compile_call_to_fast_jit(const WASMModule *module, uint32 func_idx)
+{
+ uint32 func_idx_non_import = func_idx - module->import_function_count;
+ WASMType *func_type = module->functions[func_idx_non_import]->func_type;
+ /* the index of integer argument registers */
+ uint8 reg_idx_of_int_args[] = { REG_RDI_IDX, REG_RSI_IDX, REG_RDX_IDX,
+ REG_RCX_IDX, REG_R8_IDX, REG_R9_IDX };
+ uint32 int_reg_idx, fp_reg_idx, stack_arg_idx;
+ uint32 switch_info_offset, exec_env_offset, stack_arg_offset;
+ uint32 int_reg_offset, frame_lp_offset;
+ uint32 switch_info_size, code_size, i;
+ uint32 param_count = func_type->param_count;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_result_count = result_count > 1 ? result_count - 1 : 0;
+ uint32 param_cell_num = func_type->param_cell_num;
+ uint32 ret_cell_num =
+ func_type->ret_cell_num > 2 ? func_type->ret_cell_num : 2;
+ char *code_buf, *stream;
+ Imm imm;
+
+ JitErrorHandler err_handler;
+ Environment env(Arch::kX64);
+ CodeHolder code;
+ code.init(env);
+ code.setErrorHandler(&err_handler);
+ x86::Assembler a(&code);
+
+ /**
+ * Push JitInterpSwitchInfo and make stack 16-byte aligned:
+ * the size pushed must be odd multiples of 8, as the stack pointer
+ * %rsp must be aligned to a 16-byte boundary before making a call,
+ * and when a function (including this llvm jit function) gets
+ * control, the %rsp is not 16-byte aligned (call instruction will
+ * push the ret address to stack).
+ */
+ switch_info_size = align_uint((uint32)sizeof(JitInterpSwitchInfo), 16) + 8;
+ imm.setValue((uint64)switch_info_size);
+ a.sub(x86::rsp, imm);
+
+ /* Push all integer argument registers since we will use them as
+ temporarily registers to load/store data */
+ for (i = 0; i < MAX_REG_INTS; i++) {
+ a.push(regs_i64[reg_idx_of_int_args[MAX_REG_INTS - 1 - i]]);
+ }
+
+ /* We don't push float/double register since we don't use them here */
+
+ /**
+ * Layout of the stack now:
+ * stack arguments
+ * ret address of the caller
+ * switch info
+ * int registers: r9, r8, rcx, rdx, rsi
+ * exec_env: rdi
+ */
+
+ /* offset of the first stack argument to the stack pointer,
+ add 8 to skip the ret address of the caller */
+ stack_arg_offset = switch_info_size + 8 * MAX_REG_INTS + 8;
+ /* offset of jit interp switch info to the stack pointer */
+ switch_info_offset = 8 * MAX_REG_INTS;
+ /* offset of the first int register to the stack pointer */
+ int_reg_offset = 8;
+ /* offset of exec_env to the stack pointer */
+ exec_env_offset = 0;
+
+ /* Call fast_jit_alloc_frame to allocate the stack frame to
+ receive the results of the fast jit function to call */
+
+ /* rdi = exec_env, has been already set as exec_env is
+ the first argument of LLVM JIT function */
+ /* rsi = param_cell_num */
+ imm.setValue(param_cell_num);
+ a.mov(x86::rsi, imm);
+ /* rdx = ret_cell_num */
+ imm.setValue(ret_cell_num);
+ a.mov(x86::rdx, imm);
+ /* call fast_jit_alloc_frame */
+ imm.setValue((uint64)(uintptr_t)fast_jit_alloc_frame);
+ a.mov(x86::rax, imm);
+ a.call(x86::rax);
+
+ /* Check the return value, note now rax is the allocated frame */
+ {
+ /* Did fast_jit_alloc_frame return NULL? */
+ Imm imm((uint64)0);
+ a.cmp(x86::rax, imm);
+ /* If no, jump to `Copy arguments to frame lp area` */
+ imm.setValue(INT32_MAX);
+ a.jne(imm);
+
+ char *stream = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+
+ /* If yes, set eax to 0, return to caller */
+
+ /* Pop all integer arument registers */
+ for (i = 0; i < MAX_REG_INTS; i++) {
+ a.pop(regs_i64[reg_idx_of_int_args[i]]);
+ }
+ /* Pop jit interp switch info */
+ imm.setValue((uint64)switch_info_size);
+ a.add(x86::rsp, imm);
+
+ /* Return to the caller, don't use leave as we didn't
+ `push rbp` and `mov rbp, rsp` */
+ a.ret();
+
+ /* Patch the offset of jne instruction */
+ char *stream_new = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+ *(int32 *)(stream - 4) = (int32)(stream_new - stream);
+ }
+
+ int_reg_idx = 1; /* skip exec_env */
+ fp_reg_idx = 0;
+ stack_arg_idx = 0;
+
+ /* Offset of the dest arguments to outs area */
+ frame_lp_offset = wasm_interp_interp_frame_size(ret_cell_num)
+ + (uint32)offsetof(WASMInterpFrame, lp);
+
+ /* Copy arguments to frame lp area */
+ for (i = 0; i < func_type->param_count; i++) {
+ x86::Mem m_dst(x86::rax, frame_lp_offset);
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ if (int_reg_idx < MAX_REG_INTS) {
+ /* Copy i32 argument from int register */
+ x86::Mem m_src(x86::rsp, int_reg_offset);
+ a.mov(x86::esi, m_src);
+ a.mov(m_dst, x86::esi);
+ int_reg_offset += 8;
+ int_reg_idx++;
+ }
+ else {
+ /* Copy i32 argument from stack */
+ x86::Mem m_src(x86::rsp, stack_arg_offset);
+ a.mov(x86::esi, m_src);
+ a.mov(m_dst, x86::esi);
+ stack_arg_offset += 8;
+ stack_arg_idx++;
+ }
+ frame_lp_offset += 4;
+ break;
+ case VALUE_TYPE_I64:
+ if (int_reg_idx < MAX_REG_INTS) {
+ /* Copy i64 argument from int register */
+ x86::Mem m_src(x86::rsp, int_reg_offset);
+ a.mov(x86::rsi, m_src);
+ a.mov(m_dst, x86::rsi);
+ int_reg_offset += 8;
+ int_reg_idx++;
+ }
+ else {
+ /* Copy i64 argument from stack */
+ x86::Mem m_src(x86::rsp, stack_arg_offset);
+ a.mov(x86::rsi, m_src);
+ a.mov(m_dst, x86::rsi);
+ stack_arg_offset += 8;
+ stack_arg_idx++;
+ }
+ frame_lp_offset += 8;
+ break;
+ case VALUE_TYPE_F32:
+ if (fp_reg_idx < MAX_REG_FLOATS) {
+ /* Copy f32 argument from fp register */
+ a.movss(m_dst, regs_float[fp_reg_idx++]);
+ }
+ else {
+ /* Copy f32 argument from stack */
+ x86::Mem m_src(x86::rsp, stack_arg_offset);
+ a.mov(x86::esi, m_src);
+ a.mov(m_dst, x86::esi);
+ stack_arg_offset += 8;
+ stack_arg_idx++;
+ }
+ frame_lp_offset += 4;
+ break;
+ case VALUE_TYPE_F64:
+ if (fp_reg_idx < MAX_REG_FLOATS) {
+ /* Copy f64 argument from fp register */
+ a.movsd(m_dst, regs_float[fp_reg_idx++]);
+ }
+ else {
+ /* Copy f64 argument from stack */
+ x86::Mem m_src(x86::rsp, stack_arg_offset);
+ a.mov(x86::rsi, m_src);
+ a.mov(m_dst, x86::rsi);
+ stack_arg_offset += 8;
+ stack_arg_idx++;
+ }
+ frame_lp_offset += 8;
+ break;
+ default:
+ bh_assert(0);
+ }
+ }
+
+ /* Call the fast jit function */
+ {
+ /* info = rsp + switch_info_offset */
+ a.lea(x86::rsi, x86::ptr(x86::rsp, switch_info_offset));
+ /* info.frame = frame = rax, or return of fast_jit_alloc_frame */
+ x86::Mem m1(x86::rsi, (uint32)offsetof(JitInterpSwitchInfo, frame));
+ a.mov(m1, x86::rax);
+
+ /* Call code_block_switch_to_jitted_from_interp
+ with argument (exec_env, info, func_idx, pc) */
+ /* rdi = exec_env */
+ a.mov(x86::rdi, x86::ptr(x86::rsp, exec_env_offset));
+ /* rsi = info, has been set */
+ /* rdx = func_idx */
+ imm.setValue(func_idx);
+ a.mov(x86::rdx, imm);
+ /* module_inst = exec_env->module_inst */
+ a.mov(x86::rcx,
+ x86::ptr(x86::rdi, (uint32)offsetof(WASMExecEnv, module_inst)));
+ /* fast_jit_func_ptrs = module_inst->fast_jit_func_ptrs */
+ a.mov(x86::rcx,
+ x86::ptr(x86::rcx, (uint32)offsetof(WASMModuleInstance,
+ fast_jit_func_ptrs)));
+ imm.setValue(func_idx_non_import);
+ a.mov(x86::rax, imm);
+ x86::Mem m3(x86::rcx, x86::rax, 3, 0);
+ /* rcx = module_inst->fast_jit_func_ptrs[func_idx_non_import] */
+ a.mov(x86::rcx, m3);
+
+ imm.setValue(
+ (uint64)(uintptr_t)code_block_switch_to_jitted_from_interp);
+ a.mov(x86::rax, imm);
+ a.call(x86::rax);
+ }
+
+ /* No need to check exception thrown here as it will be checked
+ in the caller */
+
+ /* Copy function results */
+ if (result_count > 0) {
+ frame_lp_offset = offsetof(WASMInterpFrame, lp);
+
+ switch (func_type->types[param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ a.mov(x86::eax, x86::edx);
+ frame_lp_offset += 4;
+ break;
+ case VALUE_TYPE_I64:
+ a.mov(x86::rax, x86::rdx);
+ frame_lp_offset += 8;
+ break;
+ case VALUE_TYPE_F32:
+ /* The first result has been put to xmm0 */
+ frame_lp_offset += 4;
+ break;
+ case VALUE_TYPE_F64:
+ /* The first result has been put to xmm0 */
+ frame_lp_offset += 8;
+ break;
+ default:
+ bh_assert(0);
+ }
+
+ /* Copy extra results from exec_env->cur_frame */
+ if (ext_result_count > 0) {
+ /* rdi = exec_env */
+ a.mov(x86::rdi, x86::ptr(x86::rsp, exec_env_offset));
+ /* rsi = exec_env->cur_frame */
+ a.mov(x86::rsi,
+ x86::ptr(x86::rdi, (uint32)offsetof(WASMExecEnv, cur_frame)));
+
+ for (i = 0; i < ext_result_count; i++) {
+ switch (func_type->types[param_count + 1 + i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ case VALUE_TYPE_F32:
+ {
+ /* Copy 32-bit result */
+ a.mov(x86::ecx, x86::ptr(x86::rsi, frame_lp_offset));
+ if (int_reg_idx < MAX_REG_INTS) {
+ x86::Mem m1(x86::rsp,
+ exec_env_offset + int_reg_idx * 8);
+ a.mov(x86::rdx, m1);
+ x86::Mem m2(x86::rdx, 0);
+ a.mov(m2, x86::ecx);
+ int_reg_idx++;
+ }
+ else {
+ x86::Mem m1(x86::rsp, stack_arg_offset);
+ a.mov(x86::rdx, m1);
+ x86::Mem m2(x86::rdx, 0);
+ a.mov(m2, x86::ecx);
+ stack_arg_offset += 8;
+ stack_arg_idx++;
+ }
+ frame_lp_offset += 4;
+ break;
+ }
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ {
+ /* Copy 64-bit result */
+ a.mov(x86::rcx, x86::ptr(x86::rsi, frame_lp_offset));
+ if (int_reg_idx < MAX_REG_INTS) {
+ x86::Mem m1(x86::rsp,
+ exec_env_offset + int_reg_idx * 8);
+ a.mov(x86::rdx, m1);
+ x86::Mem m2(x86::rdx, 0);
+ a.mov(m2, x86::rcx);
+ int_reg_idx++;
+ }
+ else {
+ x86::Mem m1(x86::rsp, stack_arg_offset);
+ a.mov(x86::rdx, m1);
+ x86::Mem m2(x86::rdx, 0);
+ a.mov(m2, x86::rcx);
+ stack_arg_offset += 8;
+ stack_arg_idx++;
+ }
+ frame_lp_offset += 8;
+ break;
+ }
+ default:
+ bh_assert(0);
+ }
+ }
+ }
+ }
+
+ /* Free the frame allocated */
+
+ /* rdi = exec_env */
+ a.mov(x86::rdi, x86::ptr(x86::rsp, exec_env_offset));
+ /* rsi = exec_env->cur_frame */
+ a.mov(x86::rsi,
+ x86::ptr(x86::rdi, (uint32)offsetof(WASMExecEnv, cur_frame)));
+ /* rdx = exec_env->cur_frame->prev_frame */
+ a.mov(x86::rdx,
+ x86::ptr(x86::rsi, (uint32)offsetof(WASMInterpFrame, prev_frame)));
+ /* exec_env->wasm_stack.s.top = cur_frame */
+ {
+ x86::Mem m(x86::rdi, offsetof(WASMExecEnv, wasm_stack.s.top));
+ a.mov(m, x86::rsi);
+ }
+ /* exec_env->cur_frame = prev_frame */
+ {
+ x86::Mem m(x86::rdi, offsetof(WASMExecEnv, cur_frame));
+ a.mov(m, x86::rdx);
+ }
+
+ /* Pop all integer arument registers */
+ for (i = 0; i < MAX_REG_INTS; i++) {
+ a.pop(regs_i64[reg_idx_of_int_args[i]]);
+ }
+ /* Pop jit interp switch info */
+ imm.setValue((uint64)switch_info_size);
+ a.add(x86::rsp, imm);
+
+ /* Return to the caller, don't use leave as we didn't
+ `push rbp` and `mov rbp, rsp` */
+ a.ret();
+
+ if (err_handler.err) {
+ return NULL;
+ }
+
+ code_buf = (char *)code.sectionById(0)->buffer().data();
+ code_size = code.sectionById(0)->buffer().size();
+ stream = (char *)jit_code_cache_alloc(code_size);
+ if (!stream)
+ return NULL;
+
+ bh_memcpy_s(stream, code_size, code_buf, code_size);
+
+#if 0
+ printf("Code of call to fast jit of func %u:\n", func_idx);
+ dump_native(stream, code_size);
+ printf("\n");
+#endif
+
+ return stream;
+}
+
+#endif /* end of WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 */
+
+bool
+jit_codegen_lower(JitCompContext *cc)
+{
+ (void)cc;
+ return true;
+}
+
+void
+jit_codegen_free_native(JitCompContext *cc)
+{
+ (void)cc;
+}
+
+void
+jit_codegen_dump_native(void *begin_addr, void *end_addr)
+{
+#if WASM_ENABLE_FAST_JIT_DUMP != 0
+ os_printf("\n");
+ dump_native((char *)begin_addr, (char *)end_addr - (char *)begin_addr);
+ os_printf("\n");
+#else
+ (void)begin_addr;
+ (void)end_addr;
+#endif
+}
+
+bool
+jit_codegen_init()
+{
+ const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+ JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+ char *code_buf, *stream;
+ uint32 code_size;
+
+ JitErrorHandler err_handler;
+ Environment env(Arch::kX64);
+ CodeHolder code;
+ code.init(env);
+ code.setErrorHandler(&err_handler);
+ x86::Assembler a(&code);
+
+ /* Initialize code_block_switch_to_jitted_from_interp */
+
+ /* push callee-save registers */
+ a.push(x86::rbp);
+ a.push(x86::rbx);
+ a.push(x86::r12);
+ a.push(x86::r13);
+ a.push(x86::r14);
+ a.push(x86::r15);
+ /* push info */
+ a.push(x86::rsi);
+
+ /* Note: the number of register pushed must be odd, as the stack pointer
+ %rsp must be aligned to a 16-byte boundary before making a call, so
+ when a function (including this function) gets control, %rsp is not
+ aligned. We push odd number registers here to make %rsp happy before
+ calling native functions. */
+
+ /* exec_env_reg = exec_env */
+ a.mov(regs_i64[hreg_info->exec_env_hreg_index], x86::rdi);
+ /* fp_reg = info->frame */
+ a.mov(x86::rbp, x86::ptr(x86::rsi, offsetof(JitInterpSwitchInfo, frame)));
+ /* rdx = func_idx, is already set in the func_idx argument of
+ jit_codegen_interp_jitted_glue */
+ /* jmp target, rcx = pc */
+ a.jmp(x86::rcx);
+
+ if (err_handler.err)
+ return false;
+
+ code_buf = (char *)code.sectionById(0)->buffer().data();
+ code_size = code.sectionById(0)->buffer().size();
+ stream = (char *)jit_code_cache_alloc(code_size);
+ if (!stream)
+ return false;
+
+ bh_memcpy_s(stream, code_size, code_buf, code_size);
+ code_block_switch_to_jitted_from_interp = stream;
+
+#if 0
+ dump_native(stream, code_size);
+#endif
+
+ /* Initialize code_block_return_to_interp_from_jitted */
+
+ a.setOffset(0);
+
+ /* pop info */
+ a.pop(x86::rsi);
+ /* info->frame = fp_reg */
+ {
+ x86::Mem m(x86::rsi, offsetof(JitInterpSwitchInfo, frame));
+ a.mov(m, x86::rbp);
+ }
+ /* info->out.ret.ival[0, 1] = rdx */
+ {
+ x86::Mem m(x86::rsi, offsetof(JitInterpSwitchInfo, out.ret.ival));
+ a.mov(m, x86::rdx);
+ }
+ /* info->out.ret.fval[0, 1] = xmm0 */
+ {
+ x86::Mem m(x86::rsi, offsetof(JitInterpSwitchInfo, out.ret.fval));
+ a.movsd(m, x86::xmm0);
+ }
+
+ /* pop callee-save registers */
+ a.pop(x86::r15);
+ a.pop(x86::r14);
+ a.pop(x86::r13);
+ a.pop(x86::r12);
+ a.pop(x86::rbx);
+ a.pop(x86::rbp);
+ a.ret();
+
+ if (err_handler.err)
+ goto fail1;
+
+ code_buf = (char *)code.sectionById(0)->buffer().data();
+ code_size = code.sectionById(0)->buffer().size();
+ stream = (char *)jit_code_cache_alloc(code_size);
+ if (!stream)
+ goto fail1;
+
+ bh_memcpy_s(stream, code_size, code_buf, code_size);
+ code_block_return_to_interp_from_jitted =
+ jit_globals->return_to_interp_from_jitted = stream;
+
+#if 0
+ dump_native(stream, code_size);
+#endif
+
+#if WASM_ENABLE_LAZY_JIT != 0
+ /* Initialize code_block_compile_fast_jit_and_then_call */
+
+ a.setOffset(0);
+
+ /* Use rbx, r12, r13 to save func_dix, module_inst and module,
+ as they are callee-save registers */
+
+ /* Backup func_idx: rbx = rdx = func_idx, note that rdx has
+ been prepared in the caller:
+ callbc or code_block_switch_to_jitted_from_interp */
+ a.mov(x86::rbx, x86::rdx);
+ /* r12 = module_inst = exec_env->module_inst */
+ {
+ x86::Mem m(regs_i64[hreg_info->exec_env_hreg_index],
+ (uint32)offsetof(WASMExecEnv, module_inst));
+ a.mov(x86::r12, m);
+ }
+ /* rdi = r13 = module_inst->module */
+ {
+ x86::Mem m(x86::r12, (uint32)offsetof(WASMModuleInstance, module));
+ a.mov(x86::rdi, m);
+ a.mov(x86::r13, x86::rdi);
+ }
+ /* rsi = rdx = func_idx */
+ a.mov(x86::rsi, x86::rdx);
+ /* Call jit_compiler_compile(module, func_idx) */
+ {
+ Imm imm((uint64)(uintptr_t)jit_compiler_compile);
+ a.mov(x86::rax, imm);
+ a.call(x86::rax);
+ }
+
+ /* Check if failed to compile the jit function */
+ {
+ /* Did jit_compiler_compile return false? */
+ Imm imm((uint8)0);
+ a.cmp(x86::al, imm);
+ /* If no, jump to `Load compiled func ptr and call it` */
+ imm.setValue(INT32_MAX);
+ a.jne(imm);
+
+ char *stream = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+
+ /* If yes, call jit_set_exception_with_id to throw exception,
+ and then set eax to JIT_INTERP_ACTION_THROWN, and jump to
+ code_block_return_to_interp_from_jitted to return */
+
+ /* rdi = module_inst */
+ a.mov(x86::rdi, x86::r12);
+ /* rsi = EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
+ imm.setValue(EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC);
+ a.mov(x86::rsi, imm);
+ /* Call jit_set_exception_with_id */
+ imm.setValue((uint64)(uintptr_t)jit_set_exception_with_id);
+ a.mov(x86::rax, imm);
+ a.call(x86::rax);
+ /* Return to the caller */
+ imm.setValue(JIT_INTERP_ACTION_THROWN);
+ a.mov(x86::eax, imm);
+ imm.setValue(code_block_return_to_interp_from_jitted);
+ a.mov(x86::rsi, imm);
+ a.jmp(x86::rsi);
+
+ /* Patch the offset of jne instruction */
+ char *stream_new = (char *)a.code()->sectionById(0)->buffer().data()
+ + a.code()->sectionById(0)->buffer().size();
+ *(int32 *)(stream - 4) = (int32)(stream_new - stream);
+ }
+
+ /* Load compiled func ptr and call it */
+ {
+ /* rsi = module->import_function_count */
+ x86::Mem m1(x86::r13,
+ (uint32)offsetof(WASMModule, import_function_count));
+ a.movzx(x86::rsi, m1);
+ /* rbx = rbx - module->import_function_count */
+ a.sub(x86::rbx, x86::rsi);
+ /* rax = module->fast_jit_func_ptrs */
+ x86::Mem m2(x86::r13, (uint32)offsetof(WASMModule, fast_jit_func_ptrs));
+ a.mov(x86::rax, m2);
+ /* rax = fast_jit_func_ptrs[rbx] */
+ x86::Mem m3(x86::rax, x86::rbx, 3, 0);
+ a.mov(x86::rax, m3);
+ a.jmp(x86::rax);
+ }
+
+ if (err_handler.err)
+ goto fail2;
+
+ code_buf = (char *)code.sectionById(0)->buffer().data();
+ code_size = code.sectionById(0)->buffer().size();
+ stream = (char *)jit_code_cache_alloc(code_size);
+ if (!stream)
+ goto fail2;
+
+ bh_memcpy_s(stream, code_size, code_buf, code_size);
+ code_block_compile_fast_jit_and_then_call =
+ jit_globals->compile_fast_jit_and_then_call = stream;
+
+#if 0
+ dump_native(stream, code_size);
+#endif
+#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
+
+ return true;
+
+#if WASM_ENABLE_LAZY_JIT != 0
+fail2:
+ jit_code_cache_free(code_block_return_to_interp_from_jitted);
+#endif
+fail1:
+ jit_code_cache_free(code_block_switch_to_jitted_from_interp);
+ return false;
+}
+
+void
+jit_codegen_destroy()
+{
+#if WASM_ENABLE_LAZY_JIT != 0
+ jit_code_cache_free(code_block_compile_fast_jit_and_then_call);
+#endif
+ jit_code_cache_free(code_block_return_to_interp_from_jitted);
+ jit_code_cache_free(code_block_switch_to_jitted_from_interp);
+}
+
+/* clang-format off */
+static const uint8 hreg_info_I32[3][7] = {
+ /* ebp, eax, ebx, ecx, edx, edi, esi */
+ { 1, 0, 0, 0, 0, 0, 1 }, /* fixed, esi is freely used */
+ { 0, 1, 0, 1, 1, 1, 0 }, /* caller_saved_native */
+ { 0, 1, 1, 1, 1, 1, 0 } /* caller_saved_jitted */
+};
+
+static const uint8 hreg_info_I64[3][16] = {
+ /* rbp, rax, rbx, rcx, rdx, rdi, rsi, rsp,
+ r8, r9, r10, r11, r12, r13, r14, r15 */
+ { 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 1 }, /* fixed, rsi is freely used */
+ { 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 1, 1, 1, 0, 0, 0, 0 }, /* caller_saved_native */
+ { 0, 1, 1, 1, 1, 1, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_jitted */
+};
+
+/* System V AMD64 ABI Calling Conversion. [XYZ]MM0-7 */
+static uint8 hreg_info_F32[3][16] = {
+ /* xmm0 ~ xmm15 */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_native */
+ { 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_jitted */
+};
+
+/* System V AMD64 ABI Calling Conversion. [XYZ]MM0-7 */
+static uint8 hreg_info_F64[3][16] = {
+ /* xmm0 ~ xmm15 */
+ { 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 1 },
+ { 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_native */
+ { 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_jitted */
+};
+
+static const JitHardRegInfo hreg_info = {
+ {
+ { 0, NULL, NULL, NULL }, /* VOID */
+
+ { sizeof(hreg_info_I32[0]), /* I32 */
+ hreg_info_I32[0],
+ hreg_info_I32[1],
+ hreg_info_I32[2] },
+
+ { sizeof(hreg_info_I64[0]), /* I64 */
+ hreg_info_I64[0],
+ hreg_info_I64[1],
+ hreg_info_I64[2] },
+
+ { sizeof(hreg_info_F32[0]), /* F32 */
+ hreg_info_F32[0],
+ hreg_info_F32[1],
+ hreg_info_F32[2] },
+
+ { sizeof(hreg_info_F64[0]), /* F64 */
+ hreg_info_F64[0],
+ hreg_info_F64[1],
+ hreg_info_F64[2] },
+
+ { 0, NULL, NULL, NULL }, /* V8 */
+ { 0, NULL, NULL, NULL }, /* V16 */
+ { 0, NULL, NULL, NULL } /* V32 */
+ },
+ /* frame pointer hreg index: rbp */
+ 0,
+ /* exec_env hreg index: r15 */
+ 15,
+ /* cmp hreg index: esi */
+ 6
+};
+/* clang-format on */
+
+const JitHardRegInfo *
+jit_codegen_get_hreg_info()
+{
+ return &hreg_info;
+}
+
+static const char *reg_names_i32[] = {
+ "ebp", "eax", "ebx", "ecx", "edx", "edi", "esi", "esp",
+};
+
+static const char *reg_names_i64[] = {
+ "rbp", "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rsp",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+};
+
+static const char *reg_names_f32[] = { "xmm0", "xmm1", "xmm2", "xmm3",
+ "xmm4", "xmm5", "xmm6", "xmm7",
+ "xmm8", "xmm9", "xmm10", "xmm11",
+ "xmm12", "xmm13", "xmm14", "xmm15" };
+
+static const char *reg_names_f64[] = {
+ "xmm0_f64", "xmm1_f64", "xmm2_f64", "xmm3_f64", "xmm4_f64", "xmm5_f64",
+ "xmm6_f64", "xmm7_f64", "xmm8_f64", "xmm9_f64", "xmm10_f64", "xmm11_f64",
+ "xmm12_f64", "xmm13_f64", "xmm14_f64", "xmm15_f64"
+};
+
+JitReg
+jit_codegen_get_hreg_by_name(const char *name)
+{
+ size_t i;
+
+ if (name[0] == 'e') {
+ for (i = 0; i < sizeof(reg_names_i32) / sizeof(char *); i++)
+ if (!strcmp(reg_names_i32[i], name))
+ return jit_reg_new(JIT_REG_KIND_I32, i);
+ }
+ else if (name[0] == 'r') {
+ for (i = 0; i < sizeof(reg_names_i64) / sizeof(char *); i++)
+ if (!strcmp(reg_names_i64[i], name))
+ return jit_reg_new(JIT_REG_KIND_I64, i);
+ }
+ else if (!strncmp(name, "xmm", 3)) {
+ if (!strstr(name, "_f64")) {
+ for (i = 0; i < sizeof(reg_names_f32) / sizeof(char *); i++)
+ if (!strcmp(reg_names_f32[i], name))
+ return jit_reg_new(JIT_REG_KIND_F32, i);
+ }
+ else {
+ for (i = 0; i < sizeof(reg_names_f64) / sizeof(char *); i++)
+ if (!strcmp(reg_names_f64[i], name))
+ return jit_reg_new(JIT_REG_KIND_F64, i);
+ }
+ }
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.c
new file mode 100644
index 000000000..d41249346
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_compare.h"
+#include "jit_emit_function.h"
+#include "../jit_frontend.h"
+#include "../jit_codegen.h"
+
+static bool
+jit_compile_op_compare_integer(JitCompContext *cc, IntCond cond, bool is64Bit)
+{
+ JitReg lhs, rhs, res, const_zero, const_one;
+
+ if (cond < INT_EQZ || cond > INT_GE_U) {
+ jit_set_last_error(cc, "unsupported comparation operation");
+ goto fail;
+ }
+
+ res = jit_cc_new_reg_I32(cc);
+ const_zero = NEW_CONST(I32, 0);
+ const_one = NEW_CONST(I32, 1);
+
+ if (is64Bit) {
+ if (INT_EQZ == cond) {
+ rhs = NEW_CONST(I64, 0);
+ }
+ else {
+ POP_I64(rhs);
+ }
+ POP_I64(lhs);
+ }
+ else {
+ if (INT_EQZ == cond) {
+ rhs = NEW_CONST(I32, 0);
+ }
+ else {
+ POP_I32(rhs);
+ }
+ POP_I32(lhs);
+ }
+
+ GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
+ switch (cond) {
+ case INT_EQ:
+ case INT_EQZ:
+ {
+ GEN_INSN(SELECTEQ, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_NE:
+ {
+ GEN_INSN(SELECTNE, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_LT_S:
+ {
+ GEN_INSN(SELECTLTS, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_LT_U:
+ {
+ GEN_INSN(SELECTLTU, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_GT_S:
+ {
+ GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_GT_U:
+ {
+ GEN_INSN(SELECTGTU, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_LE_S:
+ {
+ GEN_INSN(SELECTLES, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_LE_U:
+ {
+ GEN_INSN(SELECTLEU, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case INT_GE_S:
+ {
+ GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ default: /* INT_GE_U */
+ {
+ GEN_INSN(SELECTGEU, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ }
+
+ PUSH_I32(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_compare(JitCompContext *cc, IntCond cond)
+{
+ return jit_compile_op_compare_integer(cc, cond, false);
+}
+
+bool
+jit_compile_op_i64_compare(JitCompContext *cc, IntCond cond)
+{
+ return jit_compile_op_compare_integer(cc, cond, true);
+}
+
+static int32
+float_cmp_eq(float f1, float f2)
+{
+ if (isnan(f1) || isnan(f2))
+ return 0;
+
+ return f1 == f2;
+}
+
+static int32
+float_cmp_ne(float f1, float f2)
+{
+ if (isnan(f1) || isnan(f2))
+ return 1;
+
+ return f1 != f2;
+}
+
+static int32
+double_cmp_eq(double d1, double d2)
+{
+ if (isnan(d1) || isnan(d2))
+ return 0;
+
+ return d1 == d2;
+}
+
+static int32
+double_cmp_ne(double d1, double d2)
+{
+ if (isnan(d1) || isnan(d2))
+ return 1;
+
+ return d1 != d2;
+}
+
+static bool
+jit_compile_op_compare_float_point(JitCompContext *cc, FloatCond cond,
+ JitReg lhs, JitReg rhs)
+{
+ JitReg res, args[2], const_zero, const_one;
+ JitRegKind kind;
+ void *func;
+
+ if (cond == FLOAT_EQ || cond == FLOAT_NE) {
+ kind = jit_reg_kind(lhs);
+ if (cond == FLOAT_EQ)
+ func = (kind == JIT_REG_KIND_F32) ? (void *)float_cmp_eq
+ : (void *)double_cmp_eq;
+ else
+ func = (kind == JIT_REG_KIND_F32) ? (void *)float_cmp_ne
+ : (void *)double_cmp_ne;
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = lhs;
+ args[1] = rhs;
+
+ if (!jit_emit_callnative(cc, func, res, args, 2)) {
+ goto fail;
+ }
+ }
+ else {
+ res = jit_cc_new_reg_I32(cc);
+ const_zero = NEW_CONST(I32, 0);
+ const_one = NEW_CONST(I32, 1);
+ switch (cond) {
+ case FLOAT_LT:
+ {
+ GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
+ GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case FLOAT_GT:
+ {
+ GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
+ GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case FLOAT_LE:
+ {
+ GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
+ GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ case FLOAT_GE:
+ {
+ GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
+ GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
+ break;
+ }
+ default:
+ {
+ bh_assert(!"unknown FloatCond");
+ goto fail;
+ }
+ }
+ }
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_compare(JitCompContext *cc, FloatCond cond)
+{
+ JitReg res, const_zero, const_one;
+ JitReg lhs, rhs;
+
+ POP_F32(rhs);
+ POP_F32(lhs);
+
+ if (jit_reg_is_const_val(lhs) && jit_reg_is_const_val(rhs)) {
+ float32 lvalue = jit_cc_get_const_F32(cc, lhs);
+ float32 rvalue = jit_cc_get_const_F32(cc, rhs);
+
+ const_zero = NEW_CONST(I32, 0);
+ const_one = NEW_CONST(I32, 1);
+
+ switch (cond) {
+ case FLOAT_EQ:
+ {
+ res = (lvalue == rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_NE:
+ {
+ res = (lvalue != rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_LT:
+ {
+ res = (lvalue < rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_GT:
+ {
+ res = (lvalue > rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_LE:
+ {
+ res = (lvalue <= rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_GE:
+ {
+ res = (lvalue >= rvalue) ? const_one : const_zero;
+ break;
+ }
+ default:
+ {
+ bh_assert(!"unknown FloatCond");
+ goto fail;
+ }
+ }
+
+ PUSH_I32(res);
+ return true;
+ }
+
+ return jit_compile_op_compare_float_point(cc, cond, lhs, rhs);
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_compare(JitCompContext *cc, FloatCond cond)
+{
+ JitReg res, const_zero, const_one;
+ JitReg lhs, rhs;
+
+ POP_F64(rhs);
+ POP_F64(lhs);
+
+ if (jit_reg_is_const_val(lhs) && jit_reg_is_const_val(rhs)) {
+ float64 lvalue = jit_cc_get_const_F64(cc, lhs);
+ float64 rvalue = jit_cc_get_const_F64(cc, rhs);
+
+ const_zero = NEW_CONST(I32, 0);
+ const_one = NEW_CONST(I32, 1);
+
+ switch (cond) {
+ case FLOAT_EQ:
+ {
+ res = (lvalue == rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_NE:
+ {
+ res = (lvalue != rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_LT:
+ {
+ res = (lvalue < rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_GT:
+ {
+ res = (lvalue > rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_LE:
+ {
+ res = (lvalue <= rvalue) ? const_one : const_zero;
+ break;
+ }
+ case FLOAT_GE:
+ {
+ res = (lvalue >= rvalue) ? const_one : const_zero;
+ break;
+ }
+ default:
+ {
+ bh_assert(!"unknown FloatCond");
+ goto fail;
+ }
+ }
+
+ PUSH_I32(res);
+ return true;
+ }
+
+ return jit_compile_op_compare_float_point(cc, cond, lhs, rhs);
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.h
new file mode 100644
index 000000000..db905b550
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_compare.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_COMPARE_H_
+#define _JIT_EMIT_COMPARE_H_
+
+#include "../jit_compiler.h"
+#include "../jit_frontend.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_i32_compare(JitCompContext *cc, IntCond cond);
+
+bool
+jit_compile_op_i64_compare(JitCompContext *cc, IntCond cond);
+
+bool
+jit_compile_op_f32_compare(JitCompContext *cc, FloatCond cond);
+
+bool
+jit_compile_op_f64_compare(JitCompContext *cc, FloatCond cond);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_COMPARE_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.c
new file mode 100644
index 000000000..1bbc83c2f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_const.h"
+#include "../jit_frontend.h"
+
+bool
+jit_compile_op_i32_const(JitCompContext *cc, int32 i32_const)
+{
+ JitReg value = NEW_CONST(I32, i32_const);
+ PUSH_I32(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_const(JitCompContext *cc, int64 i64_const)
+{
+ JitReg value = NEW_CONST(I64, i64_const);
+ PUSH_I64(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_const(JitCompContext *cc, float32 f32_const)
+{
+ JitReg value = NEW_CONST(F32, f32_const);
+ PUSH_F32(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_const(JitCompContext *cc, float64 f64_const)
+{
+ JitReg value = NEW_CONST(F64, f64_const);
+ PUSH_F64(value);
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.h
new file mode 100644
index 000000000..b75314117
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_const.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_CONST_H_
+#define _JIT_EMIT_CONST_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_i32_const(JitCompContext *cc, int32 i32_const);
+
+bool
+jit_compile_op_i64_const(JitCompContext *cc, int64 i64_const);
+
+bool
+jit_compile_op_f32_const(JitCompContext *cc, float32 f32_const);
+
+bool
+jit_compile_op_f64_const(JitCompContext *cc, float64 f64_const);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_CONST_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.c
new file mode 100644
index 000000000..f7536c73e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.c
@@ -0,0 +1,1318 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_control.h"
+#include "jit_emit_exception.h"
+#include "jit_emit_function.h"
+#include "../jit_frontend.h"
+#include "../interpreter/wasm_loader.h"
+
+#define CREATE_BASIC_BLOCK(new_basic_block) \
+ do { \
+ bh_assert(!new_basic_block); \
+ if (!(new_basic_block = jit_cc_new_basic_block(cc, 0))) { \
+ jit_set_last_error(cc, "create basic block failed"); \
+ goto fail; \
+ } \
+ } while (0)
+
+#define CURR_BASIC_BLOCK() cc->cur_basic_block
+
+#define BUILD_BR(target_block) \
+ do { \
+ if (!GEN_INSN(JMP, jit_basic_block_label(target_block))) { \
+ jit_set_last_error(cc, "generate jmp insn failed"); \
+ goto fail; \
+ } \
+ } while (0)
+
+#define BUILD_COND_BR(value_if, block_then, block_else) \
+ do { \
+ if (!GEN_INSN(CMP, cc->cmp_reg, value_if, NEW_CONST(I32, 0)) \
+ || !GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(block_then), \
+ jit_basic_block_label(block_else))) { \
+ jit_set_last_error(cc, "generate bne insn failed"); \
+ goto fail; \
+ } \
+ } while (0)
+
+#define SET_BUILDER_POS(basic_block) \
+ do { \
+ cc->cur_basic_block = basic_block; \
+ } while (0)
+
+#define SET_BB_BEGIN_BCIP(basic_block, bcip) \
+ do { \
+ *(jit_annl_begin_bcip(cc, jit_basic_block_label(basic_block))) = bcip; \
+ } while (0)
+
+#define SET_BB_END_BCIP(basic_block, bcip) \
+ do { \
+ *(jit_annl_end_bcip(cc, jit_basic_block_label(basic_block))) = bcip; \
+ } while (0)
+
+static JitBlock *
+get_target_block(JitCompContext *cc, uint32 br_depth)
+{
+ uint32 i = br_depth;
+ JitBlock *block = jit_block_stack_top(&cc->block_stack);
+
+ while (i-- > 0 && block) {
+ block = block->prev;
+ }
+
+ if (!block) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return NULL;
+ }
+ return block;
+}
+
+static bool
+load_block_params(JitCompContext *cc, JitBlock *block)
+{
+ JitFrame *jit_frame = cc->jit_frame;
+ uint32 offset, i;
+ JitReg value = 0;
+
+ /* Clear jit frame's locals and stacks */
+ clear_values(jit_frame);
+
+ /* Restore jit frame's sp to block's sp begin */
+ jit_frame->sp = block->frame_sp_begin;
+
+ /* Load params to new block */
+ offset = (uint32)(jit_frame->sp - jit_frame->lp);
+ for (i = 0; i < block->param_count; i++) {
+ switch (block->param_types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ value = gen_load_i32(jit_frame, offset);
+ offset++;
+ break;
+ case VALUE_TYPE_I64:
+ value = gen_load_i64(jit_frame, offset);
+ offset += 2;
+ break;
+ case VALUE_TYPE_F32:
+ value = gen_load_f32(jit_frame, offset);
+ offset++;
+ break;
+ case VALUE_TYPE_F64:
+ value = gen_load_f64(jit_frame, offset);
+ offset += 2;
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ PUSH(value, block->param_types[i]);
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_block_results(JitCompContext *cc, JitBlock *block)
+{
+ JitFrame *jit_frame = cc->jit_frame;
+ uint32 offset, i;
+ JitReg value = 0;
+
+ /* Restore jit frame's sp to block's sp begin */
+ jit_frame->sp = block->frame_sp_begin;
+
+ /* Load results to new block */
+ offset = (uint32)(jit_frame->sp - jit_frame->lp);
+ for (i = 0; i < block->result_count; i++) {
+ switch (block->result_types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ value = gen_load_i32(jit_frame, offset);
+ offset++;
+ break;
+ case VALUE_TYPE_I64:
+ value = gen_load_i64(jit_frame, offset);
+ offset += 2;
+ break;
+ case VALUE_TYPE_F32:
+ value = gen_load_f32(jit_frame, offset);
+ offset++;
+ break;
+ case VALUE_TYPE_F64:
+ value = gen_load_f64(jit_frame, offset);
+ offset += 2;
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ PUSH(value, block->result_types[i]);
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+jit_reg_is_i32_const(JitCompContext *cc, JitReg reg, int32 val)
+{
+ return (jit_reg_kind(reg) == JIT_REG_KIND_I32 && jit_reg_is_const(reg)
+ && jit_cc_get_const_I32(cc, reg) == val)
+ ? true
+ : false;
+}
+
+/**
+ * get the last two insns:
+ * CMP cmp_reg, r0, r1
+ * SELECTcc r2, cmp_reg, 1, 0
+ */
+static void
+get_last_cmp_and_selectcc(JitCompContext *cc, JitReg cond, JitInsn **p_insn_cmp,
+ JitInsn **p_insn_select)
+{
+ JitInsn *insn = jit_basic_block_last_insn(cc->cur_basic_block);
+
+ if (insn && insn->prev && insn->prev->opcode == JIT_OP_CMP
+ && insn->opcode >= JIT_OP_SELECTEQ && insn->opcode <= JIT_OP_SELECTLEU
+ && *jit_insn_opnd(insn, 0) == cond
+ && jit_reg_is_i32_const(cc, *jit_insn_opnd(insn, 2), 1)
+ && jit_reg_is_i32_const(cc, *jit_insn_opnd(insn, 3), 0)) {
+ *p_insn_cmp = insn->prev;
+ *p_insn_select = insn;
+ }
+}
+
+static bool
+push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block,
+ JitBasicBlock *basic_block, JitReg cond,
+ bool merge_cmp_and_if)
+{
+ JitFrame *jit_frame = cc->jit_frame;
+ JitValue *value_list_head = NULL, *value_list_end = NULL, *jit_value;
+ JitInsn *insn;
+ JitReg value;
+ uint32 i, param_index, cell_num;
+
+ if (cc->cur_basic_block == basic_block) {
+ /* Reuse the current basic block and no need to commit values,
+ we just move param values from current block's value stack to
+ the new block's value stack */
+ for (i = 0; i < block->param_count; i++) {
+ jit_value = jit_value_stack_pop(
+ &jit_block_stack_top(&cc->block_stack)->value_stack);
+ if (!value_list_head) {
+ value_list_head = value_list_end = jit_value;
+ jit_value->prev = jit_value->next = NULL;
+ }
+ else {
+ jit_value->prev = NULL;
+ jit_value->next = value_list_head;
+ value_list_head->prev = jit_value;
+ value_list_head = jit_value;
+ }
+ }
+ block->value_stack.value_list_head = value_list_head;
+ block->value_stack.value_list_end = value_list_end;
+
+ /* Save block's begin frame sp */
+ cell_num = wasm_get_cell_num(block->param_types, block->param_count);
+ block->frame_sp_begin = jit_frame->sp - cell_num;
+
+ /* Push the new block to block stack */
+ jit_block_stack_push(&cc->block_stack, block);
+
+ /* Continue to translate current block */
+ }
+ else {
+ JitInsn *insn_select = NULL, *insn_cmp = NULL;
+
+ if (merge_cmp_and_if) {
+ get_last_cmp_and_selectcc(cc, cond, &insn_cmp, &insn_select);
+ }
+
+ /* Commit register values to locals and stacks */
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+
+ /* Pop param values from current block's value stack */
+ for (i = 0; i < block->param_count; i++) {
+ param_index = block->param_count - 1 - i;
+ POP(value, block->param_types[param_index]);
+ }
+
+ /* Clear frame values */
+ clear_values(jit_frame);
+ /* Save block's begin frame sp */
+ block->frame_sp_begin = jit_frame->sp;
+
+ /* Push the new block to block stack */
+ jit_block_stack_push(&cc->block_stack, block);
+
+ if (block->label_type == LABEL_TYPE_LOOP) {
+ BUILD_BR(basic_block);
+ }
+ else {
+ /* IF block with condition br insn */
+ if (insn_select && insn_cmp) {
+ /* Change `CMP + SELECTcc` into `CMP + Bcc` */
+ if (!(insn = GEN_INSN(BEQ, cc->cmp_reg,
+ jit_basic_block_label(basic_block), 0))) {
+ jit_set_last_error(cc, "generate cond br failed");
+ goto fail;
+ }
+ insn->opcode =
+ JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
+ jit_insn_unlink(insn_select);
+ jit_insn_delete(insn_select);
+ }
+ else {
+ if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
+ || !(insn =
+ GEN_INSN(BNE, cc->cmp_reg,
+ jit_basic_block_label(basic_block), 0))) {
+ jit_set_last_error(cc, "generate cond br failed");
+ goto fail;
+ }
+ }
+
+ /* Don't create else basic block or end basic block now, just
+ save its incoming BNE insn, and patch the insn's else label
+ when the basic block is lazily created */
+ if (block->wasm_code_else) {
+ block->incoming_insn_for_else_bb = insn;
+ }
+ else {
+ if (!jit_block_add_incoming_insn(block, insn, 2)) {
+ jit_set_last_error(cc, "add incoming insn failed");
+ goto fail;
+ }
+ }
+ }
+
+ /* Start to translate the block */
+ SET_BUILDER_POS(basic_block);
+
+ /* Push the block parameters */
+ if (!load_block_params(cc, block)) {
+ goto fail;
+ }
+ }
+ return true;
+fail:
+ return false;
+}
+
+static void
+copy_block_arities(JitCompContext *cc, JitReg dst_frame_sp, uint8 *dst_types,
+ uint32 dst_type_count, JitReg *p_first_res_reg)
+{
+ JitFrame *jit_frame;
+ uint32 offset_src, offset_dst, i;
+ JitReg value;
+
+ jit_frame = cc->jit_frame;
+ offset_src = (uint32)(jit_frame->sp - jit_frame->lp)
+ - wasm_get_cell_num(dst_types, dst_type_count);
+ offset_dst = 0;
+
+ /* pop values from stack and store to dest frame */
+ for (i = 0; i < dst_type_count; i++) {
+ switch (dst_types[i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ value = gen_load_i32(jit_frame, offset_src);
+ if (i == 0 && p_first_res_reg)
+ *p_first_res_reg = value;
+ else
+ GEN_INSN(STI32, value, dst_frame_sp,
+ NEW_CONST(I32, offset_dst * 4));
+ offset_src++;
+ offset_dst++;
+ break;
+ case VALUE_TYPE_I64:
+ value = gen_load_i64(jit_frame, offset_src);
+ if (i == 0 && p_first_res_reg)
+ *p_first_res_reg = value;
+ else
+ GEN_INSN(STI64, value, dst_frame_sp,
+ NEW_CONST(I32, offset_dst * 4));
+ offset_src += 2;
+ offset_dst += 2;
+ break;
+ case VALUE_TYPE_F32:
+ value = gen_load_f32(jit_frame, offset_src);
+ if (i == 0 && p_first_res_reg)
+ *p_first_res_reg = value;
+ else
+ GEN_INSN(STF32, value, dst_frame_sp,
+ NEW_CONST(I32, offset_dst * 4));
+ offset_src++;
+ offset_dst++;
+ break;
+ case VALUE_TYPE_F64:
+ value = gen_load_f64(jit_frame, offset_src);
+ if (i == 0 && p_first_res_reg)
+ *p_first_res_reg = value;
+ else
+ GEN_INSN(STF64, value, dst_frame_sp,
+ NEW_CONST(I32, offset_dst * 4));
+ offset_src += 2;
+ offset_dst += 2;
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+}
+
+static bool
+handle_func_return(JitCompContext *cc, JitBlock *block)
+{
+ JitReg prev_frame, prev_frame_sp;
+ JitReg ret_reg = 0;
+#if WASM_ENABLE_PERF_PROFILING != 0
+ JitReg func_inst = jit_cc_new_reg_ptr(cc);
+ JitReg time_start = jit_cc_new_reg_I64(cc);
+ JitReg time_end = jit_cc_new_reg_I64(cc);
+ JitReg cur_exec_time = jit_cc_new_reg_I64(cc);
+ JitReg total_exec_time = jit_cc_new_reg_I64(cc);
+ JitReg total_exec_cnt = jit_cc_new_reg_I32(cc);
+#endif
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ /* time_end = os_time_get_boot_microsecond() */
+ if (!jit_emit_callnative(cc, os_time_get_boot_microsecond, time_end, NULL,
+ 0)) {
+ return false;
+ }
+ /* time_start = cur_frame->time_started */
+ GEN_INSN(LDI64, time_start, cc->fp_reg,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, time_started)));
+ /* cur_exec_time = time_end - time_start */
+ GEN_INSN(SUB, cur_exec_time, time_end, time_start);
+ /* func_inst = cur_frame->function */
+ GEN_INSN(LDPTR, func_inst, cc->fp_reg,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, function)));
+ /* total_exec_time = func_inst->total_exec_time */
+ GEN_INSN(LDI64, total_exec_time, func_inst,
+ NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_time)));
+ /* total_exec_time += cur_exec_time */
+ GEN_INSN(ADD, total_exec_time, total_exec_time, cur_exec_time);
+ /* func_inst->total_exec_time = total_exec_time */
+ GEN_INSN(STI64, total_exec_time, func_inst,
+ NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_time)));
+ /* totoal_exec_cnt = func_inst->total_exec_cnt */
+ GEN_INSN(LDI32, total_exec_cnt, func_inst,
+ NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_cnt)));
+ /* total_exec_cnt++ */
+ GEN_INSN(ADD, total_exec_cnt, total_exec_cnt, NEW_CONST(I32, 1));
+ /* func_inst->total_exec_cnt = total_exec_cnt */
+ GEN_INSN(STI32, total_exec_cnt, func_inst,
+ NEW_CONST(I32, offsetof(WASMFunctionInstance, total_exec_cnt)));
+#endif
+
+ prev_frame = jit_cc_new_reg_ptr(cc);
+ prev_frame_sp = jit_cc_new_reg_ptr(cc);
+
+ /* prev_frame = cur_frame->prev_frame */
+ GEN_INSN(LDPTR, prev_frame, cc->fp_reg,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, prev_frame)));
+ GEN_INSN(LDPTR, prev_frame_sp, prev_frame,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
+
+ if (block->result_count) {
+ uint32 cell_num =
+ wasm_get_cell_num(block->result_types, block->result_count);
+
+ copy_block_arities(cc, prev_frame_sp, block->result_types,
+ block->result_count, &ret_reg);
+ /* prev_frame->sp += cell_num */
+ GEN_INSN(ADD, prev_frame_sp, prev_frame_sp,
+ NEW_CONST(PTR, cell_num * 4));
+ GEN_INSN(STPTR, prev_frame_sp, prev_frame,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
+ }
+
+ /* Free stack space of the current frame:
+ exec_env->wasm_stack.s.top = cur_frame */
+ GEN_INSN(STPTR, cc->fp_reg, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
+ /* Set the prev_frame as the current frame:
+ exec_env->cur_frame = prev_frame */
+ GEN_INSN(STPTR, prev_frame, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, cur_frame)));
+ /* fp_reg = prev_frame */
+ GEN_INSN(MOV, cc->fp_reg, prev_frame);
+ /* return 0 */
+ GEN_INSN(RETURNBC, NEW_CONST(I32, JIT_INTERP_ACTION_NORMAL), ret_reg, 0);
+
+ return true;
+}
+
+/**
+ * is_block_polymorphic: whether current block's stack is in polymorphic state,
+ * if the opcode is one of unreachable/br/br_table/return, stack is marked
+ * to polymorphic state until the block's 'end' opcode is processed
+ */
+static bool
+handle_op_end(JitCompContext *cc, uint8 **p_frame_ip, bool is_block_polymorphic)
+{
+ JitFrame *jit_frame = cc->jit_frame;
+ JitBlock *block, *block_prev;
+ JitIncomingInsn *incoming_insn;
+ JitInsn *insn;
+
+ /* Check block stack */
+ if (!(block = jit_block_stack_top(&cc->block_stack))) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return false;
+ }
+
+ if (!block->incoming_insns_for_end_bb) {
+ /* No other basic blocks jumping to this end, no need to
+ create the end basic block, just continue to translate
+ the following opcodes */
+ if (block->label_type == LABEL_TYPE_FUNCTION) {
+ if (!handle_func_return(cc, block)) {
+ return false;
+ }
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ clear_values(jit_frame);
+ }
+ else if (block->result_count > 0) {
+ JitValue *value_list_head = NULL, *value_list_end = NULL;
+ JitValue *jit_value;
+ uint32 i;
+
+ /* No need to change cc->jit_frame, just move result values
+ from current block's value stack to previous block's
+ value stack */
+ block_prev = block->prev;
+
+ for (i = 0; i < block->result_count; i++) {
+ jit_value = jit_value_stack_pop(&block->value_stack);
+ bh_assert(jit_value);
+ if (!value_list_head) {
+ value_list_head = value_list_end = jit_value;
+ jit_value->prev = jit_value->next = NULL;
+ }
+ else {
+ jit_value->prev = NULL;
+ jit_value->next = value_list_head;
+ value_list_head->prev = jit_value;
+ value_list_head = jit_value;
+ }
+ }
+
+ if (!block_prev->value_stack.value_list_head) {
+ block_prev->value_stack.value_list_head = value_list_head;
+ block_prev->value_stack.value_list_end = value_list_end;
+ }
+ else {
+ /* Link to the end of previous block's value stack */
+ block_prev->value_stack.value_list_end->next = value_list_head;
+ value_list_head->prev = block_prev->value_stack.value_list_end;
+ block_prev->value_stack.value_list_end = value_list_end;
+ }
+ }
+
+ /* Pop block and destroy the block */
+ block = jit_block_stack_pop(&cc->block_stack);
+ jit_block_destroy(block);
+ return true;
+ }
+ else {
+ /* Commit register values to locals and stacks */
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ /* Clear frame values */
+ clear_values(jit_frame);
+
+ /* Create the end basic block */
+ CREATE_BASIC_BLOCK(block->basic_block_end);
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ SET_BB_BEGIN_BCIP(block->basic_block_end, *p_frame_ip);
+ /* No need to create 'JMP' insn if block is in stack polymorphic
+ state, as previous br/br_table opcode has created 'JMP' insn
+ to this end basic block */
+ if (!is_block_polymorphic) {
+ /* Jump to the end basic block */
+ BUILD_BR(block->basic_block_end);
+ }
+
+ /* Patch the INSNs which jump to this basic block */
+ incoming_insn = block->incoming_insns_for_end_bb;
+ while (incoming_insn) {
+ insn = incoming_insn->insn;
+
+ bh_assert(
+ insn->opcode == JIT_OP_JMP
+ || (insn->opcode >= JIT_OP_BEQ && insn->opcode <= JIT_OP_BLEU)
+ || insn->opcode == JIT_OP_LOOKUPSWITCH);
+
+ if (insn->opcode == JIT_OP_JMP
+ || (insn->opcode >= JIT_OP_BEQ
+ && insn->opcode <= JIT_OP_BLEU)) {
+ *(jit_insn_opnd(insn, incoming_insn->opnd_idx)) =
+ jit_basic_block_label(block->basic_block_end);
+ }
+ else {
+ /* Patch LOOKUPSWITCH INSN */
+ JitOpndLookupSwitch *opnd = jit_insn_opndls(insn);
+ if (incoming_insn->opnd_idx < opnd->match_pairs_num) {
+ opnd->match_pairs[incoming_insn->opnd_idx].target =
+ jit_basic_block_label(block->basic_block_end);
+ }
+ else {
+ opnd->default_target =
+ jit_basic_block_label(block->basic_block_end);
+ }
+ }
+
+ incoming_insn = incoming_insn->next;
+ }
+
+ SET_BUILDER_POS(block->basic_block_end);
+
+ /* Pop block and load block results */
+ block = jit_block_stack_pop(&cc->block_stack);
+
+ if (block->label_type == LABEL_TYPE_FUNCTION) {
+ if (!handle_func_return(cc, block)) {
+ jit_block_destroy(block);
+ goto fail;
+ }
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ clear_values(jit_frame);
+ }
+ else {
+ if (!load_block_results(cc, block)) {
+ jit_block_destroy(block);
+ goto fail;
+ }
+ }
+
+ jit_block_destroy(block);
+ return true;
+ }
+ return true;
+fail:
+ return false;
+}
+
+/**
+ * is_block_polymorphic: whether current block's stack is in polymorphic state,
+ * if the opcode is one of unreachable/br/br_table/return, stack is marked
+ * to polymorphic state until the block's 'end' opcode is processed
+ */
+static bool
+handle_op_else(JitCompContext *cc, uint8 **p_frame_ip,
+ bool is_block_polymorphic)
+{
+ JitBlock *block = jit_block_stack_top(&cc->block_stack);
+ JitFrame *jit_frame = cc->jit_frame;
+ JitInsn *insn;
+
+ /* Check block */
+ if (!block) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return false;
+ }
+ if (block->label_type != LABEL_TYPE_IF) {
+ jit_set_last_error(cc, "Invalid WASM block type");
+ return false;
+ }
+
+ if (!block->incoming_insn_for_else_bb) {
+ /* The if branch is handled like OP_BLOCK (cond is const and != 0),
+ just skip the else branch and handle OP_END */
+ *p_frame_ip = block->wasm_code_end + 1;
+ return handle_op_end(cc, p_frame_ip, false);
+ }
+ else {
+ /* Has else branch and need to translate else branch */
+
+ /* Commit register values to locals and stacks */
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ /* Clear frame values */
+ clear_values(jit_frame);
+
+ /* No need to create 'JMP' insn if block is in stack polymorphic
+ state, as previous br/br_table opcode has created 'JMP' insn
+ to this end basic block */
+ if (!is_block_polymorphic) {
+ /* Jump to end basic block */
+ if (!(insn = GEN_INSN(JMP, 0))) {
+ jit_set_last_error(cc, "generate jmp insn failed");
+ return false;
+ }
+ if (!jit_block_add_incoming_insn(block, insn, 0)) {
+ jit_set_last_error(cc, "add incoming insn failed");
+ return false;
+ }
+ }
+
+ /* Clear value stack, restore param values and
+ start to translate the else branch. */
+ jit_value_stack_destroy(&block->value_stack);
+
+ /* create else basic block */
+ CREATE_BASIC_BLOCK(block->basic_block_else);
+ SET_BB_END_BCIP(block->basic_block_entry, *p_frame_ip - 1);
+ SET_BB_BEGIN_BCIP(block->basic_block_else, *p_frame_ip);
+
+ /* Patch the insn which conditionly jumps to the else basic block */
+ insn = block->incoming_insn_for_else_bb;
+ *(jit_insn_opnd(insn, 2)) =
+ jit_basic_block_label(block->basic_block_else);
+
+ SET_BUILDER_POS(block->basic_block_else);
+
+ /* Reload block parameters */
+ if (!load_block_params(cc, block)) {
+ return false;
+ }
+
+ return true;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+handle_next_reachable_block(JitCompContext *cc, uint8 **p_frame_ip)
+{
+ JitBlock *block = jit_block_stack_top(&cc->block_stack);
+
+ bh_assert(block);
+
+ do {
+ if (block->label_type == LABEL_TYPE_IF
+ && block->incoming_insn_for_else_bb
+ && *p_frame_ip <= block->wasm_code_else) {
+ /* Else branch hasn't been translated,
+ start to translate the else branch */
+ *p_frame_ip = block->wasm_code_else + 1;
+ /* Restore jit frame's sp to block's sp begin */
+ cc->jit_frame->sp = block->frame_sp_begin;
+ return handle_op_else(cc, p_frame_ip, true);
+ }
+ else if (block->incoming_insns_for_end_bb) {
+ *p_frame_ip = block->wasm_code_end + 1;
+ /* Restore jit frame's sp to block's sp end */
+ cc->jit_frame->sp =
+ block->frame_sp_begin
+ + wasm_get_cell_num(block->result_types, block->result_count);
+ return handle_op_end(cc, p_frame_ip, true);
+ }
+ else {
+ *p_frame_ip = block->wasm_code_end + 1;
+ jit_block_stack_pop(&cc->block_stack);
+ jit_block_destroy(block);
+ block = jit_block_stack_top(&cc->block_stack);
+ }
+ } while (block != NULL);
+
+ return true;
+}
+
+bool
+jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
+ uint8 *frame_ip_end, uint32 label_type, uint32 param_count,
+ uint8 *param_types, uint32 result_count,
+ uint8 *result_types, bool merge_cmp_and_if)
+{
+ BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
+ JitBlock *block;
+ JitReg value;
+ uint8 *else_addr, *end_addr;
+
+ /* Check block stack */
+ if (!jit_block_stack_top(&cc->block_stack)) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return false;
+ }
+
+ memset(block_addr_cache, 0, sizeof(block_addr_cache));
+
+ /* Get block info */
+ if (!(wasm_loader_find_block_addr(
+ NULL, (BlockAddr *)block_addr_cache, *p_frame_ip, frame_ip_end,
+ (uint8)label_type, &else_addr, &end_addr))) {
+ jit_set_last_error(cc, "find block end addr failed");
+ return false;
+ }
+
+ /* Allocate memory */
+ if (!(block = jit_calloc(sizeof(JitBlock)))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ return false;
+ }
+
+ if (param_count && !(block->param_types = jit_calloc(param_count))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ goto fail;
+ }
+ if (result_count && !(block->result_types = jit_calloc(result_count))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ goto fail;
+ }
+
+ /* Initialize block data */
+ block->label_type = label_type;
+ block->param_count = param_count;
+ if (param_count) {
+ bh_memcpy_s(block->param_types, param_count, param_types, param_count);
+ }
+ block->result_count = result_count;
+ if (result_count) {
+ bh_memcpy_s(block->result_types, result_count, result_types,
+ result_count);
+ }
+ block->wasm_code_else = else_addr;
+ block->wasm_code_end = end_addr;
+
+ if (label_type == LABEL_TYPE_BLOCK) {
+ /* Push the new jit block to block stack and continue to
+ translate current basic block */
+ if (!push_jit_block_to_stack_and_pass_params(
+ cc, block, cc->cur_basic_block, 0, false))
+ goto fail;
+ }
+ else if (label_type == LABEL_TYPE_LOOP) {
+ CREATE_BASIC_BLOCK(block->basic_block_entry);
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ SET_BB_BEGIN_BCIP(block->basic_block_entry, *p_frame_ip);
+ /* Push the new jit block to block stack and continue to
+ translate the new basic block */
+ if (!push_jit_block_to_stack_and_pass_params(
+ cc, block, block->basic_block_entry, 0, false))
+ goto fail;
+ }
+ else if (label_type == LABEL_TYPE_IF) {
+ POP_I32(value);
+
+ if (!jit_reg_is_const_val(value)) {
+ /* Compare value is not constant, create condition br IR */
+
+ /* Create entry block */
+ CREATE_BASIC_BLOCK(block->basic_block_entry);
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ SET_BB_BEGIN_BCIP(block->basic_block_entry, *p_frame_ip);
+
+ if (!push_jit_block_to_stack_and_pass_params(
+ cc, block, block->basic_block_entry, value,
+ merge_cmp_and_if))
+ goto fail;
+ }
+ else {
+ if (jit_cc_get_const_I32(cc, value) != 0) {
+ /* Compare value is not 0, condition is true, else branch of
+ BASIC_BLOCK if cannot be reached, we treat it same as
+ LABEL_TYPE_BLOCK and start to translate if branch */
+ if (!push_jit_block_to_stack_and_pass_params(
+ cc, block, cc->cur_basic_block, 0, false))
+ goto fail;
+ }
+ else {
+ if (else_addr) {
+ /* Compare value is not 0, condition is false, if branch of
+ BASIC_BLOCK if cannot be reached, we treat it same as
+ LABEL_TYPE_BLOCK and start to translate else branch */
+ if (!push_jit_block_to_stack_and_pass_params(
+ cc, block, cc->cur_basic_block, 0, false))
+ goto fail;
+ *p_frame_ip = else_addr + 1;
+ }
+ else {
+ /* The whole if block cannot be reached, skip it */
+ jit_block_destroy(block);
+ *p_frame_ip = end_addr + 1;
+ }
+ }
+ }
+ }
+ else {
+ jit_set_last_error(cc, "Invalid block type");
+ goto fail;
+ }
+
+ return true;
+fail:
+ /* Only destroy the block if it hasn't been pushed into
+ the block stack, or if will be destroyed again when
+ destroying the block stack */
+ if (jit_block_stack_top(&cc->block_stack) != block)
+ jit_block_destroy(block);
+ return false;
+}
+
+bool
+jit_compile_op_else(JitCompContext *cc, uint8 **p_frame_ip)
+{
+ return handle_op_else(cc, p_frame_ip, false);
+}
+
+bool
+jit_compile_op_end(JitCompContext *cc, uint8 **p_frame_ip)
+{
+ return handle_op_end(cc, p_frame_ip, false);
+}
+
+/* Check whether need to copy arities when jumping from current block
+ to the dest block */
+static bool
+check_copy_arities(const JitBlock *block_dst, JitFrame *jit_frame)
+{
+ JitValueSlot *frame_sp_src = NULL;
+
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
+ frame_sp_src =
+ jit_frame->sp
+ - wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
+ /* There are parameters to copy and the src/dst addr are different */
+ return (block_dst->param_count > 0
+ && block_dst->frame_sp_begin != frame_sp_src)
+ ? true
+ : false;
+ }
+ else {
+ frame_sp_src = jit_frame->sp
+ - wasm_get_cell_num(block_dst->result_types,
+ block_dst->result_count);
+ /* There are results to copy and the src/dst addr are different */
+ return (block_dst->result_count > 0
+ && block_dst->frame_sp_begin != frame_sp_src)
+ ? true
+ : false;
+ }
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+jit_check_suspend_flags(JitCompContext *cc)
+{
+ JitReg exec_env, suspend_flags, terminate_flag, offset;
+ JitBasicBlock *terminate_block, *cur_basic_block;
+ JitFrame *jit_frame = cc->jit_frame;
+
+ cur_basic_block = cc->cur_basic_block;
+ terminate_block = jit_cc_new_basic_block(cc, 0);
+ if (!terminate_block) {
+ return false;
+ }
+
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ exec_env = cc->exec_env_reg;
+ suspend_flags = jit_cc_new_reg_I32(cc);
+ terminate_flag = jit_cc_new_reg_I32(cc);
+
+ offset = jit_cc_new_const_I32(cc, offsetof(WASMExecEnv, suspend_flags));
+ GEN_INSN(LDI32, suspend_flags, exec_env, offset);
+ GEN_INSN(AND, terminate_flag, suspend_flags, NEW_CONST(I32, 1));
+
+ GEN_INSN(CMP, cc->cmp_reg, terminate_flag, NEW_CONST(I32, 0));
+ GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(terminate_block), 0);
+
+ cc->cur_basic_block = terminate_block;
+ GEN_INSN(RETURN, NEW_CONST(I32, 0));
+
+ cc->cur_basic_block = cur_basic_block;
+
+ return true;
+}
+
+#endif
+
+static bool
+handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
+{
+ JitFrame *jit_frame;
+ JitBlock *block_dst, *block;
+ JitReg frame_sp_dst;
+ JitInsn *insn;
+ bool copy_arities;
+ uint32 offset;
+
+ /* Check block stack */
+ if (!(block = jit_block_stack_top(&cc->block_stack))) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return false;
+ }
+
+ if (!(block_dst = get_target_block(cc, br_depth))) {
+ return false;
+ }
+
+ jit_frame = cc->jit_frame;
+
+ /* Only opy parameters or results when their count > 0 and
+ the src/dst addr are different */
+ copy_arities = check_copy_arities(block_dst, jit_frame);
+
+ if (copy_arities) {
+ frame_sp_dst = jit_cc_new_reg_ptr(cc);
+ offset = offsetof(WASMInterpFrame, lp)
+ + (block_dst->frame_sp_begin - jit_frame->lp) * 4;
+ GEN_INSN(ADD, frame_sp_dst, cc->fp_reg, NEW_CONST(PTR, offset));
+
+ /* No need to commit results as they will be copied to dest block */
+ gen_commit_values(jit_frame, jit_frame->lp, block->frame_sp_begin);
+ }
+ else {
+ /* Commit all including results as they won't be copied */
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ }
+
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
+ if (copy_arities) {
+ /* Dest block is Loop block, copy loop parameters */
+ copy_block_arities(cc, frame_sp_dst, block_dst->param_types,
+ block_dst->param_count, NULL);
+ }
+
+ clear_values(jit_frame);
+
+ /* Jump to the begin basic block */
+ BUILD_BR(block_dst->basic_block_entry);
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ }
+ else {
+ if (copy_arities) {
+ /* Dest block is Block/If/Function block, copy block results */
+ copy_block_arities(cc, frame_sp_dst, block_dst->result_types,
+ block_dst->result_count, NULL);
+ }
+
+ clear_values(jit_frame);
+
+ /* Jump to the end basic block */
+ if (!(insn = GEN_INSN(JMP, 0))) {
+ jit_set_last_error(cc, "generate jmp insn failed");
+ goto fail;
+ }
+ if (!jit_block_add_incoming_insn(block_dst, insn, 0)) {
+ jit_set_last_error(cc, "add incoming insn failed");
+ goto fail;
+ }
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
+{
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ return false;
+#endif
+
+ return handle_op_br(cc, br_depth, p_frame_ip)
+ && handle_next_reachable_block(cc, p_frame_ip);
+}
+
+static JitFrame *
+jit_frame_clone(const JitFrame *jit_frame)
+{
+ JitFrame *jit_frame_cloned;
+ uint32 max_locals = jit_frame->max_locals;
+ uint32 max_stacks = jit_frame->max_stacks;
+ uint32 total_size;
+
+ total_size = (uint32)(offsetof(JitFrame, lp)
+ + sizeof(*jit_frame->lp) * (max_locals + max_stacks));
+
+ jit_frame_cloned = jit_calloc(total_size);
+ if (jit_frame_cloned) {
+ bh_memcpy_s(jit_frame_cloned, total_size, jit_frame, total_size);
+ jit_frame_cloned->sp =
+ jit_frame_cloned->lp + (jit_frame->sp - jit_frame->lp);
+ }
+
+ return jit_frame_cloned;
+}
+
+static void
+jit_frame_copy(JitFrame *jit_frame_dst, const JitFrame *jit_frame_src)
+{
+ uint32 max_locals = jit_frame_src->max_locals;
+ uint32 max_stacks = jit_frame_src->max_stacks;
+ uint32 total_size;
+
+ total_size =
+ (uint32)(offsetof(JitFrame, lp)
+ + sizeof(*jit_frame_src->lp) * (max_locals + max_stacks));
+ bh_memcpy_s(jit_frame_dst, total_size, jit_frame_src, total_size);
+ jit_frame_dst->sp =
+ jit_frame_dst->lp + (jit_frame_src->sp - jit_frame_src->lp);
+}
+
+bool
+jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth,
+ bool merge_cmp_and_br_if, uint8 **p_frame_ip)
+{
+ JitFrame *jit_frame, *jit_frame_cloned;
+ JitBlock *block_dst;
+ JitReg cond;
+ JitBasicBlock *cur_basic_block, *if_basic_block = NULL;
+ JitInsn *insn, *insn_select = NULL, *insn_cmp = NULL;
+ bool copy_arities;
+
+ if (!(block_dst = get_target_block(cc, br_depth))) {
+ return false;
+ }
+
+ /* append IF to current basic block */
+ POP_I32(cond);
+
+ if (merge_cmp_and_br_if) {
+ get_last_cmp_and_selectcc(cc, cond, &insn_cmp, &insn_select);
+ }
+
+ jit_frame = cc->jit_frame;
+ cur_basic_block = cc->cur_basic_block;
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+
+ if (!(insn_select && insn_cmp)) {
+ if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))) {
+ jit_set_last_error(cc, "generate cmp insn failed");
+ goto fail;
+ }
+ }
+
+ /* Only opy parameters or results when their count > 0 and
+ the src/dst addr are different */
+ copy_arities = check_copy_arities(block_dst, jit_frame);
+
+ if (!copy_arities) {
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
+ if (!(insn = GEN_INSN(
+ BNE, cc->cmp_reg,
+ jit_basic_block_label(block_dst->basic_block_entry),
+ 0))) {
+ jit_set_last_error(cc, "generate bne insn failed");
+ goto fail;
+ }
+ }
+ else {
+ if (!(insn = GEN_INSN(BNE, cc->cmp_reg, 0, 0))) {
+ jit_set_last_error(cc, "generate bne insn failed");
+ goto fail;
+ }
+ if (!jit_block_add_incoming_insn(block_dst, insn, 1)) {
+ jit_set_last_error(cc, "add incoming insn failed");
+ goto fail;
+ }
+ }
+ if (insn_select && insn_cmp) {
+ /* Change `CMP + SELECTcc` into `CMP + Bcc` */
+ insn->opcode = JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
+ jit_insn_unlink(insn_select);
+ jit_insn_delete(insn_select);
+ }
+ return true;
+ }
+
+ CREATE_BASIC_BLOCK(if_basic_block);
+ if (!(insn = GEN_INSN(BNE, cc->cmp_reg,
+ jit_basic_block_label(if_basic_block), 0))) {
+ jit_set_last_error(cc, "generate bne insn failed");
+ goto fail;
+ }
+ if (insn_select && insn_cmp) {
+ /* Change `CMP + SELECTcc` into `CMP + Bcc` */
+ insn->opcode = JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
+ jit_insn_unlink(insn_select);
+ jit_insn_delete(insn_select);
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ return false;
+#endif
+
+ SET_BUILDER_POS(if_basic_block);
+ SET_BB_BEGIN_BCIP(if_basic_block, *p_frame_ip - 1);
+
+ /* Clone current jit frame to a new jit fame */
+ if (!(jit_frame_cloned = jit_frame_clone(jit_frame))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ goto fail;
+ }
+
+ /* Clear current jit frame so that the registers
+ in the new basic block will be loaded again */
+ clear_values(jit_frame);
+ if (!handle_op_br(cc, br_depth, p_frame_ip)) {
+ jit_free(jit_frame_cloned);
+ goto fail;
+ }
+
+ /* Restore the jit frame so that the registers can
+ be used again in current basic block */
+ jit_frame_copy(jit_frame, jit_frame_cloned);
+ jit_free(jit_frame_cloned);
+
+ /* Continue processing opcodes after BR_IF */
+ SET_BUILDER_POS(cur_basic_block);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
+ uint8 **p_frame_ip)
+{
+ JitBasicBlock *cur_basic_block;
+ JitReg value;
+ JitInsn *insn;
+ uint32 i = 0;
+ JitOpndLookupSwitch *opnd = NULL;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ return false;
+#endif
+
+ cur_basic_block = cc->cur_basic_block;
+
+ POP_I32(value);
+
+ /* append LOOKUPSWITCH to current basic block */
+ gen_commit_values(cc->jit_frame, cc->jit_frame->lp, cc->jit_frame->sp);
+ /* Clear frame values */
+ clear_values(cc->jit_frame);
+ SET_BB_END_BCIP(cur_basic_block, *p_frame_ip - 1);
+
+ /* prepare basic blocks for br */
+ insn = GEN_INSN(LOOKUPSWITCH, value, br_count);
+ if (NULL == insn) {
+ jit_set_last_error(cc, "generate insn LOOKUPSWITCH failed");
+ goto fail;
+ }
+
+ for (i = 0, opnd = jit_insn_opndls(insn); i < br_count + 1; i++) {
+ JitBasicBlock *basic_block = NULL;
+ JitBlock *block_dst;
+ bool copy_arities;
+
+ if (!(block_dst = get_target_block(cc, br_depths[i]))) {
+ goto fail;
+ }
+
+ /* Only opy parameters or results when their count > 0 and
+ the src/dst addr are different */
+ copy_arities = check_copy_arities(block_dst, cc->jit_frame);
+
+ if (!copy_arities) {
+ /* No need to create new basic block, direclty jump to
+ the existing basic block when no need to copy arities */
+ if (i == br_count) {
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
+ opnd->default_target =
+ jit_basic_block_label(block_dst->basic_block_entry);
+ }
+ else {
+ bh_assert(!block_dst->basic_block_end);
+ if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
+ jit_set_last_error(cc, "add incoming insn failed");
+ goto fail;
+ }
+ }
+ }
+ else {
+ opnd->match_pairs[i].value = i;
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
+ opnd->match_pairs[i].target =
+ jit_basic_block_label(block_dst->basic_block_entry);
+ }
+ else {
+ bh_assert(!block_dst->basic_block_end);
+ if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
+ jit_set_last_error(cc, "add incoming insn failed");
+ goto fail;
+ }
+ }
+ }
+ continue;
+ }
+
+ /* Create new basic block when need to copy arities */
+ CREATE_BASIC_BLOCK(basic_block);
+ SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip - 1);
+
+ if (i == br_count) {
+ opnd->default_target = jit_basic_block_label(basic_block);
+ }
+ else {
+ opnd->match_pairs[i].value = i;
+ opnd->match_pairs[i].target = jit_basic_block_label(basic_block);
+ }
+
+ SET_BUILDER_POS(basic_block);
+
+ if (!handle_op_br(cc, br_depths[i], p_frame_ip))
+ goto fail;
+ }
+
+ /* Search next available block to handle */
+ return handle_next_reachable_block(cc, p_frame_ip);
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_return(JitCompContext *cc, uint8 **p_frame_ip)
+{
+ JitBlock *block_func = cc->block_stack.block_list_head;
+
+ bh_assert(block_func);
+
+ if (!handle_func_return(cc, block_func)) {
+ return false;
+ }
+ SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
+ clear_values(cc->jit_frame);
+
+ return handle_next_reachable_block(cc, p_frame_ip);
+}
+
+bool
+jit_compile_op_unreachable(JitCompContext *cc, uint8 **p_frame_ip)
+{
+ if (!jit_emit_exception(cc, EXCE_UNREACHABLE, JIT_OP_JMP, 0, NULL))
+ return false;
+
+ return handle_next_reachable_block(cc, p_frame_ip);
+}
+
+bool
+jit_handle_next_reachable_block(JitCompContext *cc, uint8 **p_frame_ip)
+{
+ return handle_next_reachable_block(cc, p_frame_ip);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.h
new file mode 100644
index 000000000..e1bc09a0a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_control.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_CONTROL_H_
+#define _JIT_EMIT_CONTROL_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
+ uint8 *frame_ip_end, uint32 label_type, uint32 param_count,
+ uint8 *param_types, uint32 result_count,
+ uint8 *result_types, bool merge_cmp_and_if);
+
+bool
+jit_compile_op_else(JitCompContext *cc, uint8 **p_frame_ip);
+
+bool
+jit_compile_op_end(JitCompContext *cc, uint8 **p_frame_ip);
+
+bool
+jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip);
+
+bool
+jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth,
+ bool merge_cmp_and_br_if, uint8 **p_frame_ip);
+
+bool
+jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
+ uint8 **p_frame_ip);
+
+bool
+jit_compile_op_return(JitCompContext *cc, uint8 **p_frame_ip);
+
+bool
+jit_compile_op_unreachable(JitCompContext *cc, uint8 **p_frame_ip);
+
+bool
+jit_handle_next_reachable_block(JitCompContext *cc, uint8 **p_frame_ip);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+jit_check_suspend_flags(JitCompContext *cc);
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_CONTROL_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.c
new file mode 100644
index 000000000..8308a3ca9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_conversion.h"
+#include "jit_emit_exception.h"
+#include "jit_emit_function.h"
+#include "../jit_codegen.h"
+#include "../jit_frontend.h"
+
+#define F32_I32_S_MIN (-2147483904.0f)
+#define F32_I32_S_MAX (2147483648.0f)
+#define F32_I32_U_MIN (-1.0f)
+#define F32_I32_U_MAX (4294967296.0f)
+#define F32_I64_S_MIN (-9223373136366403584.0f)
+#define F32_I64_S_MAX (9223372036854775808.0f)
+#define F32_I64_U_MIN (-1.0f)
+#define F32_I64_U_MAX (18446744073709551616.0f)
+
+#define F64_I32_S_MIN (-2147483649.0)
+#define F64_I32_S_MAX (2147483648.0)
+#define F64_I32_U_MIN (-1.0)
+#define F64_I32_U_MAX (4294967296.0)
+#define F64_I64_S_MIN (-9223372036854777856.0)
+#define F64_I64_S_MAX (9223372036854775808.0)
+#define F64_I64_U_MIN (-1.0)
+#define F64_I64_U_MAX (18446744073709551616.0)
+
+#define FP_TO_INT(f_ty, i_ty, f_nm, i_nm) \
+ static i_ty i_nm##_trunc_##f_nm(f_ty fp)
+
+#define INT_TO_FP(i_ty, f_ty, i_nm, f_nm) \
+ static f_ty f_nm##_convert_##i_nm(i_ty i)
+
+#define FP_TO_INT_SAT(f_ty, i_ty, f_nm, i_nm) \
+ static i_ty i_nm##_trunc_##f_nm##_sat(f_ty fp)
+
+static int
+local_isnan(double x)
+{
+ return isnan(x);
+}
+
+static int
+local_isnanf(float x)
+{
+ return isnan(x);
+}
+
+#define RETURN_IF_NANF(fp) \
+ if (local_isnanf(fp)) { \
+ return 0; \
+ }
+
+#define RETURN_IF_NAN(fp) \
+ if (local_isnan(fp)) { \
+ return 0; \
+ }
+
+#define RETURN_IF_INF(fp, i_min, i_max) \
+ if (isinf(fp)) { \
+ return fp < 0 ? i_min : i_max; \
+ }
+
+#define RETURN_IF_MIN(fp, f_min, i_min) \
+ if (fp <= f_min) { \
+ return i_min; \
+ }
+
+#define RETURN_IF_MAX(fp, f_max, i_max) \
+ if (fp >= f_max) { \
+ return i_max; \
+ }
+
+FP_TO_INT_SAT(float, int32, f32, i32)
+{
+ RETURN_IF_NANF(fp)
+ RETURN_IF_INF(fp, INT32_MIN, INT32_MAX)
+ RETURN_IF_MIN(fp, F32_I32_S_MIN, INT32_MIN)
+ RETURN_IF_MAX(fp, F32_I32_S_MAX, INT32_MAX)
+ return (int32)fp;
+}
+
+FP_TO_INT_SAT(float, uint32, f32, u32)
+{
+ RETURN_IF_NANF(fp)
+ RETURN_IF_INF(fp, 0, UINT32_MAX)
+ RETURN_IF_MIN(fp, F32_I32_U_MIN, 0)
+ RETURN_IF_MAX(fp, F32_I32_U_MAX, UINT32_MAX)
+ return (uint32)fp;
+}
+
+FP_TO_INT_SAT(double, int32, f64, i32)
+{
+ RETURN_IF_NAN(fp)
+ RETURN_IF_INF(fp, INT32_MIN, INT32_MAX)
+ RETURN_IF_MIN(fp, F64_I32_S_MIN, INT32_MIN)
+ RETURN_IF_MAX(fp, F64_I32_S_MAX, INT32_MAX)
+ return (int32)fp;
+}
+
+FP_TO_INT_SAT(double, uint32, f64, u32)
+{
+ RETURN_IF_NAN(fp)
+ RETURN_IF_INF(fp, 0, UINT32_MAX)
+ RETURN_IF_MIN(fp, F64_I32_U_MIN, 0)
+ RETURN_IF_MAX(fp, F64_I32_U_MAX, UINT32_MAX)
+ return (uint32)fp;
+}
+
+FP_TO_INT_SAT(float, int64, f32, i64)
+{
+ RETURN_IF_NANF(fp)
+ RETURN_IF_INF(fp, INT64_MIN, INT64_MAX)
+ RETURN_IF_MIN(fp, F32_I64_S_MIN, INT64_MIN)
+ RETURN_IF_MAX(fp, F32_I64_S_MAX, INT64_MAX)
+ return (int64)fp;
+}
+
+FP_TO_INT(float, uint64, f32, u64)
+{
+ return (uint64)fp;
+}
+
+FP_TO_INT_SAT(float, uint64, f32, u64)
+{
+ RETURN_IF_NANF(fp)
+ RETURN_IF_INF(fp, 0, UINT64_MAX)
+ RETURN_IF_MIN(fp, F32_I64_U_MIN, 0)
+ RETURN_IF_MAX(fp, F32_I64_U_MAX, UINT64_MAX)
+ return (uint64)fp;
+}
+
+FP_TO_INT_SAT(double, int64, f64, i64)
+{
+ RETURN_IF_NANF(fp)
+ RETURN_IF_INF(fp, INT64_MIN, INT64_MAX)
+ RETURN_IF_MIN(fp, F64_I64_S_MIN, INT64_MIN)
+ RETURN_IF_MAX(fp, F64_I64_S_MAX, INT64_MAX)
+ return (int64)fp;
+}
+
+FP_TO_INT(double, uint64, f64, u64)
+{
+ return (uint64)fp;
+}
+
+FP_TO_INT_SAT(double, uint64, f64, u64)
+{
+ RETURN_IF_NANF(fp)
+ RETURN_IF_INF(fp, 0, UINT64_MAX)
+ RETURN_IF_MIN(fp, F64_I64_U_MIN, 0)
+ RETURN_IF_MAX(fp, F64_I64_U_MAX, UINT64_MAX)
+ return (uint64)fp;
+}
+
+INT_TO_FP(uint64, float, u64, f32)
+{
+ return (float)i;
+}
+
+INT_TO_FP(uint64, double, u64, f64)
+{
+ return (double)i;
+}
+
+bool
+jit_compile_op_i32_wrap_i64(JitCompContext *cc)
+{
+ JitReg num, res;
+
+ POP_I64(num);
+
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(I64TOI32, res, num);
+
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+jit_compile_check_value_range(JitCompContext *cc, JitReg value, JitReg min_fp,
+ JitReg max_fp)
+{
+ JitReg nan_ret = jit_cc_new_reg_I32(cc);
+ JitRegKind kind = jit_reg_kind(value);
+ bool emit_ret = false;
+
+ bh_assert(JIT_REG_KIND_F32 == kind || JIT_REG_KIND_F64 == kind);
+
+ /* If value is NaN, throw exception */
+ if (JIT_REG_KIND_F32 == kind)
+ emit_ret = jit_emit_callnative(cc, local_isnanf, nan_ret, &value, 1);
+ else
+ emit_ret = jit_emit_callnative(cc, local_isnan, nan_ret, &value, 1);
+ if (!emit_ret)
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, nan_ret, NEW_CONST(I32, 1));
+ if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER, JIT_OP_BEQ,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ /* If value is out of integer range, throw exception */
+ GEN_INSN(CMP, cc->cmp_reg, min_fp, value);
+ if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BGES, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, value, max_fp);
+ if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BGES, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_trunc_f32(JitCompContext *cc, bool sign, bool sat)
+{
+ JitReg value, res;
+
+ POP_F32(value);
+
+ res = jit_cc_new_reg_I32(cc);
+ if (!sat) {
+ JitReg min_fp = NEW_CONST(F32, sign ? F32_I32_S_MIN : F32_I32_U_MIN);
+ JitReg max_fp = NEW_CONST(F32, sign ? F32_I32_S_MAX : F32_I32_U_MAX);
+
+ if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
+ goto fail;
+
+ if (sign)
+ GEN_INSN(F32TOI32, res, value);
+ else
+ GEN_INSN(F32TOU32, res, value);
+ }
+ else {
+ if (!jit_emit_callnative(cc,
+ sign ? (void *)i32_trunc_f32_sat
+ : (void *)u32_trunc_f32_sat,
+ res, &value, 1))
+ goto fail;
+ }
+
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_trunc_f64(JitCompContext *cc, bool sign, bool sat)
+{
+ JitReg value, res;
+
+ POP_F64(value);
+
+ res = jit_cc_new_reg_I32(cc);
+ if (!sat) {
+ JitReg min_fp = NEW_CONST(F64, sign ? F64_I32_S_MIN : F64_I32_U_MIN);
+ JitReg max_fp = NEW_CONST(F64, sign ? F64_I32_S_MAX : F64_I32_U_MAX);
+
+ if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
+ goto fail;
+
+ if (sign)
+ GEN_INSN(F64TOI32, res, value);
+ else
+ GEN_INSN(F64TOU32, res, value);
+ }
+ else {
+ if (!jit_emit_callnative(cc,
+ sign ? (void *)i32_trunc_f64_sat
+ : (void *)u32_trunc_f64_sat,
+ res, &value, 1))
+ goto fail;
+ }
+
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_extend_i32(JitCompContext *cc, bool sign)
+{
+ JitReg num, res;
+
+ POP_I32(num);
+
+ res = jit_cc_new_reg_I64(cc);
+ if (sign)
+ GEN_INSN(I32TOI64, res, num);
+ else
+ GEN_INSN(U32TOI64, res, num);
+
+ PUSH_I64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_extend_i64(JitCompContext *cc, int8 bitwidth)
+{
+ JitReg value, tmp, res;
+
+ POP_I64(value);
+
+ tmp = jit_cc_new_reg_I32(cc);
+ res = jit_cc_new_reg_I64(cc);
+
+ switch (bitwidth) {
+ case 8:
+ {
+ GEN_INSN(I64TOI8, tmp, value);
+ GEN_INSN(I8TOI64, res, tmp);
+ break;
+ }
+ case 16:
+ {
+ GEN_INSN(I64TOI16, tmp, value);
+ GEN_INSN(I16TOI64, res, tmp);
+ break;
+ }
+ case 32:
+ {
+ GEN_INSN(I64TOI32, tmp, value);
+ GEN_INSN(I32TOI64, res, tmp);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ PUSH_I64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_extend_i32(JitCompContext *cc, int8 bitwidth)
+{
+ JitReg value, tmp, res;
+
+ POP_I32(value);
+
+ tmp = jit_cc_new_reg_I32(cc);
+ res = jit_cc_new_reg_I32(cc);
+
+ switch (bitwidth) {
+ case 8:
+ {
+ GEN_INSN(I32TOI8, tmp, value);
+ GEN_INSN(I8TOI32, res, tmp);
+ break;
+ }
+ case 16:
+ {
+ GEN_INSN(I32TOI16, tmp, value);
+ GEN_INSN(I16TOI32, res, tmp);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_trunc_f32(JitCompContext *cc, bool sign, bool sat)
+{
+ JitReg value, res;
+
+ POP_F32(value);
+
+ res = jit_cc_new_reg_I64(cc);
+ if (!sat) {
+ JitReg min_fp = NEW_CONST(F32, sign ? F32_I64_S_MIN : F32_I64_U_MIN);
+ JitReg max_fp = NEW_CONST(F32, sign ? F32_I64_S_MAX : F32_I64_U_MAX);
+
+ if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
+ goto fail;
+
+ if (sign) {
+ GEN_INSN(F32TOI64, res, value);
+ }
+ else {
+ if (!jit_emit_callnative(cc, u64_trunc_f32, res, &value, 1))
+ goto fail;
+ }
+ }
+ else {
+ if (!jit_emit_callnative(cc,
+ sign ? (void *)i64_trunc_f32_sat
+ : (void *)u64_trunc_f32_sat,
+ res, &value, 1))
+ goto fail;
+ }
+
+ PUSH_I64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_trunc_f64(JitCompContext *cc, bool sign, bool sat)
+{
+ JitReg value, res;
+
+ POP_F64(value);
+
+ res = jit_cc_new_reg_I64(cc);
+ if (!sat) {
+ JitReg min_fp = NEW_CONST(F64, sign ? F64_I64_S_MIN : F64_I64_U_MIN);
+ JitReg max_fp = NEW_CONST(F64, sign ? F64_I64_S_MAX : F64_I64_U_MAX);
+
+ if (!jit_compile_check_value_range(cc, value, min_fp, max_fp))
+ goto fail;
+
+ if (sign) {
+ GEN_INSN(F64TOI64, res, value);
+ }
+ else {
+ if (!jit_emit_callnative(cc, u64_trunc_f64, res, &value, 1))
+ goto fail;
+ }
+ }
+ else {
+ if (!jit_emit_callnative(cc,
+ sign ? (void *)i64_trunc_f64_sat
+ : (void *)u64_trunc_f64_sat,
+ res, &value, 1))
+ goto fail;
+ }
+
+ PUSH_I64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_convert_i32(JitCompContext *cc, bool sign)
+{
+ JitReg value, res;
+
+ POP_I32(value);
+
+ res = jit_cc_new_reg_F32(cc);
+ if (sign) {
+ GEN_INSN(I32TOF32, res, value);
+ }
+ else {
+ GEN_INSN(U32TOF32, res, value);
+ }
+
+ PUSH_F32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_convert_i64(JitCompContext *cc, bool sign)
+{
+ JitReg value, res;
+
+ POP_I64(value);
+
+ res = jit_cc_new_reg_F32(cc);
+ if (sign) {
+ GEN_INSN(I64TOF32, res, value);
+ }
+ else {
+ if (!jit_emit_callnative(cc, f32_convert_u64, res, &value, 1)) {
+ goto fail;
+ }
+ }
+
+ PUSH_F32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_demote_f64(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_F64(value);
+
+ res = jit_cc_new_reg_F32(cc);
+ GEN_INSN(F64TOF32, res, value);
+
+ PUSH_F32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_convert_i32(JitCompContext *cc, bool sign)
+{
+ JitReg value, res;
+
+ POP_I32(value);
+
+ res = jit_cc_new_reg_F64(cc);
+ if (sign)
+ GEN_INSN(I32TOF64, res, value);
+ else
+ GEN_INSN(U32TOF64, res, value);
+
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_convert_i64(JitCompContext *cc, bool sign)
+{
+ JitReg value, res;
+
+ POP_I64(value);
+
+ res = jit_cc_new_reg_F64(cc);
+ if (sign) {
+ GEN_INSN(I64TOF64, res, value);
+ }
+ else {
+ if (!jit_emit_callnative(cc, f64_convert_u64, res, &value, 1)) {
+ goto fail;
+ }
+ }
+
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_promote_f32(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_F32(value);
+
+ res = jit_cc_new_reg_F64(cc);
+ GEN_INSN(F32TOF64, res, value);
+
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_reinterpret_f64(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_F64(value);
+
+ res = jit_cc_new_reg_I64(cc);
+ GEN_INSN(F64CASTI64, res, value);
+
+ PUSH_I64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_reinterpret_f32(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_F32(value);
+
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(F32CASTI32, res, value);
+
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_reinterpret_i64(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I64(value);
+
+ res = jit_cc_new_reg_F64(cc);
+ GEN_INSN(I64CASTF64, res, value);
+
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_reinterpret_i32(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I32(value);
+
+ res = jit_cc_new_reg_F32(cc);
+ GEN_INSN(I32CASTF32, res, value);
+
+ PUSH_F32(res);
+
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.h
new file mode 100644
index 000000000..28952fc61
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_conversion.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_CONVERSION_H_
+#define _JIT_EMIT_CONVERSION_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_i32_wrap_i64(JitCompContext *cc);
+
+bool
+jit_compile_op_i32_trunc_f32(JitCompContext *cc, bool sign, bool sat);
+
+bool
+jit_compile_op_i32_trunc_f64(JitCompContext *cc, bool sign, bool sat);
+
+bool
+jit_compile_op_i64_extend_i32(JitCompContext *comp_ctx, bool sign);
+
+bool
+jit_compile_op_i64_extend_i64(JitCompContext *comp_ctx, int8 bitwidth);
+
+bool
+jit_compile_op_i32_extend_i32(JitCompContext *comp_ctx, int8 bitwidth);
+
+bool
+jit_compile_op_i64_trunc_f32(JitCompContext *cc, bool sign, bool sat);
+
+bool
+jit_compile_op_i64_trunc_f64(JitCompContext *cc, bool sign, bool sat);
+
+bool
+jit_compile_op_f32_convert_i32(JitCompContext *comp_ctx, bool sign);
+
+bool
+jit_compile_op_f32_convert_i64(JitCompContext *comp_ctx, bool sign);
+
+bool
+jit_compile_op_f32_demote_f64(JitCompContext *comp_ctx);
+
+bool
+jit_compile_op_f64_convert_i32(JitCompContext *comp_ctx, bool sign);
+
+bool
+jit_compile_op_f64_convert_i64(JitCompContext *comp_ctx, bool sign);
+
+bool
+jit_compile_op_f64_promote_f32(JitCompContext *comp_ctx);
+
+bool
+jit_compile_op_i64_reinterpret_f64(JitCompContext *comp_ctx);
+
+bool
+jit_compile_op_i32_reinterpret_f32(JitCompContext *comp_ctx);
+
+bool
+jit_compile_op_f64_reinterpret_i64(JitCompContext *comp_ctx);
+
+bool
+jit_compile_op_f32_reinterpret_i32(JitCompContext *comp_ctx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_CONVERSION_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.c
new file mode 100644
index 000000000..2addb5cde
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_exception.h"
+#include "../jit_frontend.h"
+
+bool
+jit_emit_exception(JitCompContext *cc, int32 exception_id, uint8 jit_opcode,
+ JitReg cond_br_if, JitBasicBlock *cond_br_else_block)
+{
+ JitInsn *insn = NULL;
+ JitIncomingInsn *incoming_insn;
+ JitReg else_label;
+
+ bh_assert(exception_id < EXCE_NUM);
+
+ if (jit_opcode >= JIT_OP_BEQ && jit_opcode <= JIT_OP_BLEU) {
+ bh_assert(cond_br_if == cc->cmp_reg);
+ else_label =
+ cond_br_else_block ? jit_basic_block_label(cond_br_else_block) : 0;
+ switch (jit_opcode) {
+ case JIT_OP_BEQ:
+ insn = GEN_INSN(BEQ, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BNE:
+ insn = GEN_INSN(BNE, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BGTS:
+ insn = GEN_INSN(BGTS, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BGES:
+ insn = GEN_INSN(BGES, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BLTS:
+ insn = GEN_INSN(BLTS, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BLES:
+ insn = GEN_INSN(BLES, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BGTU:
+ insn = GEN_INSN(BGTU, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BGEU:
+ insn = GEN_INSN(BGEU, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BLTU:
+ insn = GEN_INSN(BLTU, cond_br_if, 0, else_label);
+ break;
+ case JIT_OP_BLEU:
+ insn = GEN_INSN(BLEU, cond_br_if, 0, else_label);
+ break;
+ }
+ if (!insn) {
+ jit_set_last_error(cc, "generate cond br insn failed");
+ return false;
+ }
+ }
+ else if (jit_opcode == JIT_OP_JMP) {
+ insn = GEN_INSN(JMP, 0);
+ if (!insn) {
+ jit_set_last_error(cc, "generate jmp insn failed");
+ return false;
+ }
+ }
+
+ incoming_insn = jit_calloc(sizeof(JitIncomingInsn));
+ if (!incoming_insn) {
+ jit_set_last_error(cc, "allocate memory failed");
+ return false;
+ }
+
+ incoming_insn->insn = insn;
+ incoming_insn->next = cc->incoming_insns_for_exec_bbs[exception_id];
+ cc->incoming_insns_for_exec_bbs[exception_id] = incoming_insn;
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.h
new file mode 100644
index 000000000..7aa393b78
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_exception.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_EXCEPTION_H_
+#define _JIT_EMIT_EXCEPTION_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_emit_exception(JitCompContext *cc, int32 exception_id, uint8 jit_opcode,
+ JitReg cond_br_if, JitBasicBlock *cond_br_else_block);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_EXCEPTION_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.c
new file mode 100644
index 000000000..3ac9e3ed6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.c
@@ -0,0 +1,945 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_function.h"
+#include "jit_emit_exception.h"
+#include "jit_emit_control.h"
+#include "../jit_frontend.h"
+#include "../jit_codegen.h"
+#include "../../interpreter/wasm_runtime.h"
+
+static bool
+emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
+ JitReg *params, uint32 param_count);
+
+/* Prepare parameters for the function to call */
+static bool
+pre_call(JitCompContext *cc, const WASMType *func_type)
+{
+ JitReg value;
+ uint32 i, outs_off;
+ /* Prepare parameters for the function to call */
+ outs_off =
+ cc->total_frame_size + offsetof(WASMInterpFrame, lp)
+ + wasm_get_cell_num(func_type->types, func_type->param_count) * 4;
+
+ for (i = 0; i < func_type->param_count; i++) {
+ switch (func_type->types[func_type->param_count - 1 - i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ POP_I32(value);
+ outs_off -= 4;
+ GEN_INSN(STI32, value, cc->fp_reg, NEW_CONST(I32, outs_off));
+ break;
+ case VALUE_TYPE_I64:
+ POP_I64(value);
+ outs_off -= 8;
+ GEN_INSN(STI64, value, cc->fp_reg, NEW_CONST(I32, outs_off));
+ break;
+ case VALUE_TYPE_F32:
+ POP_F32(value);
+ outs_off -= 4;
+ GEN_INSN(STF32, value, cc->fp_reg, NEW_CONST(I32, outs_off));
+ break;
+ case VALUE_TYPE_F64:
+ POP_F64(value);
+ outs_off -= 8;
+ GEN_INSN(STF64, value, cc->fp_reg, NEW_CONST(I32, outs_off));
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ /* Commit sp as the callee may use it to store the results */
+ gen_commit_sp_ip(cc->jit_frame);
+
+ return true;
+fail:
+ return false;
+}
+
+/* Push results */
+static bool
+post_return(JitCompContext *cc, const WASMType *func_type, JitReg first_res,
+ bool update_committed_sp)
+{
+ uint32 i, n;
+ JitReg value;
+
+ n = cc->jit_frame->sp - cc->jit_frame->lp;
+ for (i = 0; i < func_type->result_count; i++) {
+ switch (func_type->types[func_type->param_count + i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ if (i == 0 && first_res) {
+ bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_I32);
+ value = first_res;
+ }
+ else {
+ value = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, value, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+ PUSH_I32(value);
+ n++;
+ break;
+ case VALUE_TYPE_I64:
+ if (i == 0 && first_res) {
+ bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_I64);
+ value = first_res;
+ }
+ else {
+ value = jit_cc_new_reg_I64(cc);
+ GEN_INSN(LDI64, value, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+ PUSH_I64(value);
+ n += 2;
+ break;
+ case VALUE_TYPE_F32:
+ if (i == 0 && first_res) {
+ bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_F32);
+ value = first_res;
+ }
+ else {
+ value = jit_cc_new_reg_F32(cc);
+ GEN_INSN(LDF32, value, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+ PUSH_F32(value);
+ n++;
+ break;
+ case VALUE_TYPE_F64:
+ if (i == 0 && first_res) {
+ bh_assert(jit_reg_kind(first_res) == JIT_REG_KIND_F64);
+ value = first_res;
+ }
+ else {
+ value = jit_cc_new_reg_F64(cc);
+ GEN_INSN(LDF64, value, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+ PUSH_F64(value);
+ n += 2;
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ if (update_committed_sp)
+ /* Update the committed_sp as the callee has updated the frame sp */
+ cc->jit_frame->committed_sp = cc->jit_frame->sp;
+
+ return true;
+fail:
+ return false;
+}
+
+static bool
+pre_load(JitCompContext *cc, JitReg *argvs, const WASMType *func_type)
+{
+ JitReg value;
+ uint32 i;
+
+ /* Prepare parameters for the function to call */
+ for (i = 0; i < func_type->param_count; i++) {
+ switch (func_type->types[func_type->param_count - 1 - i]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ POP_I32(value);
+ argvs[func_type->param_count - 1 - i] = value;
+ break;
+ case VALUE_TYPE_I64:
+ POP_I64(value);
+ argvs[func_type->param_count - 1 - i] = value;
+ break;
+ case VALUE_TYPE_F32:
+ POP_F32(value);
+ argvs[func_type->param_count - 1 - i] = value;
+ break;
+ case VALUE_TYPE_F64:
+ POP_F64(value);
+ argvs[func_type->param_count - 1 - i] = value;
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ gen_commit_sp_ip(cc->jit_frame);
+
+ return true;
+fail:
+ return false;
+}
+
+static JitReg
+create_first_res_reg(JitCompContext *cc, const WASMType *func_type)
+{
+ if (func_type->result_count) {
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ return jit_cc_new_reg_I32(cc);
+ case VALUE_TYPE_I64:
+ return jit_cc_new_reg_I64(cc);
+ case VALUE_TYPE_F32:
+ return jit_cc_new_reg_F32(cc);
+ case VALUE_TYPE_F64:
+ return jit_cc_new_reg_F64(cc);
+ default:
+ bh_assert(0);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+bool
+jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call)
+{
+ WASMModule *wasm_module = cc->cur_wasm_module;
+ WASMFunctionImport *func_import;
+ WASMFunction *func;
+ WASMType *func_type;
+ JitFrame *jit_frame = cc->jit_frame;
+ JitReg fast_jit_func_ptrs, jitted_code = 0;
+ JitReg native_func, *argvs = NULL, *argvs1 = NULL, func_params[5];
+ JitReg native_addr_ptr, module_inst_reg, ret, res;
+ uint32 jitted_func_idx, i;
+ uint64 total_size;
+ const char *signature = NULL;
+ /* Whether the argument is a pointer/str argument and
+ need to call jit_check_app_addr_and_convert */
+ bool is_pointer_arg;
+ bool return_value = false;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ goto fail;
+#endif
+
+ if (func_idx < wasm_module->import_function_count) {
+ /* The function to call is an import function */
+ func_import = &wasm_module->import_functions[func_idx].u.function;
+ func_type = func_import->func_type;
+
+ /* Call fast_jit_invoke_native in some cases */
+ if (!func_import->func_ptr_linked /* import func hasn't been linked */
+ || func_import->call_conv_wasm_c_api /* linked by wasm_c_api */
+ || func_import->call_conv_raw /* registered as raw mode */
+ || func_type->param_count >= 5 /* registered as normal mode, but
+ jit_emit_callnative only supports
+ maximum 6 registers now
+ (include exec_nev) */) {
+ JitReg arg_regs[3];
+
+ if (!pre_call(cc, func_type)) {
+ goto fail;
+ }
+
+ /* Call fast_jit_invoke_native */
+ ret = jit_cc_new_reg_I32(cc);
+ arg_regs[0] = cc->exec_env_reg;
+ arg_regs[1] = NEW_CONST(I32, func_idx);
+ arg_regs[2] = cc->fp_reg;
+ if (!jit_emit_callnative(cc, fast_jit_invoke_native, ret, arg_regs,
+ 3)) {
+ goto fail;
+ }
+
+ /* Convert the return value from bool to uint32 */
+ GEN_INSN(AND, ret, ret, NEW_CONST(I32, 0xFF));
+
+ /* Check whether there is exception thrown */
+ GEN_INSN(CMP, cc->cmp_reg, ret, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ,
+ cc->cmp_reg, NULL)) {
+ goto fail;
+ }
+
+ if (!post_return(cc, func_type, 0, true)) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ goto fail;
+#endif
+
+ return true;
+ }
+
+ /* Import function was registered as normal mode, and its argument count
+ is no more than 5, we directly call it */
+
+ signature = func_import->signature;
+ bh_assert(signature);
+
+ /* Allocate memory for argvs*/
+ total_size = sizeof(JitReg) * (uint64)(func_type->param_count);
+ if (total_size > 0) {
+ if (total_size >= UINT32_MAX
+ || !(argvs = jit_malloc((uint32)total_size))) {
+ goto fail;
+ }
+ }
+
+ /* Pop function params from stack and store them into argvs */
+ if (!pre_load(cc, argvs, func_type)) {
+ goto fail;
+ }
+
+ ret = jit_cc_new_reg_I32(cc);
+ func_params[0] = module_inst_reg = get_module_inst_reg(jit_frame);
+ func_params[4] = native_addr_ptr = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(ADD, native_addr_ptr, cc->exec_env_reg,
+ NEW_CONST(PTR, offsetof(WASMExecEnv, jit_cache)));
+
+ /* Traverse each pointer/str argument, call
+ jit_check_app_addr_and_convert to check whether it is
+ in the range of linear memory and and convert it from
+ app offset into native address */
+ for (i = 0; i < func_type->param_count; i++) {
+
+ is_pointer_arg = false;
+
+ if (signature[i + 1] == '*') {
+ /* param is a pointer */
+ is_pointer_arg = true;
+ func_params[1] = NEW_CONST(I32, false); /* is_str = false */
+ func_params[2] = argvs[i];
+ if (signature[i + 2] == '~') {
+ /* pointer with length followed */
+ func_params[3] = argvs[i + 1];
+ }
+ else {
+ /* pointer with length followed */
+ func_params[3] = NEW_CONST(I32, 1);
+ }
+ }
+ else if (signature[i + 1] == '$') {
+ /* param is a string */
+ is_pointer_arg = true;
+ func_params[1] = NEW_CONST(I32, true); /* is_str = true */
+ func_params[2] = argvs[i];
+ func_params[3] = NEW_CONST(I32, 1);
+ }
+
+ if (is_pointer_arg) {
+ if (!jit_emit_callnative(cc, jit_check_app_addr_and_convert,
+ ret, func_params, 5)) {
+ goto fail;
+ }
+
+ /* Convert the return value from bool to uint32 */
+ GEN_INSN(AND, ret, ret, NEW_CONST(I32, 0xFF));
+ /* Check whether there is exception thrown */
+ GEN_INSN(CMP, cc->cmp_reg, ret, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ,
+ cc->cmp_reg, NULL)) {
+ return false;
+ }
+
+ /* Load native addr from pointer of native addr,
+ or exec_env->jit_cache */
+ argvs[i] = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(LDPTR, argvs[i], native_addr_ptr, NEW_CONST(I32, 0));
+ }
+ }
+
+ res = create_first_res_reg(cc, func_type);
+
+ /* Prepare arguments of the native function */
+ if (!(argvs1 =
+ jit_calloc(sizeof(JitReg) * (func_type->param_count + 1)))) {
+ goto fail;
+ }
+ argvs1[0] = cc->exec_env_reg;
+ for (i = 0; i < func_type->param_count; i++) {
+ argvs1[i + 1] = argvs[i];
+ }
+
+ /* Call the native function */
+ native_func = NEW_CONST(PTR, (uintptr_t)func_import->func_ptr_linked);
+ if (!emit_callnative(cc, native_func, res, argvs1,
+ func_type->param_count + 1)) {
+ jit_free(argvs1);
+ goto fail;
+ }
+ jit_free(argvs1);
+
+ /* Check whether there is exception thrown */
+ GEN_INSN(LDI8, ret, module_inst_reg,
+ NEW_CONST(I32, offsetof(WASMModuleInstance, cur_exception)));
+ GEN_INSN(CMP, cc->cmp_reg, ret, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BNE,
+ cc->cmp_reg, NULL)) {
+ goto fail;
+ }
+
+ if (!post_return(cc, func_type, res, false)) {
+ goto fail;
+ }
+ }
+ else {
+ /* The function to call is a bytecode function */
+ func = wasm_module
+ ->functions[func_idx - wasm_module->import_function_count];
+ func_type = func->func_type;
+
+ /* jitted_code = func_ptrs[func_idx - import_function_count] */
+ fast_jit_func_ptrs = get_fast_jit_func_ptrs_reg(jit_frame);
+ jitted_code = jit_cc_new_reg_ptr(cc);
+ jitted_func_idx = func_idx - wasm_module->import_function_count;
+ GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs,
+ NEW_CONST(I32, (uint32)sizeof(void *) * jitted_func_idx));
+
+ if (!pre_call(cc, func_type)) {
+ goto fail;
+ }
+
+ res = create_first_res_reg(cc, func_type);
+
+ GEN_INSN(CALLBC, res, 0, jitted_code, NEW_CONST(I32, func_idx));
+
+ if (!post_return(cc, func_type, res, true)) {
+ goto fail;
+ }
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ goto fail;
+#endif
+
+ /* Clear part of memory regs and table regs as their values
+ may be changed in the function call */
+ if (cc->cur_wasm_module->possible_memory_grow)
+ clear_memory_regs(jit_frame);
+ clear_table_regs(jit_frame);
+
+ /* Ignore tail call currently */
+ (void)tail_call;
+
+ return_value = true;
+
+fail:
+ if (argvs)
+ jit_free(argvs);
+
+ return return_value;
+}
+
+static JitReg
+pack_argv(JitCompContext *cc)
+{
+ /* reuse the stack of the next frame */
+ uint32 stack_base;
+ JitReg argv;
+
+ stack_base = cc->total_frame_size + offsetof(WASMInterpFrame, lp);
+ argv = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(ADD, argv, cc->fp_reg, NEW_CONST(PTR, stack_base));
+ if (jit_get_last_error(cc)) {
+ return (JitReg)0;
+ }
+ return argv;
+}
+
+bool
+jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
+ uint32 tbl_idx)
+{
+ WASMModule *wasm_module = cc->cur_wasm_module;
+ JitBasicBlock *block_import, *block_nonimport, *func_return;
+ JitReg elem_idx, native_ret, argv, arg_regs[6];
+ JitFrame *jit_frame = cc->jit_frame;
+ JitReg tbl_size, offset, offset_i32;
+ JitReg func_import, func_idx, tbl_elems, func_count;
+ JitReg func_type_indexes, func_type_idx, fast_jit_func_ptrs;
+ JitReg offset1_i32, offset1, func_type_idx1, res;
+ JitReg import_func_ptrs, jitted_code_idx, jitted_code;
+ WASMType *func_type;
+ uint32 n;
+
+ POP_I32(elem_idx);
+
+ /* check elem_idx */
+ tbl_size = get_table_cur_size_reg(jit_frame, tbl_idx);
+
+ GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_size);
+ if (!jit_emit_exception(cc, EXCE_UNDEFINED_ELEMENT, JIT_OP_BGEU,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ /* check func_idx */
+ if (UINTPTR_MAX == UINT64_MAX) {
+ offset_i32 = jit_cc_new_reg_I32(cc);
+ offset = jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHL, offset_i32, elem_idx, NEW_CONST(I32, 2));
+ GEN_INSN(I32TOI64, offset, offset_i32);
+ }
+ else {
+ offset = jit_cc_new_reg_I32(cc);
+ GEN_INSN(SHL, offset, elem_idx, NEW_CONST(I32, 2));
+ }
+ func_idx = jit_cc_new_reg_I32(cc);
+ tbl_elems = get_table_elems_reg(jit_frame, tbl_idx);
+ GEN_INSN(LDI32, func_idx, tbl_elems, offset);
+
+ GEN_INSN(CMP, cc->cmp_reg, func_idx, NEW_CONST(I32, -1));
+ if (!jit_emit_exception(cc, EXCE_UNINITIALIZED_ELEMENT, JIT_OP_BEQ,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ func_count = NEW_CONST(I32, wasm_module->import_function_count
+ + wasm_module->function_count);
+ GEN_INSN(CMP, cc->cmp_reg, func_idx, func_count);
+ if (!jit_emit_exception(cc, EXCE_INVALID_FUNCTION_INDEX, JIT_OP_BGTU,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ /* check func_type */
+ /* get func_type_idx from func_type_indexes */
+ if (UINTPTR_MAX == UINT64_MAX) {
+ offset1_i32 = jit_cc_new_reg_I32(cc);
+ offset1 = jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHL, offset1_i32, func_idx, NEW_CONST(I32, 2));
+ GEN_INSN(I32TOI64, offset1, offset1_i32);
+ }
+ else {
+ offset1 = jit_cc_new_reg_I32(cc);
+ GEN_INSN(SHL, offset1, func_idx, NEW_CONST(I32, 2));
+ }
+
+ func_type_indexes = get_func_type_indexes_reg(jit_frame);
+ func_type_idx = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, func_type_idx, func_type_indexes, offset1);
+
+ type_idx = wasm_get_smallest_type_idx(wasm_module->types,
+ wasm_module->type_count, type_idx);
+ func_type_idx1 = NEW_CONST(I32, type_idx);
+ GEN_INSN(CMP, cc->cmp_reg, func_type_idx, func_type_idx1);
+ if (!jit_emit_exception(cc, EXCE_INVALID_FUNCTION_TYPE_INDEX, JIT_OP_BNE,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ /* pop function arguments and store it to out area of callee stack frame */
+ func_type = wasm_module->types[type_idx];
+ if (!pre_call(cc, func_type)) {
+ goto fail;
+ }
+
+ /* store elem_idx and func_idx to exec_env->jit_cache */
+ GEN_INSN(STI32, elem_idx, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache)));
+ GEN_INSN(STI32, func_idx, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ goto fail;
+#endif
+
+ block_import = jit_cc_new_basic_block(cc, 0);
+ block_nonimport = jit_cc_new_basic_block(cc, 0);
+ func_return = jit_cc_new_basic_block(cc, 0);
+ if (!block_import || !block_nonimport || !func_return) {
+ goto fail;
+ }
+
+ /* Commit register values to locals and stacks */
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ /* Clear frame values */
+ clear_values(jit_frame);
+
+ /* jump to block_import or block_nonimport */
+ GEN_INSN(CMP, cc->cmp_reg, func_idx,
+ NEW_CONST(I32, cc->cur_wasm_module->import_function_count));
+ GEN_INSN(BLTU, cc->cmp_reg, jit_basic_block_label(block_import),
+ jit_basic_block_label(block_nonimport));
+
+ /* block_import */
+ cc->cur_basic_block = block_import;
+
+ elem_idx = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, elem_idx, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache)));
+ GEN_INSN(LDI32, func_idx, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
+
+ argv = pack_argv(cc);
+ if (!argv) {
+ goto fail;
+ }
+ native_ret = jit_cc_new_reg_I32(cc);
+ arg_regs[0] = cc->exec_env_reg;
+ arg_regs[1] = NEW_CONST(I32, tbl_idx);
+ arg_regs[2] = elem_idx;
+ arg_regs[3] = NEW_CONST(I32, type_idx);
+ arg_regs[4] = NEW_CONST(I32, func_type->param_cell_num);
+ arg_regs[5] = argv;
+
+ import_func_ptrs = get_import_func_ptrs_reg(jit_frame);
+ func_import = jit_cc_new_reg_ptr(cc);
+ if (UINTPTR_MAX == UINT64_MAX) {
+ JitReg func_import_offset = jit_cc_new_reg_I32(cc);
+ JitReg func_import_offset_i64 = jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHL, func_import_offset, func_idx, NEW_CONST(I32, 3));
+ GEN_INSN(I32TOI64, func_import_offset_i64, func_import_offset);
+ GEN_INSN(LDPTR, func_import, import_func_ptrs, func_import_offset_i64);
+ }
+ else {
+ JitReg func_import_offset = jit_cc_new_reg_I32(cc);
+ GEN_INSN(SHL, func_import_offset, func_idx, NEW_CONST(I32, 2));
+ GEN_INSN(LDPTR, func_import, import_func_ptrs, func_import_offset);
+ }
+ if (!jit_emit_callnative(cc, fast_jit_call_indirect, native_ret, arg_regs,
+ 6)) {
+ goto fail;
+ }
+
+ /* Convert bool to uint32 */
+ GEN_INSN(AND, native_ret, native_ret, NEW_CONST(I32, 0xFF));
+
+ /* Check whether there is exception thrown */
+ GEN_INSN(CMP, cc->cmp_reg, native_ret, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
+ NULL)) {
+ return false;
+ }
+
+ /* Store res into current frame, so that post_return in
+ block func_return can get the value */
+ n = cc->jit_frame->sp - cc->jit_frame->lp;
+ if (func_type->result_count > 0) {
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, res, argv, NEW_CONST(I32, 0));
+ GEN_INSN(STI32, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ case VALUE_TYPE_I64:
+ res = jit_cc_new_reg_I64(cc);
+ GEN_INSN(LDI64, res, argv, NEW_CONST(I32, 0));
+ GEN_INSN(STI64, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ case VALUE_TYPE_F32:
+ res = jit_cc_new_reg_F32(cc);
+ GEN_INSN(LDF32, res, argv, NEW_CONST(I32, 0));
+ GEN_INSN(STF32, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ case VALUE_TYPE_F64:
+ res = jit_cc_new_reg_F64(cc);
+ GEN_INSN(LDF64, res, argv, NEW_CONST(I32, 0));
+ GEN_INSN(STF64, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ clear_values(jit_frame);
+ GEN_INSN(JMP, jit_basic_block_label(func_return));
+
+ /* basic_block non_import */
+ cc->cur_basic_block = block_nonimport;
+
+ GEN_INSN(LDI32, func_idx, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, jit_cache) + 4));
+
+ /* get jitted_code */
+ fast_jit_func_ptrs = get_fast_jit_func_ptrs_reg(jit_frame);
+ jitted_code_idx = jit_cc_new_reg_I32(cc);
+ jitted_code = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(SUB, jitted_code_idx, func_idx,
+ NEW_CONST(I32, cc->cur_wasm_module->import_function_count));
+ if (UINTPTR_MAX == UINT64_MAX) {
+ JitReg jitted_code_offset = jit_cc_new_reg_I32(cc);
+ JitReg jitted_code_offset_64 = jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHL, jitted_code_offset, jitted_code_idx, NEW_CONST(I32, 3));
+ GEN_INSN(I32TOI64, jitted_code_offset_64, jitted_code_offset);
+ GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs, jitted_code_offset_64);
+ }
+ else {
+ JitReg jitted_code_offset = jit_cc_new_reg_I32(cc);
+ GEN_INSN(SHL, jitted_code_offset, jitted_code_idx, NEW_CONST(I32, 2));
+ GEN_INSN(LDPTR, jitted_code, fast_jit_func_ptrs, jitted_code_offset);
+ }
+
+ res = 0;
+ if (func_type->result_count > 0) {
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ res = jit_cc_new_reg_I32(cc);
+ break;
+ case VALUE_TYPE_I64:
+ res = jit_cc_new_reg_I64(cc);
+ break;
+ case VALUE_TYPE_F32:
+ res = jit_cc_new_reg_F32(cc);
+ break;
+ case VALUE_TYPE_F64:
+ res = jit_cc_new_reg_F64(cc);
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+ }
+ GEN_INSN(CALLBC, res, 0, jitted_code, func_idx);
+ /* Store res into current frame, so that post_return in
+ block func_return can get the value */
+ n = cc->jit_frame->sp - cc->jit_frame->lp;
+ if (func_type->result_count > 0) {
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ GEN_INSN(STI32, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ case VALUE_TYPE_I64:
+ GEN_INSN(STI64, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ case VALUE_TYPE_F32:
+ GEN_INSN(STF32, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ case VALUE_TYPE_F64:
+ GEN_INSN(STF64, res, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+ }
+ /* commit and clear jit frame, then jump to block func_ret */
+ gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
+ clear_values(jit_frame);
+ GEN_INSN(JMP, jit_basic_block_label(func_return));
+
+ /* translate block func_return */
+ cc->cur_basic_block = func_return;
+ if (!post_return(cc, func_type, 0, true)) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ goto fail;
+#endif
+
+ /* Clear part of memory regs and table regs as their values
+ may be changed in the function call */
+ if (cc->cur_wasm_module->possible_memory_grow)
+ clear_memory_regs(cc->jit_frame);
+ clear_table_regs(cc->jit_frame);
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+bool
+jit_compile_op_ref_null(JitCompContext *cc, uint32 ref_type)
+{
+ PUSH_I32(NEW_CONST(I32, NULL_REF));
+ (void)ref_type;
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_ref_is_null(JitCompContext *cc)
+{
+ JitReg ref, res;
+
+ POP_I32(ref);
+
+ GEN_INSN(CMP, cc->cmp_reg, ref, NEW_CONST(I32, NULL_REF));
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(SELECTEQ, res, cc->cmp_reg, NEW_CONST(I32, 1), NEW_CONST(I32, 0));
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_ref_func(JitCompContext *cc, uint32 func_idx)
+{
+ PUSH_I32(NEW_CONST(I32, func_idx));
+ return true;
+fail:
+ return false;
+}
+#endif
+
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+static bool
+emit_callnative(JitCompContext *cc, JitReg native_func_reg, JitReg res,
+ JitReg *params, uint32 param_count)
+{
+ JitInsn *insn;
+ char *i64_arg_names[] = { "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
+ char *f32_arg_names[] = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" };
+ char *f64_arg_names[] = { "xmm0_f64", "xmm1_f64", "xmm2_f64",
+ "xmm3_f64", "xmm4_f64", "xmm5_f64" };
+ JitReg i64_arg_regs[6], f32_arg_regs[6], f64_arg_regs[6], res_reg = 0;
+ JitReg eax_hreg = jit_codegen_get_hreg_by_name("eax");
+ JitReg xmm0_hreg = jit_codegen_get_hreg_by_name("xmm0");
+ uint32 i, i64_reg_idx, float_reg_idx;
+
+ bh_assert(param_count <= 6);
+
+ for (i = 0; i < 6; i++) {
+ i64_arg_regs[i] = jit_codegen_get_hreg_by_name(i64_arg_names[i]);
+ f32_arg_regs[i] = jit_codegen_get_hreg_by_name(f32_arg_names[i]);
+ f64_arg_regs[i] = jit_codegen_get_hreg_by_name(f64_arg_names[i]);
+ }
+
+ i64_reg_idx = float_reg_idx = 0;
+ for (i = 0; i < param_count; i++) {
+ switch (jit_reg_kind(params[i])) {
+ case JIT_REG_KIND_I32:
+ GEN_INSN(I32TOI64, i64_arg_regs[i64_reg_idx++], params[i]);
+ break;
+ case JIT_REG_KIND_I64:
+ GEN_INSN(MOV, i64_arg_regs[i64_reg_idx++], params[i]);
+ break;
+ case JIT_REG_KIND_F32:
+ GEN_INSN(MOV, f32_arg_regs[float_reg_idx++], params[i]);
+ break;
+ case JIT_REG_KIND_F64:
+ GEN_INSN(MOV, f64_arg_regs[float_reg_idx++], params[i]);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ if (res) {
+ switch (jit_reg_kind(res)) {
+ case JIT_REG_KIND_I32:
+ res_reg = eax_hreg;
+ break;
+ case JIT_REG_KIND_I64:
+ res_reg = res;
+ break;
+ case JIT_REG_KIND_F32:
+ res_reg = xmm0_hreg;
+ break;
+ case JIT_REG_KIND_F64:
+ res_reg = res;
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ insn = GEN_INSN(CALLNATIVE, res_reg, native_func_reg, param_count);
+ if (!insn) {
+ return false;
+ }
+
+ i64_reg_idx = float_reg_idx = 0;
+ for (i = 0; i < param_count; i++) {
+ switch (jit_reg_kind(params[i])) {
+ case JIT_REG_KIND_I32:
+ case JIT_REG_KIND_I64:
+ *(jit_insn_opndv(insn, i + 2)) = i64_arg_regs[i64_reg_idx++];
+ break;
+ case JIT_REG_KIND_F32:
+ *(jit_insn_opndv(insn, i + 2)) = f32_arg_regs[float_reg_idx++];
+ break;
+ case JIT_REG_KIND_F64:
+ *(jit_insn_opndv(insn, i + 2)) = f64_arg_regs[float_reg_idx++];
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+ }
+
+ if (res && res != res_reg) {
+ GEN_INSN(MOV, res, res_reg);
+ }
+
+ return true;
+}
+#else
+static bool
+emit_callnative(JitCompContext *cc, JitRef native_func_reg, JitReg res,
+ JitReg *params, uint32 param_count)
+{
+ JitInsn *insn;
+ uint32 i;
+
+ bh_assert(param_count <= 6);
+
+ insn = GEN_INSN(CALLNATIVE, res, native_func_reg, param_count);
+ if (!insn)
+ return false;
+
+ for (i = 0; i < param_count; i++) {
+ *(jit_insn_opndv(insn, i + 2)) = params[i];
+ }
+ return true;
+}
+#endif
+
+bool
+jit_emit_callnative(JitCompContext *cc, void *native_func, JitReg res,
+ JitReg *params, uint32 param_count)
+{
+ return emit_callnative(cc, NEW_CONST(PTR, (uintptr_t)native_func), res,
+ params, param_count);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.h
new file mode 100644
index 000000000..7405f774c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_function.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_FUNCTION_H_
+#define _JIT_EMIT_FUNCTION_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call);
+
+bool
+jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
+ uint32 tbl_idx);
+
+bool
+jit_compile_op_ref_null(JitCompContext *cc, uint32 ref_type);
+
+bool
+jit_compile_op_ref_is_null(JitCompContext *cc);
+
+bool
+jit_compile_op_ref_func(JitCompContext *cc, uint32 func_idx);
+
+bool
+jit_emit_callnative(JitCompContext *cc, void *native_func, JitReg res,
+ JitReg *params, uint32 param_count);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_FUNCTION_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.c
new file mode 100644
index 000000000..9635d4e57
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.c
@@ -0,0 +1,1200 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_memory.h"
+#include "jit_emit_exception.h"
+#include "jit_emit_function.h"
+#include "../jit_frontend.h"
+#include "../jit_codegen.h"
+#include "../../interpreter/wasm_runtime.h"
+#include "jit_emit_control.h"
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+static JitReg
+get_memory_boundary(JitCompContext *cc, uint32 mem_idx, uint32 bytes)
+{
+ JitReg memory_boundary;
+
+ switch (bytes) {
+ case 1:
+ {
+ memory_boundary =
+ get_mem_bound_check_1byte_reg(cc->jit_frame, mem_idx);
+ break;
+ }
+ case 2:
+ {
+ memory_boundary =
+ get_mem_bound_check_2bytes_reg(cc->jit_frame, mem_idx);
+ break;
+ }
+ case 4:
+ {
+ memory_boundary =
+ get_mem_bound_check_4bytes_reg(cc->jit_frame, mem_idx);
+ break;
+ }
+ case 8:
+ {
+ memory_boundary =
+ get_mem_bound_check_8bytes_reg(cc->jit_frame, mem_idx);
+ break;
+ }
+ case 16:
+ {
+ memory_boundary =
+ get_mem_bound_check_16bytes_reg(cc->jit_frame, mem_idx);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ return memory_boundary;
+fail:
+ return 0;
+}
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+static void
+set_load_or_store_atomic(JitInsn *load_or_store_inst)
+{
+ load_or_store_inst->flags_u8 |= 0x1;
+}
+#endif
+
+#if UINTPTR_MAX == UINT64_MAX
+static JitReg
+check_and_seek_on_64bit_platform(JitCompContext *cc, JitReg addr, JitReg offset,
+ JitReg memory_boundary)
+{
+ JitReg long_addr, offset1;
+
+ /* long_addr = (int64_t)addr */
+ long_addr = jit_cc_new_reg_I64(cc);
+ GEN_INSN(U32TOI64, long_addr, addr);
+
+ /* offset1 = offset + long_addr */
+ offset1 = jit_cc_new_reg_I64(cc);
+ GEN_INSN(ADD, offset1, offset, long_addr);
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ /* if (offset1 > memory_boundary) goto EXCEPTION */
+ GEN_INSN(CMP, cc->cmp_reg, offset1, memory_boundary);
+ if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BGTU,
+ cc->cmp_reg, NULL)) {
+ goto fail;
+ }
+#endif
+
+ return offset1;
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+fail:
+ return 0;
+#endif
+}
+#else
+static JitReg
+check_and_seek_on_32bit_platform(JitCompContext *cc, JitReg addr, JitReg offset,
+ JitReg memory_boundary)
+{
+ JitReg offset1;
+
+ /* offset1 = offset + addr */
+ offset1 = jit_cc_new_reg_I32(cc);
+ GEN_INSN(ADD, offset1, offset, addr);
+
+ /* if (offset1 < addr) goto EXCEPTION */
+ GEN_INSN(CMP, cc->cmp_reg, offset1, addr);
+ if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BLTU,
+ cc->cmp_reg, NULL)) {
+ goto fail;
+ }
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ /* if (offset1 > memory_boundary) goto EXCEPTION */
+ GEN_INSN(CMP, cc->cmp_reg, offset1, memory_boundary);
+ if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BGTU,
+ cc->cmp_reg, NULL)) {
+ goto fail;
+ }
+#endif
+
+ return offset1;
+fail:
+ return 0;
+}
+#endif
+
+static JitReg
+check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
+{
+ JitReg memory_boundary = 0, offset1;
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ /* the default memory */
+ uint32 mem_idx = 0;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ /* ---------- check ---------- */
+ /* 1. shortcut if the memory size is 0 */
+ if (cc->cur_wasm_module->memories != NULL
+ && 0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) {
+ JitReg module_inst, cur_page_count;
+ uint32 cur_page_count_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, cur_page_count);
+
+ /* if (cur_mem_page_count == 0) goto EXCEPTION */
+ module_inst = get_module_inst_reg(cc->jit_frame);
+ cur_page_count = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, cur_page_count, module_inst,
+ NEW_CONST(I32, cur_page_count_offset));
+ GEN_INSN(CMP, cc->cmp_reg, cur_page_count, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
+ JIT_OP_BEQ, cc->cmp_reg, NULL)) {
+ goto fail;
+ }
+ }
+
+ /* 2. a complete boundary check */
+ memory_boundary = get_memory_boundary(cc, mem_idx, bytes);
+ if (!memory_boundary)
+ goto fail;
+#endif
+
+#if UINTPTR_MAX == UINT64_MAX
+ offset1 = check_and_seek_on_64bit_platform(cc, addr, NEW_CONST(I64, offset),
+ memory_boundary);
+ if (!offset1)
+ goto fail;
+#else
+ offset1 = check_and_seek_on_32bit_platform(cc, addr, NEW_CONST(I32, offset),
+ memory_boundary);
+ if (!offset1)
+ goto fail;
+#endif
+
+ return offset1;
+fail:
+ return 0;
+}
+
+#if UINTPTR_MAX == UINT64_MAX
+#define CHECK_ALIGNMENT(offset1) \
+ do { \
+ JitReg align_mask = NEW_CONST(I64, ((uint64)1 << align) - 1); \
+ JitReg AND_res = jit_cc_new_reg_I64(cc); \
+ GEN_INSN(AND, AND_res, offset1, align_mask); \
+ GEN_INSN(CMP, cc->cmp_reg, AND_res, NEW_CONST(I64, 0)); \
+ if (!jit_emit_exception(cc, EXCE_UNALIGNED_ATOMIC, JIT_OP_BNE, \
+ cc->cmp_reg, NULL)) \
+ goto fail; \
+ } while (0)
+#else
+#define CHECK_ALIGNMENT(offset1) \
+ do { \
+ JitReg align_mask = NEW_CONST(I32, (1 << align) - 1); \
+ JitReg AND_res = jit_cc_new_reg_I32(cc); \
+ GEN_INSN(AND, AND_res, offset1, align_mask); \
+ GEN_INSN(CMP, cc->cmp_reg, AND_res, NEW_CONST(I32, 0)); \
+ if (!jit_emit_exception(cc, EXCE_UNALIGNED_ATOMIC, JIT_OP_BNE, \
+ cc->cmp_reg, NULL)) \
+ goto fail; \
+ } while (0)
+#endif
+
+bool
+jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool sign, bool atomic)
+{
+ JitReg addr, offset1, value, memory_data;
+ JitInsn *load_insn = NULL;
+
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1) {
+ goto fail;
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic) {
+ CHECK_ALIGNMENT(offset1);
+ }
+#endif
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ value = jit_cc_new_reg_I32(cc);
+ switch (bytes) {
+ case 1:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI8, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU8, value, memory_data, offset1);
+ }
+ break;
+ }
+ case 2:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI16, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU16, value, memory_data, offset1);
+ }
+ break;
+ }
+ case 4:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI32, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU32, value, memory_data, offset1);
+ }
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic && load_insn)
+ set_load_or_store_atomic(load_insn);
+#else
+ (void)load_insn;
+#endif
+
+ PUSH_I32(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_load(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool sign, bool atomic)
+{
+ JitReg addr, offset1, value, memory_data;
+ JitInsn *load_insn = NULL;
+
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1) {
+ goto fail;
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic) {
+ CHECK_ALIGNMENT(offset1);
+ }
+#endif
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ value = jit_cc_new_reg_I64(cc);
+ switch (bytes) {
+ case 1:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI8, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU8, value, memory_data, offset1);
+ }
+ break;
+ }
+ case 2:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI16, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU16, value, memory_data, offset1);
+ }
+ break;
+ }
+ case 4:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI32, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU32, value, memory_data, offset1);
+ }
+ break;
+ }
+ case 8:
+ {
+ if (sign) {
+ load_insn = GEN_INSN(LDI64, value, memory_data, offset1);
+ }
+ else {
+ load_insn = GEN_INSN(LDU64, value, memory_data, offset1);
+ }
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic && load_insn)
+ set_load_or_store_atomic(load_insn);
+#else
+ (void)load_insn;
+#endif
+
+ PUSH_I64(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_load(JitCompContext *cc, uint32 align, uint32 offset)
+{
+ JitReg addr, offset1, value, memory_data;
+
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, 4);
+ if (!offset1) {
+ goto fail;
+ }
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ value = jit_cc_new_reg_F32(cc);
+ GEN_INSN(LDF32, value, memory_data, offset1);
+
+ PUSH_F32(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_load(JitCompContext *cc, uint32 align, uint32 offset)
+{
+ JitReg addr, offset1, value, memory_data;
+
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, 8);
+ if (!offset1) {
+ goto fail;
+ }
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ value = jit_cc_new_reg_F64(cc);
+ GEN_INSN(LDF64, value, memory_data, offset1);
+
+ PUSH_F64(value);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_store(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool atomic)
+{
+ JitReg value, addr, offset1, memory_data;
+ JitInsn *store_insn = NULL;
+
+ POP_I32(value);
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1) {
+ goto fail;
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic) {
+ CHECK_ALIGNMENT(offset1);
+ }
+#endif
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ switch (bytes) {
+ case 1:
+ {
+ store_insn = GEN_INSN(STI8, value, memory_data, offset1);
+ break;
+ }
+ case 2:
+ {
+ store_insn = GEN_INSN(STI16, value, memory_data, offset1);
+ break;
+ }
+ case 4:
+ {
+ store_insn = GEN_INSN(STI32, value, memory_data, offset1);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic && store_insn)
+ set_load_or_store_atomic(store_insn);
+#else
+ (void)store_insn;
+#endif
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_store(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool atomic)
+{
+ JitReg value, addr, offset1, memory_data;
+ JitInsn *store_insn = NULL;
+
+ POP_I64(value);
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1) {
+ goto fail;
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic) {
+ CHECK_ALIGNMENT(offset1);
+ }
+#endif
+
+ if (jit_reg_is_const(value) && bytes < 8) {
+ value = NEW_CONST(I32, (int32)jit_cc_get_const_I64(cc, value));
+ }
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ switch (bytes) {
+ case 1:
+ {
+ store_insn = GEN_INSN(STI8, value, memory_data, offset1);
+ break;
+ }
+ case 2:
+ {
+ store_insn = GEN_INSN(STI16, value, memory_data, offset1);
+ break;
+ }
+ case 4:
+ {
+ store_insn = GEN_INSN(STI32, value, memory_data, offset1);
+ break;
+ }
+ case 8:
+ {
+ store_insn = GEN_INSN(STI64, value, memory_data, offset1);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (atomic && store_insn)
+ set_load_or_store_atomic(store_insn);
+#else
+ (void)store_insn;
+#endif
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_store(JitCompContext *cc, uint32 align, uint32 offset)
+{
+ JitReg value, addr, offset1, memory_data;
+
+ POP_F32(value);
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, 4);
+ if (!offset1) {
+ goto fail;
+ }
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ GEN_INSN(STF32, value, memory_data, offset1);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_store(JitCompContext *cc, uint32 align, uint32 offset)
+{
+ JitReg value, addr, offset1, memory_data;
+
+ POP_F64(value);
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, 8);
+ if (!offset1) {
+ goto fail;
+ }
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ GEN_INSN(STF64, value, memory_data, offset1);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_memory_size(JitCompContext *cc, uint32 mem_idx)
+{
+ JitReg module_inst, cur_page_count;
+ uint32 cur_page_count_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, cur_page_count);
+
+ module_inst = get_module_inst_reg(cc->jit_frame);
+ cur_page_count = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, cur_page_count, module_inst,
+ NEW_CONST(I32, cur_page_count_offset));
+
+ PUSH_I32(cur_page_count);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx)
+{
+ JitReg module_inst, grow_res, res;
+ JitReg prev_page_count, inc_page_count, args[2];
+
+ /* Get current page count */
+ uint32 cur_page_count_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, cur_page_count);
+
+ module_inst = get_module_inst_reg(cc->jit_frame);
+ prev_page_count = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, prev_page_count, module_inst,
+ NEW_CONST(I32, cur_page_count_offset));
+
+ /* Call wasm_enlarge_memory */
+ POP_I32(inc_page_count);
+
+ grow_res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = inc_page_count;
+
+ if (!jit_emit_callnative(cc, wasm_enlarge_memory, grow_res, args, 2)) {
+ goto fail;
+ }
+ /* Convert bool to uint32 */
+ GEN_INSN(AND, grow_res, grow_res, NEW_CONST(I32, 0xFF));
+
+ /* return different values according to memory.grow result */
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(CMP, cc->cmp_reg, grow_res, NEW_CONST(I32, 0));
+ GEN_INSN(SELECTNE, res, cc->cmp_reg, prev_page_count,
+ NEW_CONST(I32, (int32)-1));
+ PUSH_I32(res);
+
+ /* Ensure a refresh in next get memory related registers */
+ clear_memory_regs(cc->jit_frame);
+
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+static int
+wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
+ uint32 len, uint32 mem_offset, uint32 data_offset)
+{
+ WASMMemoryInstance *mem_inst;
+ WASMDataSeg *data_segment;
+ uint32 mem_size;
+ uint8 *mem_addr, *data_addr;
+
+ /* if d + n > the length of mem.data */
+ mem_inst = inst->memories[mem_idx];
+ mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page;
+ if (mem_size < mem_offset || mem_size - mem_offset < len)
+ goto out_of_bounds;
+
+ /* if s + n > the length of data.data */
+ bh_assert(seg_idx < inst->module->data_seg_count);
+ data_segment = inst->module->data_segments[seg_idx];
+ if (data_segment->data_length < data_offset
+ || data_segment->data_length - data_offset < len)
+ goto out_of_bounds;
+
+ mem_addr = mem_inst->memory_data + mem_offset;
+ data_addr = data_segment->data + data_offset;
+ bh_memcpy_s(mem_addr, mem_size - mem_offset, data_addr, len);
+
+ return 0;
+out_of_bounds:
+ wasm_set_exception(inst, "out of bounds memory access");
+ return -1;
+}
+
+bool
+jit_compile_op_memory_init(JitCompContext *cc, uint32 mem_idx, uint32 seg_idx)
+{
+ JitReg len, mem_offset, data_offset, res;
+ JitReg args[6] = { 0 };
+
+ POP_I32(len);
+ POP_I32(data_offset);
+ POP_I32(mem_offset);
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, mem_idx);
+ args[2] = NEW_CONST(I32, seg_idx);
+ args[3] = len;
+ args[4] = mem_offset;
+ args[5] = data_offset;
+
+ if (!jit_emit_callnative(cc, wasm_init_memory, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx)
+{
+ JitReg module = get_module_reg(cc->jit_frame);
+ JitReg data_segments = jit_cc_new_reg_ptr(cc);
+ JitReg data_segment = jit_cc_new_reg_ptr(cc);
+
+ GEN_INSN(LDPTR, data_segments, module,
+ NEW_CONST(I32, offsetof(WASMModule, data_segments)));
+ GEN_INSN(LDPTR, data_segment, data_segments,
+ NEW_CONST(I32, seg_idx * sizeof(WASMDataSeg *)));
+ GEN_INSN(STI32, NEW_CONST(I32, 0), data_segment,
+ NEW_CONST(I32, offsetof(WASMDataSeg, data_length)));
+
+ return true;
+}
+
+static int
+wasm_copy_memory(WASMModuleInstance *inst, uint32 src_mem_idx,
+ uint32 dst_mem_idx, uint32 len, uint32 src_offset,
+ uint32 dst_offset)
+{
+ WASMMemoryInstance *src_mem, *dst_mem;
+ uint32 src_mem_size, dst_mem_size;
+ uint8 *src_addr, *dst_addr;
+
+ src_mem = inst->memories[src_mem_idx];
+ dst_mem = inst->memories[dst_mem_idx];
+ src_mem_size = src_mem->cur_page_count * src_mem->num_bytes_per_page;
+ dst_mem_size = dst_mem->cur_page_count * dst_mem->num_bytes_per_page;
+
+ /* if s + n > the length of mem.data */
+ if (src_mem_size < src_offset || src_mem_size - src_offset < len)
+ goto out_of_bounds;
+
+ /* if d + n > the length of mem.data */
+ if (dst_mem_size < dst_offset || dst_mem_size - dst_offset < len)
+ goto out_of_bounds;
+
+ src_addr = src_mem->memory_data + src_offset;
+ dst_addr = dst_mem->memory_data + dst_offset;
+ /* allowing the destination and source to overlap */
+ bh_memmove_s(dst_addr, dst_mem_size - dst_offset, src_addr, len);
+
+ return 0;
+out_of_bounds:
+ wasm_set_exception(inst, "out of bounds memory access");
+ return -1;
+}
+
+bool
+jit_compile_op_memory_copy(JitCompContext *cc, uint32 src_mem_idx,
+ uint32 dst_mem_idx)
+{
+ JitReg len, src, dst, res;
+ JitReg args[6] = { 0 };
+
+ POP_I32(len);
+ POP_I32(src);
+ POP_I32(dst);
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, src_mem_idx);
+ args[2] = NEW_CONST(I32, dst_mem_idx);
+ args[3] = len;
+ args[4] = src;
+ args[5] = dst;
+
+ if (!jit_emit_callnative(cc, wasm_copy_memory, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+
+static int
+wasm_fill_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 len,
+ uint32 val, uint32 dst)
+{
+ WASMMemoryInstance *mem_inst;
+ uint32 mem_size;
+ uint8 *dst_addr;
+
+ mem_inst = inst->memories[mem_idx];
+ mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page;
+
+ if (mem_size < dst || mem_size - dst < len)
+ goto out_of_bounds;
+
+ dst_addr = mem_inst->memory_data + dst;
+ memset(dst_addr, val, len);
+
+ return 0;
+out_of_bounds:
+ wasm_set_exception(inst, "out of bounds memory access");
+ return -1;
+}
+
+bool
+jit_compile_op_memory_fill(JitCompContext *cc, uint32 mem_idx)
+{
+ JitReg res, len, val, dst;
+ JitReg args[5] = { 0 };
+
+ POP_I32(len);
+ POP_I32(val);
+ POP_I32(dst);
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, mem_idx);
+ args[2] = len;
+ args[3] = val;
+ args[4] = dst;
+
+ if (!jit_emit_callnative(cc, wasm_fill_memory, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#define GEN_AT_RMW_INSN(op, op_type, bytes, result, value, memory_data, \
+ offset1) \
+ do { \
+ switch (bytes) { \
+ case 1: \
+ { \
+ insn = GEN_INSN(AT_##op##U8, result, value, memory_data, \
+ offset1); \
+ break; \
+ } \
+ case 2: \
+ { \
+ insn = GEN_INSN(AT_##op##U16, result, value, memory_data, \
+ offset1); \
+ break; \
+ } \
+ case 4: \
+ { \
+ if (op_type == VALUE_TYPE_I32) \
+ insn = GEN_INSN(AT_##op##I32, result, value, memory_data, \
+ offset1); \
+ else \
+ insn = GEN_INSN(AT_##op##U32, result, value, memory_data, \
+ offset1); \
+ break; \
+ } \
+ case 8: \
+ { \
+ insn = GEN_INSN(AT_##op##I64, result, value, memory_data, \
+ offset1); \
+ break; \
+ } \
+ default: \
+ { \
+ bh_assert(0); \
+ goto fail; \
+ } \
+ } \
+ } while (0)
+
+bool
+jit_compile_op_atomic_rmw(JitCompContext *cc, uint8 atomic_op, uint8 op_type,
+ uint32 align, uint32 offset, uint32 bytes)
+{
+ JitReg addr, offset1, memory_data, value, result, eax_hreg, rax_hreg,
+ ebx_hreg, rbx_hreg;
+ JitInsn *insn = NULL;
+ bool is_i32 = op_type == VALUE_TYPE_I32;
+ bool is_logical_op = atomic_op == AtomicRMWBinOpAnd
+ || atomic_op == AtomicRMWBinOpOr
+ || atomic_op == AtomicRMWBinOpXor;
+
+ /* currently we only implement atomic rmw on x86-64 target */
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+
+ /* For atomic logical binary ops, it implicitly uses rax in cmpxchg
+ * instruction and implicitly uses rbx for storing temp value in the
+ * generated loop */
+ eax_hreg = jit_codegen_get_hreg_by_name("eax");
+ rax_hreg = jit_codegen_get_hreg_by_name("rax");
+ ebx_hreg = jit_codegen_get_hreg_by_name("ebx");
+ rbx_hreg = jit_codegen_get_hreg_by_name("rbx");
+
+ bh_assert(op_type == VALUE_TYPE_I32 || op_type == VALUE_TYPE_I64);
+ if (op_type == VALUE_TYPE_I32) {
+ POP_I32(value);
+ }
+ else {
+ POP_I64(value);
+ }
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1) {
+ goto fail;
+ }
+ CHECK_ALIGNMENT(offset1);
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ if (op_type == VALUE_TYPE_I32)
+ result = jit_cc_new_reg_I32(cc);
+ else
+ result = jit_cc_new_reg_I64(cc);
+
+ switch (atomic_op) {
+ case AtomicRMWBinOpAdd:
+ {
+ GEN_AT_RMW_INSN(ADD, op_type, bytes, result, value, memory_data,
+ offset1);
+ break;
+ }
+ case AtomicRMWBinOpSub:
+ {
+ GEN_AT_RMW_INSN(SUB, op_type, bytes, result, value, memory_data,
+ offset1);
+ break;
+ }
+ case AtomicRMWBinOpAnd:
+ {
+ GEN_AT_RMW_INSN(AND, op_type, bytes, result, value, memory_data,
+ offset1);
+ break;
+ }
+ case AtomicRMWBinOpOr:
+ {
+ GEN_AT_RMW_INSN(OR, op_type, bytes, result, value, memory_data,
+ offset1);
+ break;
+ }
+ case AtomicRMWBinOpXor:
+ {
+ GEN_AT_RMW_INSN(XOR, op_type, bytes, result, value, memory_data,
+ offset1);
+ break;
+ }
+ case AtomicRMWBinOpXchg:
+ {
+ GEN_AT_RMW_INSN(XCHG, op_type, bytes, result, value, memory_data,
+ offset1);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ if (is_logical_op
+ && (!insn
+ || !jit_lock_reg_in_insn(cc, insn, is_i32 ? eax_hreg : rax_hreg)
+ || !jit_lock_reg_in_insn(cc, insn, is_i32 ? ebx_hreg : rbx_hreg))) {
+ jit_set_last_error(
+ cc, "generate atomic logical insn or lock ra&rb hreg failed");
+ goto fail;
+ }
+
+ if (op_type == VALUE_TYPE_I32)
+ PUSH_I32(result);
+ else
+ PUSH_I64(result);
+
+ return true;
+#endif /* defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
+
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_atomic_cmpxchg(JitCompContext *cc, uint8 op_type, uint32 align,
+ uint32 offset, uint32 bytes)
+{
+ JitReg addr, offset1, memory_data, value, expect, result;
+ bool is_i32 = op_type == VALUE_TYPE_I32;
+ /* currently we only implement atomic cmpxchg on x86-64 target */
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ /* cmpxchg will use register al/ax/eax/rax to store parameter expected
+ * value, and the read result will also be stored to al/ax/eax/rax */
+ JitReg eax_hreg = jit_codegen_get_hreg_by_name("eax");
+ JitReg rax_hreg = jit_codegen_get_hreg_by_name("rax");
+ JitInsn *insn = NULL;
+
+ bh_assert(op_type == VALUE_TYPE_I32 || op_type == VALUE_TYPE_I64);
+ if (is_i32) {
+ POP_I32(value);
+ POP_I32(expect);
+ result = jit_cc_new_reg_I32(cc);
+ }
+ else {
+ POP_I64(value);
+ POP_I64(expect);
+ result = jit_cc_new_reg_I64(cc);
+ }
+ POP_I32(addr);
+
+ offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1) {
+ goto fail;
+ }
+ CHECK_ALIGNMENT(offset1);
+
+ memory_data = get_memory_data_reg(cc->jit_frame, 0);
+
+ GEN_INSN(MOV, is_i32 ? eax_hreg : rax_hreg, expect);
+ switch (bytes) {
+ case 1:
+ {
+ insn = GEN_INSN(AT_CMPXCHGU8, value, is_i32 ? eax_hreg : rax_hreg,
+ memory_data, offset1);
+ break;
+ }
+ case 2:
+ {
+ insn = GEN_INSN(AT_CMPXCHGU16, value, is_i32 ? eax_hreg : rax_hreg,
+ memory_data, offset1);
+ break;
+ }
+ case 4:
+ {
+ if (op_type == VALUE_TYPE_I32)
+ insn =
+ GEN_INSN(AT_CMPXCHGI32, value, is_i32 ? eax_hreg : rax_hreg,
+ memory_data, offset1);
+ else
+ insn =
+ GEN_INSN(AT_CMPXCHGU32, value, is_i32 ? eax_hreg : rax_hreg,
+ memory_data, offset1);
+ break;
+ }
+ case 8:
+ {
+ insn = GEN_INSN(AT_CMPXCHGI64, value, is_i32 ? eax_hreg : rax_hreg,
+ memory_data, offset1);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ if (!insn
+ || !jit_lock_reg_in_insn(cc, insn, is_i32 ? eax_hreg : rax_hreg)) {
+ jit_set_last_error(cc, "generate cmpxchg insn or lock ra hreg failed");
+ goto fail;
+ }
+
+ GEN_INSN(MOV, result, is_i32 ? eax_hreg : rax_hreg);
+
+ if (is_i32)
+ PUSH_I32(result);
+ else
+ PUSH_I64(result);
+
+ return true;
+#endif /* defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
+
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
+ uint32 offset, uint32 bytes)
+{
+ bh_assert(op_type == VALUE_TYPE_I32 || op_type == VALUE_TYPE_I64);
+
+ // Pop atomic.wait arguments
+ JitReg timeout, expect, expect_64, addr;
+ POP_I64(timeout);
+ if (op_type == VALUE_TYPE_I32) {
+ POP_I32(expect);
+ expect_64 = jit_cc_new_reg_I64(cc);
+ GEN_INSN(I32TOI64, expect_64, expect);
+ }
+ else {
+ POP_I64(expect_64);
+ }
+ POP_I32(addr);
+
+ // Get referenced address and store it in `maddr`
+ JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0);
+ JitReg offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1)
+ goto fail;
+ CHECK_ALIGNMENT(offset1);
+
+ JitReg maddr = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(ADD, maddr, memory_data, offset1);
+
+ // Prepare `wasm_runtime_atomic_wait` arguments
+ JitReg res = jit_cc_new_reg_I32(cc);
+ JitReg args[5] = { 0 };
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = maddr;
+ args[2] = expect_64;
+ args[3] = timeout;
+ args[4] = NEW_CONST(I32, false);
+
+ if (!jit_emit_callnative(cc, wasm_runtime_atomic_wait, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ // Handle return code
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, -1));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ PUSH_I32(res);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (!jit_check_suspend_flags(cc))
+ goto fail;
+#endif
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes)
+{
+ // Pop atomic.notify arguments
+ JitReg notify_count, addr;
+ POP_I32(notify_count);
+ POP_I32(addr);
+
+ // Get referenced address and store it in `maddr`
+ JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0);
+ JitReg offset1 = check_and_seek(cc, addr, offset, bytes);
+ if (!offset1)
+ goto fail;
+ CHECK_ALIGNMENT(offset1);
+
+ JitReg maddr = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(ADD, maddr, memory_data, offset1);
+
+ // Prepare `wasm_runtime_atomic_notify` arguments
+ JitReg res = jit_cc_new_reg_I32(cc);
+ JitReg args[3] = { 0 };
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = maddr;
+ args[2] = notify_count;
+
+ if (!jit_emit_callnative(cc, wasm_runtime_atomic_notify, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ // Handle return code
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ PUSH_I32(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compiler_op_atomic_fence(JitCompContext *cc)
+{
+ GEN_INSN(FENCE);
+ return true;
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.h
new file mode 100644
index 000000000..6565cdc11
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_memory.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_MEMORY_H_
+#define _JIT_EMIT_MEMORY_H_
+
+#include "../jit_compiler.h"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "../../common/wasm_shared_memory.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool sign, bool atomic);
+
+bool
+jit_compile_op_i64_load(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool sign, bool atomic);
+
+bool
+jit_compile_op_f32_load(JitCompContext *cc, uint32 align, uint32 offset);
+
+bool
+jit_compile_op_f64_load(JitCompContext *cc, uint32 align, uint32 offset);
+
+bool
+jit_compile_op_i32_store(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool atomic);
+
+bool
+jit_compile_op_i64_store(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes, bool atomic);
+
+bool
+jit_compile_op_f32_store(JitCompContext *cc, uint32 align, uint32 offset);
+
+bool
+jit_compile_op_f64_store(JitCompContext *cc, uint32 align, uint32 offset);
+
+bool
+jit_compile_op_memory_size(JitCompContext *cc, uint32 mem_idx);
+
+bool
+jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+jit_compile_op_memory_init(JitCompContext *cc, uint32 mem_idx, uint32 seg_idx);
+
+bool
+jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx);
+
+bool
+jit_compile_op_memory_copy(JitCompContext *cc, uint32 src_mem_idx,
+ uint32 dst_mem_idx);
+
+bool
+jit_compile_op_memory_fill(JitCompContext *cc, uint32 mem_idx);
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+jit_compile_op_atomic_rmw(JitCompContext *cc, uint8 atomic_op, uint8 op_type,
+ uint32 align, uint32 offset, uint32 bytes);
+
+bool
+jit_compile_op_atomic_cmpxchg(JitCompContext *cc, uint8 op_type, uint32 align,
+ uint32 offset, uint32 bytes);
+
+bool
+jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
+ uint32 offset, uint32 bytes);
+
+bool
+jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
+ uint32 bytes);
+
+bool
+jit_compiler_op_atomic_fence(JitCompContext *cc);
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_MEMORY_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.c
new file mode 100644
index 000000000..03491e691
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.c
@@ -0,0 +1,1707 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_numberic.h"
+#include "jit_emit_exception.h"
+#include "jit_emit_control.h"
+#include "jit_emit_function.h"
+#include "../jit_frontend.h"
+#include "../jit_codegen.h"
+
+#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 { \
+ JitReg res, operand; \
+ POP_INT(operand); \
+ if (!(res = op)) { \
+ if (err) \
+ jit_set_last_error(cc, err); \
+ goto fail; \
+ } \
+ PUSH_INT(res); \
+ } while (0)
+
+#define DEF_INT_BINARY_OP(op, err) \
+ do { \
+ JitReg res, left, right; \
+ POP_INT(right); \
+ POP_INT(left); \
+ if (!(res = op)) { \
+ if (err) \
+ jit_set_last_error(cc, err); \
+ goto fail; \
+ } \
+ PUSH_INT(res); \
+ } while (0)
+
+#define DEF_FP_UNARY_OP(op, err) \
+ do { \
+ JitReg res, operand; \
+ POP_FLOAT(operand); \
+ if (!(res = op)) { \
+ if (err) \
+ jit_set_last_error(cc, err); \
+ goto fail; \
+ } \
+ PUSH_FLOAT(res); \
+ } while (0)
+
+#define DEF_FP_BINARY_OP(op, err) \
+ do { \
+ JitReg res, left, right; \
+ POP_FLOAT(right); \
+ POP_FLOAT(left); \
+ if (!(res = op)) { \
+ if (err) \
+ jit_set_last_error(cc, err); \
+ goto fail; \
+ } \
+ PUSH_FLOAT(res); \
+ } while (0)
+
+static uint32
+clz32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 0x80000000)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+static uint64
+clz64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 0x8000000000000000LL)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+static uint32
+ctz32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+static uint64
+ctz64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+static uint32
+popcnt32(uint32 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+static uint64
+popcnt64(uint64 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+bool
+jit_compile_op_i32_clz(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I32(value);
+ if (jit_reg_is_const(value)) {
+ uint32 i32 = jit_cc_get_const_I32(cc, value);
+ PUSH_I32(NEW_CONST(I32, clz32(i32)));
+ return true;
+ }
+
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(CLZ, res, value);
+ PUSH_I32(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_ctz(JitCompContext *cc)
+{
+ JitReg value, res = jit_cc_new_reg_I32(cc);
+
+ POP_I32(value);
+ if (jit_reg_is_const(value)) {
+ uint32 i32 = jit_cc_get_const_I32(cc, value);
+ PUSH_I32(NEW_CONST(I32, ctz32(i32)));
+ return true;
+ }
+
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(CTZ, res, value);
+ PUSH_I32(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_popcnt(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I32(value);
+ if (jit_reg_is_const(value)) {
+ uint32 i32 = jit_cc_get_const_I32(cc, value);
+ PUSH_I32(NEW_CONST(I32, popcnt32(i32)));
+ return true;
+ }
+
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(POPCNT, res, value);
+ PUSH_I32(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_clz(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I64(value);
+ if (jit_reg_is_const(value)) {
+ uint64 i64 = jit_cc_get_const_I64(cc, value);
+ PUSH_I64(NEW_CONST(I64, clz64(i64)));
+ return true;
+ }
+
+ res = jit_cc_new_reg_I64(cc);
+ GEN_INSN(CLZ, res, value);
+ PUSH_I64(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_ctz(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I64(value);
+ if (jit_reg_is_const(value)) {
+ uint64 i64 = jit_cc_get_const_I64(cc, value);
+ PUSH_I64(NEW_CONST(I64, ctz64(i64)));
+ return true;
+ }
+
+ res = jit_cc_new_reg_I64(cc);
+ GEN_INSN(CTZ, res, value);
+ PUSH_I64(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i64_popcnt(JitCompContext *cc)
+{
+ JitReg value, res;
+
+ POP_I64(value);
+ if (jit_reg_is_const(value)) {
+ uint64 i64 = jit_cc_get_const_I64(cc, value);
+ PUSH_I64(NEW_CONST(I64, popcnt64(i64)));
+ return true;
+ }
+
+ res = jit_cc_new_reg_I64(cc);
+ GEN_INSN(POPCNT, res, value);
+ PUSH_I64(res);
+ return true;
+fail:
+ return false;
+}
+
+#define IS_CONST_ALL_ONE(val, is_i32) \
+ (jit_reg_is_const(val) \
+ && ((is_i32 && jit_cc_get_const_I32(cc, val) == -1) \
+ || (!is_i32 && jit_cc_get_const_I64(cc, val) == -1LL)))
+
+#define IS_CONST_ZERO(val) \
+ (jit_reg_is_const(val) \
+ && ((is_i32 && jit_cc_get_const_I32(cc, val) == 0) \
+ || (!is_i32 && jit_cc_get_const_I64(cc, val) == 0)))
+
+/* macros for integer binary operations (ibinop) */
+
+#define __DEF_BI_INT_CONST_OPS(bits, opname, op) \
+ static int##bits do_i##bits##_const_##opname(int##bits lhs, int##bits rhs) \
+ { \
+ return lhs op rhs; \
+ }
+
+#define DEF_BI_INT_CONST_OPS(opname, op) \
+ __DEF_BI_INT_CONST_OPS(32, opname, op) \
+ __DEF_BI_INT_CONST_OPS(64, opname, op)
+
+#define DEF_UNI_INT_CONST_OPS(opname) \
+ static JitReg compile_int_##opname##_consts( \
+ JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+
+typedef JitReg (*uni_const_handler)(JitCompContext *, JitReg, JitReg, bool);
+typedef int32 (*bin_i32_consts_handler)(int32, int32);
+typedef int64 (*bin_i64_consts_handler)(int64, int64);
+
+/* ibinopt for integer binary operations */
+static JitReg
+compile_op_ibinopt_const(JitCompContext *cc, JitReg left, JitReg right,
+ bool is_i32, uni_const_handler handle_one_const,
+ bin_i32_consts_handler handle_two_i32_const,
+ bin_i64_consts_handler handle_two_i64_const)
+{
+ JitReg res;
+
+ if (jit_reg_is_const(left) && jit_reg_is_const(right)) {
+ if (is_i32) {
+ int32 left_val = jit_cc_get_const_I32(cc, left);
+ int32 right_val = jit_cc_get_const_I32(cc, right);
+ res = NEW_CONST(I32, handle_two_i32_const(left_val, right_val));
+ }
+ else {
+ int64 left_val = jit_cc_get_const_I64(cc, left);
+ int64 right_val = jit_cc_get_const_I64(cc, right);
+ res = NEW_CONST(I64, handle_two_i64_const(left_val, right_val));
+ }
+ goto shortcut;
+ }
+
+ if (jit_reg_is_const(left) || jit_reg_is_const(right)) {
+ res = handle_one_const(cc, left, right, is_i32);
+ if (res)
+ goto shortcut;
+ }
+
+ return 0;
+shortcut:
+ return res;
+}
+
+#define CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, opname) \
+ compile_op_ibinopt_const(cc, left, right, is_i32, \
+ compile_int_##opname##_consts, \
+ do_i32_const_##opname, do_i64_const_##opname)
+
+DEF_UNI_INT_CONST_OPS(add)
+{
+ /* 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;
+
+ return 0;
+}
+
+DEF_BI_INT_CONST_OPS(add, +)
+
+static JitReg
+compile_int_add(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, add);
+ if (res)
+ goto shortcut;
+
+ /* Build add */
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(ADD, res, left, right);
+
+shortcut:
+ return res;
+}
+
+DEF_UNI_INT_CONST_OPS(sub)
+{
+ /* If the right operand is 0, just return the left */
+ if (IS_CONST_ZERO(right))
+ return left;
+
+ return 0;
+}
+
+DEF_BI_INT_CONST_OPS(sub, -)
+
+static JitReg
+compile_int_sub(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, sub);
+ if (res)
+ goto shortcut;
+
+ /* Build sub */
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(SUB, res, left, right);
+
+shortcut:
+ return res;
+}
+
+DEF_UNI_INT_CONST_OPS(mul)
+{
+ /* If one of the operands is 0, just return constant 0 */
+ if (IS_CONST_ZERO(left) || IS_CONST_ZERO(right))
+ return is_i32 ? NEW_CONST(I32, 0) : NEW_CONST(I64, 0);
+
+ return 0;
+}
+
+static int32
+do_i32_const_mul(int32 lhs, int32 rhs)
+{
+ return (int32)((uint64)lhs * (uint64)rhs);
+}
+
+static int64
+do_i64_const_mul(int64 lhs, int64 rhs)
+{
+ return (int64)((uint64)lhs * (uint64)rhs);
+}
+
+static JitReg
+compile_int_mul(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, mul);
+ if (res)
+ goto shortcut;
+
+ /* Build mul */
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(MUL, res, left, right);
+
+shortcut:
+ return res;
+}
+
+static bool
+compile_int_div_no_check(JitCompContext *cc, IntArithmetic arith_op,
+ bool is_i32, JitReg left, JitReg right, JitReg res)
+{
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ JitReg eax_hreg = jit_codegen_get_hreg_by_name("eax");
+ JitReg edx_hreg = jit_codegen_get_hreg_by_name("edx");
+ JitReg rax_hreg = jit_codegen_get_hreg_by_name("rax");
+ JitReg rdx_hreg = jit_codegen_get_hreg_by_name("rdx");
+#endif
+
+ if (jit_reg_is_const(right) && jit_reg_is_const(left)) {
+ if (INT_DIV_S == arith_op || INT_REM_S == arith_op) {
+ if (is_i32) {
+ int32 lhs = jit_cc_get_const_I32(cc, left);
+ int32 rhs = jit_cc_get_const_I32(cc, right);
+ if (INT_DIV_S == arith_op) {
+ res = NEW_CONST(I32, lhs / rhs);
+ }
+ else {
+ res = NEW_CONST(I32, lhs % rhs);
+ }
+ PUSH_I32(res);
+ return true;
+ }
+ else {
+ int64 lhs = jit_cc_get_const_I64(cc, left);
+ int64 rhs = jit_cc_get_const_I64(cc, right);
+ if (INT_DIV_S == arith_op) {
+ res = NEW_CONST(I64, lhs / rhs);
+ }
+ else {
+ res = NEW_CONST(I64, lhs % rhs);
+ }
+ PUSH_I64(res);
+ return true;
+ }
+ }
+ else {
+ if (is_i32) {
+ uint32 lhs = (uint32)jit_cc_get_const_I32(cc, left);
+ uint32 rhs = (uint32)jit_cc_get_const_I32(cc, right);
+ if (INT_DIV_U == arith_op) {
+ res = NEW_CONST(I32, lhs / rhs);
+ }
+ else {
+ res = NEW_CONST(I32, lhs % rhs);
+ }
+ PUSH_I32(res);
+ return true;
+ }
+ else {
+ uint64 lhs = (uint64)jit_cc_get_const_I64(cc, left);
+ uint64 rhs = (uint64)jit_cc_get_const_I64(cc, right);
+ if (INT_DIV_U == arith_op) {
+ res = NEW_CONST(I64, lhs / rhs);
+ }
+ else {
+ res = NEW_CONST(I64, lhs % rhs);
+ }
+ PUSH_I64(res);
+ return true;
+ }
+ }
+ }
+
+ switch (arith_op) {
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ case INT_DIV_S:
+ case INT_DIV_U:
+ {
+ JitInsn *insn = NULL, *insn1 = NULL;
+
+ if (is_i32) {
+ GEN_INSN(MOV, eax_hreg, left);
+ if (arith_op == INT_DIV_S)
+ insn = GEN_INSN(DIV_S, eax_hreg, eax_hreg, right);
+ else
+ insn = GEN_INSN(DIV_U, eax_hreg, eax_hreg, right);
+ }
+ else {
+ GEN_INSN(MOV, rax_hreg, left);
+ if (arith_op == INT_DIV_S)
+ insn = GEN_INSN(DIV_S, rax_hreg, rax_hreg, right);
+ else
+ insn = GEN_INSN(DIV_U, rax_hreg, rax_hreg, right);
+ }
+
+ if (!insn) {
+ goto fail;
+ }
+ if (!jit_lock_reg_in_insn(cc, insn, eax_hreg)
+ || !jit_lock_reg_in_insn(cc, insn, edx_hreg)) {
+ goto fail;
+ }
+
+ if (is_i32) {
+ res = jit_cc_new_reg_I32(cc);
+ insn1 = jit_insn_new_MOV(res, eax_hreg);
+ }
+ else {
+ res = jit_cc_new_reg_I64(cc);
+ insn1 = jit_insn_new_MOV(res, rax_hreg);
+ }
+
+ if (!insn1) {
+ jit_set_last_error(cc, "generate insn failed");
+ goto fail;
+ }
+
+ jit_insn_insert_after(insn, insn1);
+ break;
+ }
+ case INT_REM_S:
+ case INT_REM_U:
+ {
+ JitInsn *insn = NULL, *insn1 = NULL;
+
+ if (is_i32) {
+ GEN_INSN(MOV, eax_hreg, left);
+ if (arith_op == INT_REM_S)
+ insn = GEN_INSN(REM_S, edx_hreg, eax_hreg, right);
+ else
+ insn = GEN_INSN(REM_U, edx_hreg, eax_hreg, right);
+ }
+ else {
+ GEN_INSN(MOV, rax_hreg, left);
+ if (arith_op == INT_REM_S)
+ insn = GEN_INSN(REM_S, rdx_hreg, rax_hreg, right);
+ else
+ insn = GEN_INSN(REM_U, rdx_hreg, rax_hreg, right);
+ }
+
+ if (!insn) {
+ goto fail;
+ }
+ if (!jit_lock_reg_in_insn(cc, insn, eax_hreg)
+ || !jit_lock_reg_in_insn(cc, insn, edx_hreg)) {
+ goto fail;
+ }
+
+ if (is_i32) {
+ res = jit_cc_new_reg_I32(cc);
+ insn1 = jit_insn_new_MOV(res, edx_hreg);
+ }
+ else {
+ res = jit_cc_new_reg_I64(cc);
+ insn1 = jit_insn_new_MOV(res, rdx_hreg);
+ }
+
+ if (!insn1) {
+ jit_set_last_error(cc, "generate insn failed");
+ goto fail;
+ }
+
+ jit_insn_insert_after(insn, insn1);
+ break;
+ }
+#else
+ case INT_DIV_S:
+ GEN_INSN(DIV_S, res, left, right);
+ break;
+ case INT_DIV_U:
+ GEN_INSN(DIV_U, res, left, right);
+ break;
+ case INT_REM_S:
+ GEN_INSN(REM_S, res, left, right);
+ break;
+ case INT_REM_U:
+ GEN_INSN(REM_U, res, left, right);
+ break;
+#endif /* defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ if (is_i32)
+ PUSH_I32(res);
+ else
+ PUSH_I64(res);
+ return true;
+fail:
+ return false;
+}
+
+static bool
+compile_int_div(JitCompContext *cc, IntArithmetic arith_op, bool is_i32,
+ uint8 **p_frame_ip)
+{
+ JitReg left, right, res;
+
+ bh_assert(arith_op == INT_DIV_S || arith_op == INT_DIV_U
+ || arith_op == INT_REM_S || arith_op == INT_REM_U);
+
+ if (is_i32) {
+ POP_I32(right);
+ POP_I32(left);
+ res = jit_cc_new_reg_I32(cc);
+ }
+ else {
+ POP_I64(right);
+ POP_I64(left);
+ res = jit_cc_new_reg_I64(cc);
+ }
+
+ if (jit_reg_is_const(right)) {
+ int64 right_val = is_i32 ? (int64)jit_cc_get_const_I32(cc, right)
+ : jit_cc_get_const_I64(cc, right);
+
+ switch (right_val) {
+ case 0:
+ {
+ /* Directly throw exception if divided by zero */
+ if (!(jit_emit_exception(cc, EXCE_INTEGER_DIVIDE_BY_ZERO,
+ JIT_OP_JMP, 0, NULL)))
+ goto fail;
+
+ return jit_handle_next_reachable_block(cc, p_frame_ip);
+ }
+ case 1:
+ {
+ if (arith_op == INT_DIV_S || arith_op == INT_DIV_U) {
+ if (is_i32)
+ PUSH_I32(left);
+ else
+ PUSH_I64(left);
+ }
+ else {
+ if (is_i32)
+ PUSH_I32(NEW_CONST(I32, 0));
+ else
+ PUSH_I64(NEW_CONST(I64, 0));
+ }
+ return true;
+ }
+ case -1:
+ {
+ if (arith_op == INT_DIV_S) {
+ if (is_i32)
+ GEN_INSN(CMP, cc->cmp_reg, left,
+ NEW_CONST(I32, INT32_MIN));
+ else
+ GEN_INSN(CMP, cc->cmp_reg, left,
+ NEW_CONST(I64, INT64_MIN));
+
+ /* Throw integer overflow exception if left is
+ INT32_MIN or INT64_MIN */
+ if (!(jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW,
+ JIT_OP_BEQ, cc->cmp_reg, NULL)))
+ goto fail;
+
+ /* Push -(left) to stack */
+ GEN_INSN(NEG, res, left);
+ if (is_i32)
+ PUSH_I32(res);
+ else
+ PUSH_I64(res);
+ return true;
+ }
+ else if (arith_op == INT_REM_S) {
+ if (is_i32)
+ PUSH_I32(NEW_CONST(I32, 0));
+ else
+ PUSH_I64(NEW_CONST(I64, 0));
+ return true;
+ }
+ else {
+ /* Build default div and rem */
+ return compile_int_div_no_check(cc, arith_op, is_i32, left,
+ right, res);
+ }
+ }
+ default:
+ {
+ /* Build default div and rem */
+ return compile_int_div_no_check(cc, arith_op, is_i32, left,
+ right, res);
+ }
+ }
+ }
+ else {
+ JitReg cmp1 = jit_cc_new_reg_I32(cc);
+ JitReg cmp2 = jit_cc_new_reg_I32(cc);
+
+ GEN_INSN(CMP, cc->cmp_reg, right,
+ is_i32 ? NEW_CONST(I32, 0) : NEW_CONST(I64, 0));
+ /* Throw integer divided by zero exception if right is zero */
+ if (!(jit_emit_exception(cc, EXCE_INTEGER_DIVIDE_BY_ZERO, JIT_OP_BEQ,
+ cc->cmp_reg, NULL)))
+ goto fail;
+
+ switch (arith_op) {
+ case INT_DIV_S:
+ {
+ /* Check integer overflow */
+ GEN_INSN(CMP, cc->cmp_reg, left,
+ is_i32 ? NEW_CONST(I32, INT32_MIN)
+ : NEW_CONST(I64, INT64_MIN));
+ GEN_INSN(SELECTEQ, cmp1, cc->cmp_reg, NEW_CONST(I32, 1),
+ NEW_CONST(I32, 0));
+ GEN_INSN(CMP, cc->cmp_reg, right,
+ is_i32 ? NEW_CONST(I32, -1) : NEW_CONST(I64, -1LL));
+ GEN_INSN(SELECTEQ, cmp2, cc->cmp_reg, NEW_CONST(I32, 1),
+ NEW_CONST(I32, 0));
+ GEN_INSN(AND, cmp1, cmp1, cmp2);
+ GEN_INSN(CMP, cc->cmp_reg, cmp1, NEW_CONST(I32, 1));
+ /* Throw integer overflow exception if left is INT32_MIN or
+ INT64_MIN, and right is -1 */
+ if (!(jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BEQ,
+ cc->cmp_reg, NULL)))
+ goto fail;
+
+ /* Build default div and rem */
+ return compile_int_div_no_check(cc, arith_op, is_i32, left,
+ right, res);
+ }
+ case INT_REM_S:
+ {
+ JitReg left1 =
+ is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+
+ GEN_INSN(CMP, cc->cmp_reg, right,
+ is_i32 ? NEW_CONST(I32, -1) : NEW_CONST(I64, -1LL));
+ /* Don't generate `SELECTEQ left, cmp_reg, 0, left` since
+ left might be const, use left1 instead */
+ if (is_i32)
+ GEN_INSN(SELECTEQ, left1, cc->cmp_reg, NEW_CONST(I32, 0),
+ left);
+ else
+ GEN_INSN(SELECTEQ, left1, cc->cmp_reg, NEW_CONST(I64, 0),
+ left);
+ /* Build default div and rem */
+ return compile_int_div_no_check(cc, arith_op, is_i32, left1,
+ right, res);
+ }
+ default:
+ {
+ /* Build default div and rem */
+ return compile_int_div_no_check(cc, arith_op, is_i32, left,
+ right, res);
+ }
+ }
+ }
+
+fail:
+ return false;
+}
+
+static bool
+compile_op_int_arithmetic(JitCompContext *cc, IntArithmetic arith_op,
+ bool is_i32, uint8 **p_frame_ip)
+{
+ switch (arith_op) {
+ case INT_ADD:
+ DEF_INT_BINARY_OP(compile_int_add(cc, left, right, is_i32),
+ "compile int add fail.");
+ return true;
+ case INT_SUB:
+ DEF_INT_BINARY_OP(compile_int_sub(cc, left, right, is_i32),
+ "compile int sub fail.");
+ return true;
+ case INT_MUL:
+ DEF_INT_BINARY_OP(compile_int_mul(cc, 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(cc, arith_op, is_i32, p_frame_ip);
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_arithmetic(JitCompContext *cc, IntArithmetic arith_op,
+ uint8 **p_frame_ip)
+{
+ return compile_op_int_arithmetic(cc, arith_op, true, p_frame_ip);
+}
+
+bool
+jit_compile_op_i64_arithmetic(JitCompContext *cc, IntArithmetic arith_op,
+ uint8 **p_frame_ip)
+{
+ return compile_op_int_arithmetic(cc, arith_op, false, p_frame_ip);
+}
+
+DEF_UNI_INT_CONST_OPS(and)
+{
+ JitReg res;
+ if (IS_CONST_ZERO(left) || IS_CONST_ZERO(right)) {
+ res = is_i32 ? NEW_CONST(I32, 0) : NEW_CONST(I64, 0);
+ goto shortcut;
+ }
+
+ if (IS_CONST_ALL_ONE(left, is_i32)) {
+ res = right;
+ goto shortcut;
+ }
+
+ if (IS_CONST_ALL_ONE(right, is_i32)) {
+ res = left;
+ goto shortcut;
+ }
+
+ return 0;
+shortcut:
+ return res;
+}
+
+DEF_BI_INT_CONST_OPS(and, &)
+
+static JitReg
+compile_int_and(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+
+ /* shortcuts */
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, and);
+ if (res)
+ goto shortcut;
+
+ /* do and */
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(AND, res, left, right);
+
+shortcut:
+ return res;
+}
+
+DEF_UNI_INT_CONST_OPS(or)
+{
+ JitReg res;
+
+ if (IS_CONST_ZERO(left)) {
+ res = right;
+ goto shortcut;
+ }
+
+ if (IS_CONST_ZERO(right)) {
+ res = left;
+ goto shortcut;
+ }
+
+ if (IS_CONST_ALL_ONE(left, is_i32) || IS_CONST_ALL_ONE(right, is_i32)) {
+ res = is_i32 ? NEW_CONST(I32, -1) : NEW_CONST(I64, -1LL);
+ goto shortcut;
+ }
+
+ return 0;
+shortcut:
+ return res;
+}
+
+DEF_BI_INT_CONST_OPS(or, |)
+
+static JitReg
+compile_int_or(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+
+ /* shortcuts */
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, or);
+ if (res)
+ goto shortcut;
+
+ /* do or */
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(OR, res, left, right);
+
+shortcut:
+ return res;
+}
+
+DEF_UNI_INT_CONST_OPS(xor)
+{
+ if (IS_CONST_ZERO(left))
+ return right;
+
+ if (IS_CONST_ZERO(right))
+ return left;
+
+ return 0;
+}
+
+DEF_BI_INT_CONST_OPS(xor, ^)
+
+static JitReg
+compile_int_xor(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+
+ /* shortcuts */
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, xor);
+ if (res)
+ goto shortcut;
+
+ /* do xor */
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(XOR, res, left, right);
+
+shortcut:
+ return res;
+}
+
+static bool
+compile_op_int_bitwise(JitCompContext *cc, IntBitwise arith_op, bool is_i32)
+{
+ JitReg left, right, res;
+
+ POP_INT(right);
+ POP_INT(left);
+
+ switch (arith_op) {
+ case INT_AND:
+ {
+ res = compile_int_and(cc, left, right, is_i32);
+ break;
+ }
+ case INT_OR:
+ {
+ res = compile_int_or(cc, left, right, is_i32);
+ break;
+ }
+ case INT_XOR:
+ {
+ res = compile_int_xor(cc, left, right, is_i32);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ PUSH_INT(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_bitwise(JitCompContext *cc, IntBitwise bitwise_op)
+{
+ return compile_op_int_bitwise(cc, bitwise_op, true);
+}
+
+bool
+jit_compile_op_i64_bitwise(JitCompContext *cc, IntBitwise bitwise_op)
+{
+ return compile_op_int_bitwise(cc, bitwise_op, false);
+}
+
+DEF_UNI_INT_CONST_OPS(shl)
+{
+ if (IS_CONST_ZERO(right) || IS_CONST_ZERO(left)) {
+ return left;
+ }
+
+ if (jit_reg_is_const(right)) {
+ JitReg res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHL, res, left, right);
+ return res;
+ }
+ return 0;
+}
+
+DEF_UNI_INT_CONST_OPS(shrs)
+{
+ if (IS_CONST_ZERO(right) || IS_CONST_ZERO(left)
+ || IS_CONST_ALL_ONE(left, is_i32)) {
+ return left;
+ }
+
+ if (jit_reg_is_const(right)) {
+ JitReg res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHRS, res, left, right);
+ return res;
+ }
+ return 0;
+}
+
+DEF_UNI_INT_CONST_OPS(shru)
+{
+ if (IS_CONST_ZERO(right) || IS_CONST_ZERO(left)) {
+ return left;
+ }
+
+ if (jit_reg_is_const(right)) {
+ JitReg res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(SHRU, res, left, right);
+ return res;
+ }
+ return 0;
+}
+
+static int32
+do_i32_const_shl(int32 lhs, int32 rhs)
+{
+ return (int32)((uint32)lhs << (uint32)rhs);
+}
+
+static int64
+do_i64_const_shl(int64 lhs, int64 rhs)
+{
+ return (int32)((uint64)lhs << (uint64)rhs);
+}
+
+DEF_BI_INT_CONST_OPS(shrs, >>)
+
+static int32
+do_i32_const_shru(int32 lhs, int32 rhs)
+{
+ return (uint32)lhs >> rhs;
+}
+
+static int64
+do_i64_const_shru(int64 lhs, int64 rhs)
+{
+ return (uint64)lhs >> rhs;
+}
+
+typedef enum { SHL, SHRS, SHRU, ROTL, ROTR } SHIFT_OP;
+
+static JitReg
+compile_int_shift_modulo(JitCompContext *cc, JitReg rhs, bool is_i32,
+ SHIFT_OP op)
+{
+ JitReg res;
+
+ if (jit_reg_is_const(rhs)) {
+ if (is_i32) {
+ int32 val = jit_cc_get_const_I32(cc, rhs);
+ val = val & 0x1f;
+ res = NEW_CONST(I32, val);
+ }
+ else {
+ int64 val = jit_cc_get_const_I64(cc, rhs);
+ val = val & 0x3f;
+ res = NEW_CONST(I64, val);
+ }
+ }
+ else {
+ if (op == ROTL || op == ROTR) {
+ /* No need to generate AND insn as the result
+ is same for rotate shift */
+ res = rhs;
+ }
+ else if (is_i32) {
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(AND, res, rhs, NEW_CONST(I32, 0x1f));
+ }
+ else {
+ res = jit_cc_new_reg_I64(cc);
+ GEN_INSN(AND, res, rhs, NEW_CONST(I64, 0x3f));
+ }
+ }
+
+ return res;
+}
+
+static JitReg
+mov_left_to_reg(JitCompContext *cc, bool is_i32, JitReg left)
+{
+ JitReg res = left;
+ /* left needs to be a variable */
+ if (jit_reg_is_const(left)) {
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(MOV, res, left);
+ }
+ return res;
+}
+
+static JitReg
+compile_int_shl(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ JitReg ecx_hreg = jit_codegen_get_hreg_by_name("ecx");
+ JitReg rcx_hreg = jit_codegen_get_hreg_by_name("rcx");
+ JitInsn *insn = NULL;
+#endif
+
+ right = compile_int_shift_modulo(cc, right, is_i32, SHL);
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, shl);
+ if (res)
+ goto shortcut;
+
+ left = mov_left_to_reg(cc, is_i32, left);
+
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ GEN_INSN(MOV, is_i32 ? ecx_hreg : rcx_hreg, right);
+ insn = GEN_INSN(SHL, res, left, is_i32 ? ecx_hreg : rcx_hreg);
+ if (jit_get_last_error(cc) || !jit_lock_reg_in_insn(cc, insn, ecx_hreg)) {
+ goto fail;
+ }
+#else
+ GEN_INSN(SHL, res, left, right);
+ if (jit_get_last_error(cc)) {
+ goto fail;
+ }
+#endif
+
+shortcut:
+ return res;
+fail:
+ return (JitReg)0;
+}
+
+static JitReg
+compile_int_shrs(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ JitReg ecx_hreg = jit_codegen_get_hreg_by_name("ecx");
+ JitReg rcx_hreg = jit_codegen_get_hreg_by_name("rcx");
+ JitInsn *insn = NULL;
+#endif
+
+ right = compile_int_shift_modulo(cc, right, is_i32, SHRS);
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, shrs);
+ if (res)
+ goto shortcut;
+
+ left = mov_left_to_reg(cc, is_i32, left);
+
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ GEN_INSN(MOV, is_i32 ? ecx_hreg : rcx_hreg, right);
+ insn = GEN_INSN(SHRS, res, left, is_i32 ? ecx_hreg : rcx_hreg);
+ if (jit_get_last_error(cc) || !jit_lock_reg_in_insn(cc, insn, ecx_hreg)) {
+ goto fail;
+ }
+#else
+ GEN_INSN(SHRS, res, left, right);
+ if (jit_get_last_error(cc)) {
+ goto fail;
+ }
+#endif
+
+shortcut:
+ return res;
+fail:
+ return (JitReg)0;
+}
+
+static JitReg
+compile_int_shru(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ JitReg ecx_hreg = jit_codegen_get_hreg_by_name("ecx");
+ JitReg rcx_hreg = jit_codegen_get_hreg_by_name("rcx");
+ JitInsn *insn = NULL;
+#endif
+
+ right = compile_int_shift_modulo(cc, right, is_i32, SHRU);
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, shru);
+ if (res)
+ goto shortcut;
+
+ left = mov_left_to_reg(cc, is_i32, left);
+
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ GEN_INSN(MOV, is_i32 ? ecx_hreg : rcx_hreg, right);
+ insn = GEN_INSN(SHRU, res, left, is_i32 ? ecx_hreg : rcx_hreg);
+ if (jit_get_last_error(cc) || !jit_lock_reg_in_insn(cc, insn, ecx_hreg)) {
+ goto fail;
+ }
+#else
+ GEN_INSN(SHRU, res, left, right);
+ if (jit_get_last_error(cc)) {
+ goto fail;
+ }
+#endif
+
+shortcut:
+ return res;
+fail:
+ return (JitReg)0;
+}
+
+DEF_UNI_INT_CONST_OPS(rotl)
+{
+ if (IS_CONST_ZERO(right) || IS_CONST_ZERO(left)
+ || IS_CONST_ALL_ONE(left, is_i32))
+ return left;
+
+ if (jit_reg_is_const(right)) {
+ JitReg res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(ROTL, res, left, right);
+ return res;
+ }
+
+ return 0;
+}
+
+static int32
+do_i32_const_rotl(int32 lhs, int32 rhs)
+{
+ uint32 n = (uint32)lhs;
+ uint32 d = (uint32)rhs;
+ return (n << d) | (n >> (32 - d));
+}
+
+static int64
+do_i64_const_rotl(int64 lhs, int64 rhs)
+{
+ uint64 n = (uint64)lhs;
+ uint64 d = (uint64)rhs;
+ return (n << d) | (n >> (64 - d));
+}
+
+static JitReg
+compile_int_rotl(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ JitReg ecx_hreg = jit_codegen_get_hreg_by_name("ecx");
+ JitReg rcx_hreg = jit_codegen_get_hreg_by_name("rcx");
+ JitInsn *insn = NULL;
+#endif
+
+ right = compile_int_shift_modulo(cc, right, is_i32, ROTL);
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, rotl);
+ if (res)
+ goto shortcut;
+
+ left = mov_left_to_reg(cc, is_i32, left);
+
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ GEN_INSN(MOV, is_i32 ? ecx_hreg : rcx_hreg, right);
+ insn = GEN_INSN(ROTL, res, left, is_i32 ? ecx_hreg : rcx_hreg);
+ if (jit_get_last_error(cc) || !jit_lock_reg_in_insn(cc, insn, ecx_hreg)) {
+ goto fail;
+ }
+#else
+ GEN_INSN(ROTL, res, left, right);
+ if (jit_get_last_error(cc)) {
+ goto fail;
+ }
+#endif
+
+shortcut:
+ return res;
+fail:
+ return (JitReg)0;
+}
+
+DEF_UNI_INT_CONST_OPS(rotr)
+{
+ if (IS_CONST_ZERO(right) || IS_CONST_ZERO(left)
+ || IS_CONST_ALL_ONE(left, is_i32))
+ return left;
+
+ if (jit_reg_is_const(right)) {
+ JitReg res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+ GEN_INSN(ROTR, res, left, right);
+ return res;
+ }
+
+ return 0;
+}
+
+static int32
+do_i32_const_rotr(int32 lhs, int32 rhs)
+{
+ uint32 n = (uint32)lhs;
+ uint32 d = (uint32)rhs;
+ return (n >> d) | (n << (32 - d));
+}
+
+static int64
+do_i64_const_rotr(int64 lhs, int64 rhs)
+{
+ uint64 n = (uint64)lhs;
+ uint64 d = (uint64)rhs;
+ return (n >> d) | (n << (64 - d));
+}
+
+static JitReg
+compile_int_rotr(JitCompContext *cc, JitReg left, JitReg right, bool is_i32)
+{
+ JitReg res;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ JitReg ecx_hreg = jit_codegen_get_hreg_by_name("ecx");
+ JitReg rcx_hreg = jit_codegen_get_hreg_by_name("rcx");
+ JitInsn *insn = NULL;
+#endif
+
+ right = compile_int_shift_modulo(cc, right, is_i32, ROTR);
+
+ res = CHECK_AND_PROCESS_INT_CONSTS(cc, left, right, is_i32, rotr);
+ if (res)
+ goto shortcut;
+
+ left = mov_left_to_reg(cc, is_i32, left);
+
+ res = is_i32 ? jit_cc_new_reg_I32(cc) : jit_cc_new_reg_I64(cc);
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ GEN_INSN(MOV, is_i32 ? ecx_hreg : rcx_hreg, right);
+ insn = GEN_INSN(ROTR, res, left, is_i32 ? ecx_hreg : rcx_hreg);
+ if (jit_get_last_error(cc) || !jit_lock_reg_in_insn(cc, insn, ecx_hreg)) {
+ goto fail;
+ }
+#else
+ GEN_INSN(ROTR, res, left, right);
+ if (jit_get_last_error(cc)) {
+ goto fail;
+ }
+#endif
+
+shortcut:
+ return res;
+fail:
+ return (JitReg)0;
+}
+
+static bool
+compile_op_int_shift(JitCompContext *cc, IntShift shift_op, bool is_i32)
+{
+ JitReg left, right, res;
+
+ POP_INT(right);
+ POP_INT(left);
+
+ switch (shift_op) {
+ case INT_SHL:
+ {
+ res = compile_int_shl(cc, left, right, is_i32);
+ break;
+ }
+ case INT_SHR_S:
+ {
+ res = compile_int_shrs(cc, left, right, is_i32);
+ break;
+ }
+ case INT_SHR_U:
+ {
+ res = compile_int_shru(cc, left, right, is_i32);
+ break;
+ }
+ case INT_ROTL:
+ {
+ res = compile_int_rotl(cc, left, right, is_i32);
+ break;
+ }
+ case INT_ROTR:
+ {
+ res = compile_int_rotr(cc, left, right, is_i32);
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ PUSH_INT(res);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_i32_shift(JitCompContext *cc, IntShift shift_op)
+{
+ return compile_op_int_shift(cc, shift_op, true);
+}
+
+bool
+jit_compile_op_i64_shift(JitCompContext *cc, IntShift shift_op)
+{
+ return compile_op_int_shift(cc, shift_op, false);
+}
+
+static float32
+negf(float32 f32)
+{
+ return -f32;
+}
+
+static float64
+neg(float64 f64)
+{
+ return -f64;
+}
+
+static bool
+compile_op_float_math(JitCompContext *cc, FloatMath math_op, bool is_f32)
+{
+ JitReg value, res;
+ void *func = NULL;
+
+ if (is_f32)
+ res = jit_cc_new_reg_F32(cc);
+ else
+ res = jit_cc_new_reg_F64(cc);
+
+ if (is_f32)
+ POP_F32(value);
+ else
+ POP_F64(value);
+
+ switch (math_op) {
+ case FLOAT_ABS:
+ /* TODO: andps 0x7fffffffffffffff */
+ func = is_f32 ? (void *)fabsf : (void *)fabs;
+ break;
+ case FLOAT_NEG:
+ /* TODO: xorps 0x8000000000000000 */
+ func = is_f32 ? (void *)negf : (void *)neg;
+ break;
+ case FLOAT_CEIL:
+ func = is_f32 ? (void *)ceilf : (void *)ceil;
+ break;
+ case FLOAT_FLOOR:
+ func = is_f32 ? (void *)floorf : (void *)floor;
+ break;
+ case FLOAT_TRUNC:
+ func = is_f32 ? (void *)truncf : (void *)trunc;
+ break;
+ case FLOAT_NEAREST:
+ func = is_f32 ? (void *)rintf : (void *)rint;
+ break;
+ case FLOAT_SQRT:
+ func = is_f32 ? (void *)sqrtf : (void *)sqrt;
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+
+ if (!jit_emit_callnative(cc, func, res, &value, 1)) {
+ goto fail;
+ }
+
+ if (is_f32)
+ PUSH_F32(res);
+ else
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_math(JitCompContext *cc, FloatMath math_op)
+{
+ return compile_op_float_math(cc, math_op, true);
+}
+
+bool
+jit_compile_op_f64_math(JitCompContext *cc, FloatMath math_op)
+{
+ return compile_op_float_math(cc, math_op, false);
+}
+
+static float32
+f32_min(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+static float32
+f32_max(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+static float64
+f64_min(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+static float64
+f64_max(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+static bool
+compile_op_float_min_max(JitCompContext *cc, FloatArithmetic arith_op,
+ bool is_f32, JitReg lhs, JitReg rhs, JitReg *out)
+{
+ JitReg res, args[2];
+ void *func;
+
+ res = is_f32 ? jit_cc_new_reg_F32(cc) : jit_cc_new_reg_F64(cc);
+ if (arith_op == FLOAT_MIN)
+ func = is_f32 ? (void *)f32_min : (void *)f64_min;
+ else
+ func = is_f32 ? (void *)f32_max : (void *)f64_max;
+
+ args[0] = lhs;
+ args[1] = rhs;
+ if (!jit_emit_callnative(cc, func, res, args, 2))
+ return false;
+
+ *out = res;
+ return true;
+}
+
+static bool
+compile_op_float_arithmetic(JitCompContext *cc, FloatArithmetic arith_op,
+ bool is_f32)
+{
+ JitReg lhs, rhs, res;
+
+ if (is_f32) {
+ POP_F32(rhs);
+ POP_F32(lhs);
+ res = jit_cc_new_reg_F32(cc);
+ }
+ else {
+ POP_F64(rhs);
+ POP_F64(lhs);
+ res = jit_cc_new_reg_F64(cc);
+ }
+
+ switch (arith_op) {
+ case FLOAT_ADD:
+ {
+ GEN_INSN(ADD, res, lhs, rhs);
+ break;
+ }
+ case FLOAT_SUB:
+ {
+ GEN_INSN(SUB, res, lhs, rhs);
+ break;
+ }
+ case FLOAT_MUL:
+ {
+ GEN_INSN(MUL, res, lhs, rhs);
+ break;
+ }
+ case FLOAT_DIV:
+ {
+ GEN_INSN(DIV_S, res, lhs, rhs);
+ break;
+ }
+ case FLOAT_MIN:
+ case FLOAT_MAX:
+ {
+ if (!compile_op_float_min_max(cc, arith_op, is_f32, lhs, rhs, &res))
+ goto fail;
+ break;
+ }
+ default:
+ {
+ bh_assert(0);
+ goto fail;
+ }
+ }
+
+ if (is_f32)
+ PUSH_F32(res);
+ else
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f32_arithmetic(JitCompContext *cc, FloatArithmetic arith_op)
+{
+ return compile_op_float_arithmetic(cc, arith_op, true);
+}
+
+bool
+jit_compile_op_f64_arithmetic(JitCompContext *cc, FloatArithmetic arith_op)
+{
+ return compile_op_float_arithmetic(cc, arith_op, false);
+}
+
+bool
+jit_compile_op_f32_copysign(JitCompContext *cc)
+{
+ JitReg res;
+ JitReg args[2] = { 0 };
+
+ POP_F32(args[1]);
+ POP_F32(args[0]);
+
+ res = jit_cc_new_reg_F32(cc);
+ if (!jit_emit_callnative(cc, copysignf, res, args, 2))
+ goto fail;
+
+ PUSH_F32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_f64_copysign(JitCompContext *cc)
+{
+ JitReg res;
+ JitReg args[2] = { 0 };
+
+ POP_F64(args[1]);
+ POP_F64(args[0]);
+
+ res = jit_cc_new_reg_F64(cc);
+ if (!jit_emit_callnative(cc, copysign, res, args, 2))
+ goto fail;
+
+ PUSH_F64(res);
+
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.h
new file mode 100644
index 000000000..e73c3ebad
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_numberic.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_NUMBERIC_H_
+#define _JIT_EMIT_NUMBERIC_H_
+
+#include "../jit_compiler.h"
+#include "../jit_frontend.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_i32_clz(JitCompContext *cc);
+
+bool
+jit_compile_op_i32_ctz(JitCompContext *cc);
+
+bool
+jit_compile_op_i32_popcnt(JitCompContext *cc);
+
+bool
+jit_compile_op_i64_clz(JitCompContext *cc);
+
+bool
+jit_compile_op_i64_ctz(JitCompContext *cc);
+
+bool
+jit_compile_op_i64_popcnt(JitCompContext *cc);
+
+bool
+jit_compile_op_i32_arithmetic(JitCompContext *cc, IntArithmetic arith_op,
+ uint8 **p_frame_ip);
+
+bool
+jit_compile_op_i64_arithmetic(JitCompContext *cc, IntArithmetic arith_op,
+ uint8 **p_frame_ip);
+
+bool
+jit_compile_op_i32_bitwise(JitCompContext *cc, IntBitwise bitwise_op);
+
+bool
+jit_compile_op_i64_bitwise(JitCompContext *cc, IntBitwise bitwise_op);
+
+bool
+jit_compile_op_i32_shift(JitCompContext *cc, IntShift shift_op);
+
+bool
+jit_compile_op_i64_shift(JitCompContext *cc, IntShift shift_op);
+
+bool
+jit_compile_op_f32_math(JitCompContext *cc, FloatMath math_op);
+
+bool
+jit_compile_op_f64_math(JitCompContext *cc, FloatMath math_op);
+
+bool
+jit_compile_op_f32_arithmetic(JitCompContext *cc, FloatArithmetic arith_op);
+
+bool
+jit_compile_op_f64_arithmetic(JitCompContext *cc, FloatArithmetic arith_op);
+
+bool
+jit_compile_op_f32_copysign(JitCompContext *cc);
+
+bool
+jit_compile_op_f64_copysign(JitCompContext *cc);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_NUMBERIC_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.c
new file mode 100644
index 000000000..df0b23a7a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_parametric.h"
+#include "../jit_frontend.h"
+
+static bool
+pop_value_from_wasm_stack(JitCompContext *cc, bool is_32bit, JitReg *p_value,
+ uint8 *p_type)
+{
+ JitValue *jit_value;
+ JitReg value;
+ uint8 type;
+
+ if (!jit_block_stack_top(&cc->block_stack)) {
+ jit_set_last_error(cc, "WASM block stack underflow.");
+ return false;
+ }
+ if (!jit_block_stack_top(&cc->block_stack)->value_stack.value_list_end) {
+ jit_set_last_error(cc, "WASM data stack underflow.");
+ return false;
+ }
+
+ jit_value = jit_value_stack_pop(
+ &jit_block_stack_top(&cc->block_stack)->value_stack);
+ type = jit_value->type;
+
+ if (p_type != NULL) {
+ *p_type = jit_value->type;
+ }
+
+ wasm_runtime_free(jit_value);
+
+ /* is_32: i32, f32, ref.func, ref.extern, v128 */
+ if (is_32bit
+ && !(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+#if WASM_ENABLE_REF_TYPES != 0
+ || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+#endif
+ || type == VALUE_TYPE_V128)) {
+ jit_set_last_error(cc, "invalid WASM stack data type.");
+ return false;
+ }
+ /* !is_32: i64, f64 */
+ if (!is_32bit && !(type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)) {
+ jit_set_last_error(cc, "invalid WASM stack data type.");
+ return false;
+ }
+
+ switch (type) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ value = pop_i32(cc->jit_frame);
+ break;
+ case VALUE_TYPE_I64:
+ value = pop_i64(cc->jit_frame);
+ break;
+ case VALUE_TYPE_F32:
+ value = pop_f32(cc->jit_frame);
+ break;
+ case VALUE_TYPE_F64:
+ value = pop_f64(cc->jit_frame);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ if (p_value != NULL) {
+ *p_value = value;
+ }
+ return true;
+}
+
+bool
+jit_compile_op_drop(JitCompContext *cc, bool is_drop_32)
+{
+ if (!pop_value_from_wasm_stack(cc, is_drop_32, NULL, NULL))
+ return false;
+ return true;
+}
+
+bool
+jit_compile_op_select(JitCompContext *cc, bool is_select_32)
+{
+ JitReg val1, val2, cond, selected;
+ uint8 val1_type, val2_type;
+
+ POP_I32(cond);
+
+ if (!pop_value_from_wasm_stack(cc, is_select_32, &val2, &val2_type)
+ || !pop_value_from_wasm_stack(cc, is_select_32, &val1, &val1_type)) {
+ return false;
+ }
+
+ if (val1_type != val2_type) {
+ jit_set_last_error(cc, "invalid stack values with different type");
+ return false;
+ }
+
+ switch (val1_type) {
+ case VALUE_TYPE_I32:
+ selected = jit_cc_new_reg_I32(cc);
+ break;
+ case VALUE_TYPE_I64:
+ selected = jit_cc_new_reg_I64(cc);
+ break;
+ case VALUE_TYPE_F32:
+ selected = jit_cc_new_reg_F32(cc);
+ break;
+ case VALUE_TYPE_F64:
+ selected = jit_cc_new_reg_F64(cc);
+ break;
+ default:
+ bh_assert(0);
+ return false;
+ }
+
+ GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0));
+ GEN_INSN(SELECTNE, selected, cc->cmp_reg, val1, val2);
+ PUSH(selected, val1_type);
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.h
new file mode 100644
index 000000000..40025ed21
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_parametric.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_PARAMETRIC_H_
+#define _JIT_EMIT_PARAMETRIC_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_drop(JitCompContext *cc, bool is_drop_32);
+
+bool
+jit_compile_op_select(JitCompContext *cc, bool is_select_32);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_PARAMETRIC_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.c
new file mode 100644
index 000000000..9fb61931f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_table.h"
+#include "jit_emit_exception.h"
+#include "jit_emit_function.h"
+#include "../../interpreter/wasm_runtime.h"
+#include "../jit_frontend.h"
+
+#if WASM_ENABLE_REF_TYPES != 0
+bool
+jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
+{
+ JitReg module, tbl_segs;
+
+ module = get_module_reg(cc->jit_frame);
+
+ tbl_segs = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(LDPTR, tbl_segs, module,
+ NEW_CONST(I32, offsetof(WASMModule, table_segments)));
+
+ GEN_INSN(STI32, NEW_CONST(I32, true), tbl_segs,
+ NEW_CONST(I32, tbl_seg_idx * sizeof(WASMTableSeg)
+ + offsetof(WASMTableSeg, is_dropped)));
+ return true;
+}
+
+bool
+jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx)
+{
+ JitReg elem_idx, tbl_sz, tbl_elems, elem_idx_long, offset, res;
+
+ POP_I32(elem_idx);
+
+ /* if (elem_idx >= tbl_sz) goto exception; */
+ tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
+ GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
+ if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ elem_idx_long = jit_cc_new_reg_I64(cc);
+ GEN_INSN(I32TOI64, elem_idx_long, elem_idx);
+
+ offset = jit_cc_new_reg_I64(cc);
+ GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
+
+ res = jit_cc_new_reg_I32(cc);
+ tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
+ GEN_INSN(LDI32, res, tbl_elems, offset);
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
+{
+ JitReg elem_idx, elem_val, tbl_sz, tbl_elems, elem_idx_long, offset;
+
+ POP_I32(elem_val);
+ POP_I32(elem_idx);
+
+ /* if (elem_idx >= tbl_sz) goto exception; */
+ tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
+ GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
+ if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
+ cc->cmp_reg, NULL))
+ goto fail;
+
+ elem_idx_long = jit_cc_new_reg_I64(cc);
+ GEN_INSN(I32TOI64, elem_idx_long, elem_idx);
+
+ offset = jit_cc_new_reg_I64(cc);
+ GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
+
+ tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
+ GEN_INSN(STI32, elem_val, tbl_elems, offset);
+
+ return true;
+fail:
+ return false;
+}
+
+static int
+wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
+ uint32 dst, uint32 len, uint32 src)
+{
+ WASMTableInstance *tbl;
+ uint32 tbl_sz;
+ WASMTableSeg *elem;
+ uint32 elem_len;
+
+ tbl = inst->tables[tbl_idx];
+ tbl_sz = tbl->cur_size;
+ if (dst > tbl_sz || tbl_sz - dst < len)
+ goto out_of_bounds;
+
+ elem = inst->module->table_segments + elem_idx;
+ elem_len = elem->function_count;
+ if (src > elem_len || elem_len - src < len)
+ goto out_of_bounds;
+
+ bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
+ + dst * sizeof(uint32),
+ (uint32)((tbl_sz - dst) * sizeof(uint32)),
+ elem->func_indexes + src, (uint32)(len * sizeof(uint32)));
+
+ return 0;
+out_of_bounds:
+ wasm_set_exception(inst, "out of bounds table access");
+ return -1;
+}
+
+bool
+jit_compile_op_table_init(JitCompContext *cc, uint32 tbl_idx,
+ uint32 tbl_seg_idx)
+{
+ JitReg len, src, dst, res;
+ JitReg args[6] = { 0 };
+
+ POP_I32(len);
+ POP_I32(src);
+ POP_I32(dst);
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, tbl_idx);
+ args[2] = NEW_CONST(I32, tbl_seg_idx);
+ args[3] = dst;
+ args[4] = len;
+ args[5] = src;
+
+ if (!jit_emit_callnative(cc, wasm_init_table, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+
+static int
+wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx, uint32 dst_offset, uint32 len,
+ uint32 src_offset)
+{
+ WASMTableInstance *src_tbl, *dst_tbl;
+ uint32 src_tbl_sz, dst_tbl_sz;
+
+ src_tbl = inst->tables[src_tbl_idx];
+ src_tbl_sz = src_tbl->cur_size;
+ if (src_offset > src_tbl_sz || src_tbl_sz - src_offset < len)
+ goto out_of_bounds;
+
+ dst_tbl = inst->tables[dst_tbl_idx];
+ dst_tbl_sz = dst_tbl->cur_size;
+ if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len)
+ goto out_of_bounds;
+
+ bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems)
+ + dst_offset * sizeof(uint32),
+ (uint32)((dst_tbl_sz - dst_offset) * sizeof(uint32)),
+ (uint8 *)src_tbl + offsetof(WASMTableInstance, elems)
+ + src_offset * sizeof(uint32),
+ (uint32)(len * sizeof(uint32)));
+
+ return 0;
+out_of_bounds:
+ wasm_set_exception(inst, "out of bounds table access");
+ return -1;
+}
+
+bool
+jit_compile_op_table_copy(JitCompContext *cc, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx)
+{
+ JitReg len, src, dst, res;
+ JitReg args[6] = { 0 };
+
+ POP_I32(len);
+ POP_I32(src);
+ POP_I32(dst);
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, src_tbl_idx);
+ args[2] = NEW_CONST(I32, dst_tbl_idx);
+ args[3] = dst;
+ args[4] = len;
+ args[5] = src;
+
+ if (!jit_emit_callnative(cc, wasm_copy_table, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_table_size(JitCompContext *cc, uint32 tbl_idx)
+{
+ JitReg res;
+
+ res = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
+ PUSH_I32(res);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_table_grow(JitCompContext *cc, uint32 tbl_idx)
+{
+ JitReg tbl_sz, n, val, enlarge_ret, res;
+ JitReg args[4] = { 0 };
+
+ POP_I32(n);
+ POP_I32(val);
+
+ tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
+
+ enlarge_ret = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, tbl_idx);
+ args[2] = n;
+ args[3] = val;
+
+ if (!jit_emit_callnative(cc, wasm_enlarge_table, enlarge_ret, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ /* Convert bool to uint32 */
+ GEN_INSN(AND, enlarge_ret, enlarge_ret, NEW_CONST(I32, 0xFF));
+
+ res = jit_cc_new_reg_I32(cc);
+ GEN_INSN(CMP, cc->cmp_reg, enlarge_ret, NEW_CONST(I32, 1));
+ GEN_INSN(SELECTEQ, res, cc->cmp_reg, tbl_sz, NEW_CONST(I32, -1));
+ PUSH_I32(res);
+
+ /* Ensure a refresh in next get memory related registers */
+ clear_table_regs(cc->jit_frame);
+ return true;
+fail:
+ return false;
+}
+
+static int
+wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
+ uint32 val, uint32 len)
+{
+ WASMTableInstance *tbl;
+ uint32 tbl_sz;
+
+ tbl = inst->tables[tbl_idx];
+ tbl_sz = tbl->cur_size;
+
+ if (dst > tbl_sz || tbl_sz - dst < len)
+ goto out_of_bounds;
+
+ for (; len != 0; dst++, len--) {
+ tbl->elems[dst] = val;
+ }
+
+ return 0;
+out_of_bounds:
+ wasm_set_exception(inst, "out of bounds table access");
+ return -1;
+}
+
+bool
+jit_compile_op_table_fill(JitCompContext *cc, uint32 tbl_idx)
+{
+ JitReg len, val, dst, res;
+ JitReg args[5] = { 0 };
+
+ POP_I32(len);
+ POP_I32(val);
+ POP_I32(dst);
+
+ res = jit_cc_new_reg_I32(cc);
+ args[0] = get_module_inst_reg(cc->jit_frame);
+ args[1] = NEW_CONST(I32, tbl_idx);
+ args[2] = dst;
+ args[3] = val;
+ args[4] = len;
+
+ if (!jit_emit_callnative(cc, wasm_fill_table, res, args,
+ sizeof(args) / sizeof(args[0])))
+ goto fail;
+
+ GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+ if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+ NULL))
+ goto fail;
+
+ return true;
+fail:
+ return false;
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.h
new file mode 100644
index 000000000..acfb655f2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_table.h
@@ -0,0 +1,47 @@
+
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_TABLE_H_
+#define _JIT_EMIT_TABLE_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+bool
+jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx);
+
+bool
+jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx);
+
+bool
+jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx);
+
+bool
+jit_compile_op_table_init(JitCompContext *cc, uint32 tbl_idx,
+ uint32 tbl_seg_idx);
+
+bool
+jit_compile_op_table_copy(JitCompContext *cc, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx);
+
+bool
+jit_compile_op_table_size(JitCompContext *cc, uint32 tbl_idx);
+
+bool
+jit_compile_op_table_grow(JitCompContext *cc, uint32 tbl_idx);
+
+bool
+jit_compile_op_table_fill(JitCompContext *cc, uint32 tbl_idx);
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.c
new file mode 100644
index 000000000..ffbf06ab1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_emit_variable.h"
+#include "jit_emit_exception.h"
+#include "../jit_frontend.h"
+
+#define CHECK_LOCAL(idx) \
+ do { \
+ if (idx \
+ >= wasm_func->func_type->param_count + wasm_func->local_count) { \
+ jit_set_last_error(cc, "local index out of range"); \
+ goto fail; \
+ } \
+ } while (0)
+
+static uint8
+get_local_type(const WASMFunction *wasm_func, uint32 local_idx)
+{
+ uint32 param_count = wasm_func->func_type->param_count;
+ return local_idx < param_count
+ ? wasm_func->func_type->types[local_idx]
+ : wasm_func->local_types[local_idx - param_count];
+}
+
+bool
+jit_compile_op_get_local(JitCompContext *cc, uint32 local_idx)
+{
+ WASMFunction *wasm_func = cc->cur_wasm_func;
+ uint16 *local_offsets = wasm_func->local_offsets;
+ uint16 local_offset;
+ uint8 local_type;
+ JitReg value = 0;
+
+ CHECK_LOCAL(local_idx);
+
+ local_offset = local_offsets[local_idx];
+ local_type = get_local_type(wasm_func, local_idx);
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ value = local_i32(cc->jit_frame, local_offset);
+
+ break;
+ case VALUE_TYPE_I64:
+ value = local_i64(cc->jit_frame, local_offset);
+ break;
+ case VALUE_TYPE_F32:
+ value = local_f32(cc->jit_frame, local_offset);
+ break;
+ case VALUE_TYPE_F64:
+ value = local_f64(cc->jit_frame, local_offset);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ PUSH(value, local_type);
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_set_local(JitCompContext *cc, uint32 local_idx)
+{
+ WASMFunction *wasm_func = cc->cur_wasm_func;
+ uint16 *local_offsets = wasm_func->local_offsets;
+ uint16 local_offset;
+ uint8 local_type;
+ JitReg value;
+
+ CHECK_LOCAL(local_idx);
+
+ local_offset = local_offsets[local_idx];
+ local_type = get_local_type(wasm_func, local_idx);
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ POP_I32(value);
+ set_local_i32(cc->jit_frame, local_offset, value);
+ break;
+ case VALUE_TYPE_I64:
+ POP_I64(value);
+ set_local_i64(cc->jit_frame, local_offset, value);
+ break;
+ case VALUE_TYPE_F32:
+ POP_F32(value);
+ set_local_f32(cc->jit_frame, local_offset, value);
+ break;
+ case VALUE_TYPE_F64:
+ POP_F64(value);
+ set_local_f64(cc->jit_frame, local_offset, value);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_tee_local(JitCompContext *cc, uint32 local_idx)
+{
+ WASMFunction *wasm_func = cc->cur_wasm_func;
+ uint16 *local_offsets = wasm_func->local_offsets;
+ uint16 local_offset;
+ uint8 local_type;
+ JitReg value = 0;
+
+ CHECK_LOCAL(local_idx);
+
+ local_offset = local_offsets[local_idx];
+ local_type = get_local_type(wasm_func, local_idx);
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ POP_I32(value);
+ set_local_i32(cc->jit_frame, local_offset, value);
+ PUSH_I32(value);
+ break;
+ case VALUE_TYPE_I64:
+ POP_I64(value);
+ set_local_i64(cc->jit_frame, local_offset, value);
+ PUSH_I64(value);
+ break;
+ case VALUE_TYPE_F32:
+ POP_F32(value);
+ set_local_f32(cc->jit_frame, local_offset, value);
+ PUSH_F32(value);
+ break;
+ case VALUE_TYPE_F64:
+ POP_F64(value);
+ set_local_f64(cc->jit_frame, local_offset, value);
+ PUSH_F64(value);
+ break;
+ default:
+ bh_assert(0);
+ goto fail;
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static uint8
+get_global_type(const WASMModule *module, uint32 global_idx)
+{
+ if (global_idx < module->import_global_count) {
+ const WASMGlobalImport *import_global =
+ &((module->import_globals + global_idx)->u.global);
+ return import_global->type;
+ }
+ else {
+ const WASMGlobal *global =
+ module->globals + (global_idx - module->import_global_count);
+ return global->type;
+ }
+}
+
+bool
+jit_compile_op_get_global(JitCompContext *cc, uint32 global_idx)
+{
+ uint32 data_offset;
+ uint8 global_type = 0;
+ JitReg value = 0;
+
+ bh_assert(global_idx < cc->cur_wasm_module->import_global_count
+ + cc->cur_wasm_module->global_count);
+
+ data_offset =
+ jit_frontend_get_global_data_offset(cc->cur_wasm_module, global_idx);
+ global_type = get_global_type(cc->cur_wasm_module, global_idx);
+
+ switch (global_type) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ {
+ value = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ case VALUE_TYPE_I64:
+ {
+ value = jit_cc_new_reg_I64(cc);
+ GEN_INSN(LDI64, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ case VALUE_TYPE_F32:
+ {
+ value = jit_cc_new_reg_F32(cc);
+ GEN_INSN(LDF32, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ case VALUE_TYPE_F64:
+ {
+ value = jit_cc_new_reg_F64(cc);
+ GEN_INSN(LDF64, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ default:
+ {
+ jit_set_last_error(cc, "unexpected global type");
+ goto fail;
+ }
+ }
+
+ PUSH(value, global_type);
+
+ return true;
+fail:
+ return false;
+}
+
+bool
+jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
+ bool is_aux_stack)
+{
+ uint32 data_offset;
+ uint8 global_type = 0;
+ JitReg value = 0;
+
+ bh_assert(global_idx < cc->cur_wasm_module->import_global_count
+ + cc->cur_wasm_module->global_count);
+
+ data_offset =
+ jit_frontend_get_global_data_offset(cc->cur_wasm_module, global_idx);
+ global_type = get_global_type(cc->cur_wasm_module, global_idx);
+
+ switch (global_type) {
+ case VALUE_TYPE_I32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+#endif
+ {
+ POP_I32(value);
+ if (is_aux_stack) {
+ JitReg aux_stack_bound = get_aux_stack_bound_reg(cc->jit_frame);
+ JitReg aux_stack_bottom =
+ get_aux_stack_bottom_reg(cc->jit_frame);
+ GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bound);
+ if (!(jit_emit_exception(cc, EXCE_AUX_STACK_OVERFLOW,
+ JIT_OP_BLEU, cc->cmp_reg, NULL)))
+ goto fail;
+ GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bottom);
+ if (!(jit_emit_exception(cc, EXCE_AUX_STACK_UNDERFLOW,
+ JIT_OP_BGTU, cc->cmp_reg, NULL)))
+ goto fail;
+ }
+ GEN_INSN(STI32, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ case VALUE_TYPE_I64:
+ {
+ POP_I64(value);
+ GEN_INSN(STI64, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ case VALUE_TYPE_F32:
+ {
+ POP_F32(value);
+ GEN_INSN(STF32, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ case VALUE_TYPE_F64:
+ {
+ POP_F64(value);
+ GEN_INSN(STF64, value, get_module_inst_reg(cc->jit_frame),
+ NEW_CONST(I32, data_offset));
+ break;
+ }
+ default:
+ {
+ jit_set_last_error(cc, "unexpected global type");
+ goto fail;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.h
new file mode 100644
index 000000000..80a10511d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/fe/jit_emit_variable.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_EMIT_VARIABLE_H_
+#define _JIT_EMIT_VARIABLE_H_
+
+#include "../jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_compile_op_get_local(JitCompContext *cc, uint32 local_idx);
+
+bool
+jit_compile_op_set_local(JitCompContext *cc, uint32 local_idx);
+
+bool
+jit_compile_op_tee_local(JitCompContext *cc, uint32 local_idx);
+
+bool
+jit_compile_op_get_global(JitCompContext *cc, uint32 global_idx);
+
+bool
+jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
+ bool is_aux_stack);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _JIT_EMIT_VARIABLE_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/iwasm_fast_jit.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/iwasm_fast_jit.cmake
new file mode 100644
index 000000000..cd880a34b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/iwasm_fast_jit.cmake
@@ -0,0 +1,97 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (IWASM_FAST_JIT_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DWASM_ENABLE_FAST_JIT=1)
+if (WAMR_BUILD_FAST_JIT_DUMP EQUAL 1)
+ add_definitions(-DWASM_ENABLE_FAST_JIT_DUMP=1)
+endif ()
+
+include_directories (${IWASM_FAST_JIT_DIR})
+
+if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+ include(FetchContent)
+ if (NOT WAMR_BUILD_PLATFORM STREQUAL "linux-sgx")
+ FetchContent_Declare(
+ asmjit
+ GIT_REPOSITORY https://github.com/asmjit/asmjit.git
+ GIT_TAG c1019f1642a588107148f64ba54584b0ae3ec8d1
+ )
+ else ()
+ FetchContent_Declare(
+ asmjit
+ GIT_REPOSITORY https://github.com/asmjit/asmjit.git
+ GIT_TAG c1019f1642a588107148f64ba54584b0ae3ec8d1
+ PATCH_COMMAND git apply ${IWASM_FAST_JIT_DIR}/asmjit_sgx_patch.diff
+ )
+ endif ()
+ FetchContent_GetProperties(asmjit)
+ if (NOT asmjit_POPULATED)
+ message ("-- Fetching asmjit ..")
+ FetchContent_Populate(asmjit)
+ add_definitions(-DASMJIT_STATIC)
+ add_definitions(-DASMJIT_NO_DEPRECATED)
+ add_definitions(-DASMJIT_NO_BUILDER)
+ add_definitions(-DASMJIT_NO_COMPILER)
+ add_definitions(-DASMJIT_NO_JIT)
+ add_definitions(-DASMJIT_NO_LOGGING)
+ add_definitions(-DASMJIT_NO_TEXT)
+ add_definitions(-DASMJIT_NO_VALIDATION)
+ add_definitions(-DASMJIT_NO_INTROSPECTION)
+ add_definitions(-DASMJIT_NO_INTRINSICS)
+ add_definitions(-DASMJIT_NO_AARCH64)
+ add_definitions(-DASMJIT_NO_AARCH32)
+ include_directories("${asmjit_SOURCE_DIR}/src")
+ add_subdirectory(${asmjit_SOURCE_DIR} ${asmjit_BINARY_DIR} EXCLUDE_FROM_ALL)
+ file (GLOB_RECURSE cpp_source_asmjit
+ ${asmjit_SOURCE_DIR}/src/asmjit/core/*.cpp
+ ${asmjit_SOURCE_DIR}/src/asmjit/x86/*.cpp
+ )
+ endif ()
+ if (WAMR_BUILD_FAST_JIT_DUMP EQUAL 1)
+ FetchContent_Declare(
+ zycore
+ GIT_REPOSITORY https://github.com/zyantific/zycore-c.git
+ )
+ FetchContent_GetProperties(zycore)
+ if (NOT zycore_POPULATED)
+ message ("-- Fetching zycore ..")
+ FetchContent_Populate(zycore)
+ option(ZYDIS_BUILD_TOOLS "" OFF)
+ option(ZYDIS_BUILD_EXAMPLES "" OFF)
+ include_directories("${zycore_SOURCE_DIR}/include")
+ include_directories("${zycore_BINARY_DIR}")
+ add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL)
+ file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c)
+ endif ()
+ FetchContent_Declare(
+ zydis
+ GIT_REPOSITORY https://github.com/zyantific/zydis.git
+ GIT_TAG e14a07895136182a5b53e181eec3b1c6e0b434de
+ )
+ FetchContent_GetProperties(zydis)
+ if (NOT zydis_POPULATED)
+ message ("-- Fetching zydis ..")
+ FetchContent_Populate(zydis)
+ option(ZYDIS_BUILD_TOOLS "" OFF)
+ option(ZYDIS_BUILD_EXAMPLES "" OFF)
+ include_directories("${zydis_BINARY_DIR}")
+ include_directories("${zydis_SOURCE_DIR}/include")
+ include_directories("${zydis_SOURCE_DIR}/src")
+ add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL)
+ file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c)
+ endif ()
+ endif ()
+endif ()
+
+file (GLOB c_source_jit ${IWASM_FAST_JIT_DIR}/*.c ${IWASM_FAST_JIT_DIR}/fe/*.c)
+
+if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+ file (GLOB_RECURSE cpp_source_jit_cg ${IWASM_FAST_JIT_DIR}/cg/x86-64/*.cpp)
+else ()
+ message (FATAL_ERROR "Fast JIT codegen for target ${WAMR_BUILD_TARGET} isn't implemented")
+endif ()
+
+set (IWASM_FAST_JIT_SOURCE ${c_source_jit} ${cpp_source_jit_cg}
+ ${cpp_source_asmjit} ${c_source_zycore} ${c_source_zydis})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.c
new file mode 100644
index 000000000..73a034f34
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_codecache.h"
+#include "mem_alloc.h"
+#include "jit_compiler.h"
+
+static void *code_cache_pool = NULL;
+static uint32 code_cache_pool_size = 0;
+static mem_allocator_t code_cache_pool_allocator = NULL;
+
+bool
+jit_code_cache_init(uint32 code_cache_size)
+{
+ int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
+ int map_flags = MMAP_MAP_NONE;
+
+ if (!(code_cache_pool =
+ os_mmap(NULL, code_cache_size, map_prot, map_flags))) {
+ return false;
+ }
+
+ if (!(code_cache_pool_allocator =
+ mem_allocator_create(code_cache_pool, code_cache_size))) {
+ os_munmap(code_cache_pool, code_cache_size);
+ code_cache_pool = NULL;
+ return false;
+ }
+
+ code_cache_pool_size = code_cache_size;
+ return true;
+}
+
+void
+jit_code_cache_destroy()
+{
+ mem_allocator_destroy(code_cache_pool_allocator);
+ os_munmap(code_cache_pool, code_cache_pool_size);
+}
+
+void *
+jit_code_cache_alloc(uint32 size)
+{
+ return mem_allocator_malloc(code_cache_pool_allocator, size);
+}
+
+void
+jit_code_cache_free(void *ptr)
+{
+ if (ptr)
+ mem_allocator_free(code_cache_pool_allocator, ptr);
+}
+
+bool
+jit_pass_register_jitted_code(JitCompContext *cc)
+{
+ WASMModuleInstance *instance;
+ WASMModule *module = cc->cur_wasm_module;
+ WASMFunction *func = cc->cur_wasm_func;
+ uint32 jit_func_idx = cc->cur_wasm_func_idx - module->import_function_count;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ os_mutex_lock(&module->instance_list_lock);
+#endif
+
+ module->fast_jit_func_ptrs[jit_func_idx] = func->fast_jit_jitted_code =
+ cc->jitted_addr_begin;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ instance = module->instance_list;
+ while (instance) {
+ if (instance->e->running_mode == Mode_Fast_JIT)
+ instance->fast_jit_func_ptrs[jit_func_idx] = cc->jitted_addr_begin;
+ instance = instance->e->next;
+ }
+
+ os_mutex_unlock(&module->instance_list_lock);
+#else
+ (void)instance;
+#endif
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.h
new file mode 100644
index 000000000..953026ad4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codecache.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_CODE_CACHE_H_
+#define _JIT_CODE_CACHE_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+jit_code_cache_init(uint32 code_cache_size);
+
+void
+jit_code_cache_destroy();
+
+void *
+jit_code_cache_alloc(uint32 size);
+
+void
+jit_code_cache_free(void *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _JIT_CODE_CACHE_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.c
new file mode 100644
index 000000000..2bd60bb41
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_compiler.h"
+#include "jit_codegen.h"
+
+bool
+jit_pass_lower_cg(JitCompContext *cc)
+{
+ return jit_codegen_lower(cc);
+}
+
+bool
+jit_pass_codegen(JitCompContext *cc)
+{
+ if (!jit_annl_enable_jitted_addr(cc))
+ return false;
+
+ return jit_codegen_gen_native(cc);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.h
new file mode 100644
index 000000000..735cddab6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_codegen.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_CODEGEN_H_
+#define _JIT_CODEGEN_H_
+
+#include "bh_platform.h"
+#include "jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize codegen module, such as instruction encoder.
+ *
+ * @return true if succeeded; false if failed.
+ */
+bool
+jit_codegen_init();
+
+/**
+ * Destroy codegen module, such as instruction encoder.
+ */
+void
+jit_codegen_destroy();
+
+/**
+ * Get hard register information of each kind.
+ *
+ * @return the JitHardRegInfo array of each kind
+ */
+const JitHardRegInfo *
+jit_codegen_get_hreg_info();
+
+/**
+ * Get hard register by name.
+ *
+ * @param name the name of the hard register
+ *
+ * @return the hard register of the name
+ */
+JitReg
+jit_codegen_get_hreg_by_name(const char *name);
+
+/**
+ * Generate native code for the given compilation context
+ *
+ * @param cc the compilation context that is ready to do codegen
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jit_codegen_gen_native(JitCompContext *cc);
+
+/**
+ * lower unsupported operations to supported ones for the target.
+ *
+ * @param cc the compilation context that is ready to do codegen
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jit_codegen_lower(JitCompContext *cc);
+
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
+void *
+jit_codegen_compile_call_to_llvm_jit(const WASMType *func_type);
+
+void *
+jit_codegen_compile_call_to_fast_jit(const WASMModule *module, uint32 func_idx);
+#endif
+
+/**
+ * Dump native code in the given range to assembly.
+ *
+ * @param begin_addr begin address of the native code
+ * @param end_addr end address of the native code
+ */
+void
+jit_codegen_dump_native(void *begin_addr, void *end_addr);
+
+int
+jit_codegen_interp_jitted_glue(void *self, JitInterpSwitchInfo *info,
+ uint32 func_idx, void *pc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _JIT_CODEGEN_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.c
new file mode 100644
index 000000000..958d0e987
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_compiler.h"
+#include "jit_ir.h"
+#include "jit_codegen.h"
+#include "jit_codecache.h"
+#include "../interpreter/wasm.h"
+
+typedef struct JitCompilerPass {
+ /* Name of the pass */
+ const char *name;
+ /* The entry of the compiler pass */
+ bool (*run)(JitCompContext *cc);
+} JitCompilerPass;
+
+/* clang-format off */
+static JitCompilerPass compiler_passes[] = {
+ { NULL, NULL },
+#define REG_PASS(name) { #name, jit_pass_##name }
+ REG_PASS(dump),
+ REG_PASS(update_cfg),
+ REG_PASS(frontend),
+ REG_PASS(lower_cg),
+ REG_PASS(regalloc),
+ REG_PASS(codegen),
+ REG_PASS(register_jitted_code)
+#undef REG_PASS
+};
+
+/* Number of compiler passes */
+#define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0]))
+
+#if WASM_ENABLE_FAST_JIT_DUMP == 0
+static const uint8 compiler_passes_without_dump[] = {
+ 3, 4, 5, 6, 7, 0
+};
+#else
+static const uint8 compiler_passes_with_dump[] = {
+ 3, 2, 1, 4, 1, 5, 1, 6, 1, 7, 0
+};
+#endif
+
+/* The exported global data of JIT compiler */
+static JitGlobals jit_globals = {
+#if WASM_ENABLE_FAST_JIT_DUMP == 0
+ .passes = compiler_passes_without_dump,
+#else
+ .passes = compiler_passes_with_dump,
+#endif
+ .return_to_interp_from_jitted = NULL,
+#if WASM_ENABLE_LAZY_JIT != 0
+ .compile_fast_jit_and_then_call = NULL,
+#endif
+};
+/* clang-format on */
+
+static bool
+apply_compiler_passes(JitCompContext *cc)
+{
+ const uint8 *p = jit_globals.passes;
+
+ for (; *p; p++) {
+ /* Set the pass NO */
+ cc->cur_pass_no = p - jit_globals.passes;
+ bh_assert(*p < COMPILER_PASS_NUM);
+
+ if (!compiler_passes[*p].run(cc) || jit_get_last_error(cc)) {
+ LOG_VERBOSE("JIT: compilation failed at pass[%td] = %s\n",
+ p - jit_globals.passes, compiler_passes[*p].name);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+jit_compiler_init(const JitCompOptions *options)
+{
+ uint32 code_cache_size = options->code_cache_size > 0
+ ? options->code_cache_size
+ : FAST_JIT_DEFAULT_CODE_CACHE_SIZE;
+
+ LOG_VERBOSE("JIT: compiler init with code cache size: %u\n",
+ code_cache_size);
+
+ if (!jit_code_cache_init(code_cache_size))
+ return false;
+
+ if (!jit_codegen_init())
+ goto fail1;
+
+ return true;
+
+fail1:
+ jit_code_cache_destroy();
+ return false;
+}
+
+void
+jit_compiler_destroy()
+{
+ jit_codegen_destroy();
+
+ jit_code_cache_destroy();
+}
+
+JitGlobals *
+jit_compiler_get_jit_globals()
+{
+ return &jit_globals;
+}
+
+const char *
+jit_compiler_get_pass_name(unsigned i)
+{
+ return i < COMPILER_PASS_NUM ? compiler_passes[i].name : NULL;
+}
+
+bool
+jit_compiler_compile(WASMModule *module, uint32 func_idx)
+{
+ JitCompContext *cc = NULL;
+ char *last_error;
+ bool ret = false;
+ uint32 i = func_idx - module->import_function_count;
+ uint32 j = i % WASM_ORC_JIT_BACKEND_THREAD_NUM;
+
+ /* Lock to avoid duplicated compilation by other threads */
+ os_mutex_lock(&module->fast_jit_thread_locks[j]);
+
+ if (jit_compiler_is_compiled(module, func_idx)) {
+ /* Function has been compiled */
+ os_mutex_unlock(&module->fast_jit_thread_locks[j]);
+ return true;
+ }
+
+ /* Initialize the compilation context */
+ if (!(cc = jit_calloc(sizeof(*cc)))) {
+ goto fail;
+ }
+
+ if (!jit_cc_init(cc, 64)) {
+ goto fail;
+ }
+
+ cc->cur_wasm_module = module;
+ cc->cur_wasm_func = module->functions[i];
+ cc->cur_wasm_func_idx = func_idx;
+ cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow
+ && !cc->cur_wasm_func->has_op_func_call)
+ || (!module->possible_memory_grow);
+
+ /* Apply compiler passes */
+ if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
+ last_error = jit_get_last_error(cc);
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ char *function_name = cc->cur_wasm_func->field_name;
+ os_printf("fast jit compilation failed: %s (function_name=%s)\n",
+ last_error ? last_error : "unknown error", function_name);
+#else
+ os_printf("fast jit compilation failed: %s\n",
+ last_error ? last_error : "unknown error");
+#endif
+
+ goto fail;
+ }
+
+ ret = true;
+
+fail:
+ /* Destroy the compilation context */
+ if (cc)
+ jit_cc_delete(cc);
+
+ os_mutex_unlock(&module->fast_jit_thread_locks[j]);
+
+ return ret;
+}
+
+bool
+jit_compiler_compile_all(WASMModule *module)
+{
+ uint32 i;
+
+ for (i = 0; i < module->function_count; i++) {
+ if (!jit_compiler_compile(module, module->import_function_count + i)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+jit_compiler_is_compiled(const WASMModule *module, uint32 func_idx)
+{
+ uint32 i = func_idx - module->import_function_count;
+
+ bh_assert(func_idx >= module->import_function_count
+ && func_idx
+ < module->import_function_count + module->function_count);
+
+#if WASM_ENABLE_LAZY_JIT == 0
+ return module->fast_jit_func_ptrs[i] ? true : false;
+#else
+ return module->fast_jit_func_ptrs[i]
+ != jit_globals.compile_fast_jit_and_then_call
+ ? true
+ : false;
+#endif
+}
+
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
+bool
+jit_compiler_set_call_to_llvm_jit(WASMModule *module, uint32 func_idx)
+{
+ uint32 i = func_idx - module->import_function_count;
+ uint32 j = i % WASM_ORC_JIT_BACKEND_THREAD_NUM;
+ WASMType *func_type = module->functions[i]->func_type;
+ uint32 k =
+ ((uint32)(uintptr_t)func_type >> 3) % WASM_ORC_JIT_BACKEND_THREAD_NUM;
+ void *func_ptr = NULL;
+
+ /* Compile code block of call_to_llvm_jit_from_fast_jit of
+ this kind of function type if it hasn't been compiled */
+ if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit)) {
+ os_mutex_lock(&module->fast_jit_thread_locks[k]);
+ if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit)) {
+ if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit =
+ jit_codegen_compile_call_to_llvm_jit(func_type))) {
+ os_mutex_unlock(&module->fast_jit_thread_locks[k]);
+ return false;
+ }
+ }
+ os_mutex_unlock(&module->fast_jit_thread_locks[k]);
+ }
+
+ /* Switch current fast jit func ptr to the code block */
+ os_mutex_lock(&module->fast_jit_thread_locks[j]);
+ module->fast_jit_func_ptrs[i] = func_ptr;
+ os_mutex_unlock(&module->fast_jit_thread_locks[j]);
+ return true;
+}
+
+bool
+jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx)
+{
+ void *func_ptr = NULL;
+
+ func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx);
+ if (func_ptr) {
+ uint32 i = func_idx - module->import_function_count;
+ module->functions[i]->call_to_fast_jit_from_llvm_jit = func_ptr;
+ jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr);
+ }
+
+ return func_ptr ? true : false;
+}
+
+void
+jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
+ void *func_ptr)
+{
+ WASMModuleInstance *instance;
+ uint32 i = func_idx - module->import_function_count;
+
+ os_mutex_lock(&module->instance_list_lock);
+
+ module->func_ptrs[i] = func_ptr;
+
+ instance = module->instance_list;
+ while (instance) {
+ if (instance->e->running_mode == Mode_Multi_Tier_JIT)
+ instance->func_ptrs[func_idx] = func_ptr;
+ instance = instance->e->next;
+ }
+ os_mutex_unlock(&module->instance_list_lock);
+}
+#endif /* end of WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 */
+
+int
+jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info,
+ uint32 func_idx, void *pc)
+{
+ return jit_codegen_interp_jitted_glue(exec_env, info, func_idx, pc);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.h
new file mode 100644
index 000000000..9a49cffdd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_compiler.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_COMPILER_H_
+#define _JIT_COMPILER_H_
+
+#include "bh_platform.h"
+#include "../interpreter/wasm_runtime.h"
+#include "jit_ir.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct JitGlobals {
+ /* Compiler pass sequence, the last element must be 0 */
+ const uint8 *passes;
+ char *return_to_interp_from_jitted;
+#if WASM_ENABLE_LAZY_JIT != 0
+ char *compile_fast_jit_and_then_call;
+#endif
+} JitGlobals;
+
+/**
+ * Actions the interpreter should do when jitted code returns to
+ * interpreter.
+ */
+typedef enum JitInterpAction {
+ JIT_INTERP_ACTION_NORMAL, /* normal execution */
+ JIT_INTERP_ACTION_THROWN, /* exception was thrown */
+ JIT_INTERP_ACTION_CALL /* call wasm function */
+} JitInterpAction;
+
+/**
+ * Information exchanged between jitted code and interpreter.
+ */
+typedef struct JitInterpSwitchInfo {
+ /* Points to the frame that is passed to jitted code and the frame
+ that is returned from jitted code */
+ void *frame;
+
+ /* Output values from jitted code of different actions */
+ union {
+ /* IP and SP offsets for NORMAL */
+ struct {
+ int32 ip;
+ int32 sp;
+ } normal;
+
+ /* Function called from jitted code for CALL */
+ struct {
+ void *function;
+ } call;
+
+ /* Returned integer and/or floating point values for RETURN. This
+ is also used to pass return values from interpreter to jitted
+ code if the caller is in jitted code and the callee is in
+ interpreter. */
+ struct {
+ uint32 ival[2];
+ uint32 fval[2];
+ uint32 last_return_type;
+ } ret;
+ } out;
+} JitInterpSwitchInfo;
+
+/* Jit compiler options */
+typedef struct JitCompOptions {
+ uint32 code_cache_size;
+ uint32 opt_level;
+} JitCompOptions;
+
+bool
+jit_compiler_init(const JitCompOptions *option);
+
+void
+jit_compiler_destroy();
+
+JitGlobals *
+jit_compiler_get_jit_globals();
+
+const char *
+jit_compiler_get_pass_name(unsigned i);
+
+bool
+jit_compiler_compile(WASMModule *module, uint32 func_idx);
+
+bool
+jit_compiler_compile_all(WASMModule *module);
+
+bool
+jit_compiler_is_compiled(const WASMModule *module, uint32 func_idx);
+
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
+bool
+jit_compiler_set_call_to_llvm_jit(WASMModule *module, uint32 func_idx);
+
+bool
+jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx);
+
+void
+jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
+ void *func_ptr);
+#endif
+
+int
+jit_interp_switch_to_jitted(void *self, JitInterpSwitchInfo *info,
+ uint32 func_idx, void *pc);
+
+/*
+ * Pass declarations:
+ */
+
+/**
+ * Dump the compilation context.
+ */
+bool
+jit_pass_dump(JitCompContext *cc);
+
+/**
+ * Update CFG (usually before dump for better readability).
+ */
+bool
+jit_pass_update_cfg(JitCompContext *cc);
+
+/**
+ * Translate profiling result into MIR.
+ */
+bool
+jit_pass_frontend(JitCompContext *cc);
+
+/**
+ * Lower unsupported operations into supported ones.
+ */
+bool
+jit_pass_lower_cg(JitCompContext *cc);
+
+/**
+ * Register allocation.
+ */
+bool
+jit_pass_regalloc(JitCompContext *cc);
+
+/**
+ * Native code generation.
+ */
+bool
+jit_pass_codegen(JitCompContext *cc);
+
+/**
+ * Register the jitted code so that it can be executed.
+ */
+bool
+jit_pass_register_jitted_code(JitCompContext *cc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _JIT_COMPILER_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.c
new file mode 100644
index 000000000..d61ed5dc7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_dump.h"
+#include "jit_compiler.h"
+#include "jit_codegen.h"
+
+void
+jit_dump_reg(JitCompContext *cc, JitReg reg)
+{
+ unsigned kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+
+ switch (kind) {
+ case JIT_REG_KIND_VOID:
+ os_printf("VOID");
+ break;
+
+ case JIT_REG_KIND_I32:
+ if (jit_reg_is_const(reg)) {
+ unsigned rel = jit_cc_get_const_I32_rel(cc, reg);
+
+ os_printf("0x%x", jit_cc_get_const_I32(cc, reg));
+
+ if (rel)
+ os_printf("(rel: 0x%x)", rel);
+ }
+ else
+ os_printf("i%d", no);
+ break;
+
+ case JIT_REG_KIND_I64:
+ if (jit_reg_is_const(reg))
+ os_printf("0x%llxL", jit_cc_get_const_I64(cc, reg));
+ else
+ os_printf("I%d", no);
+ break;
+
+ case JIT_REG_KIND_F32:
+ if (jit_reg_is_const(reg))
+ os_printf("%f", jit_cc_get_const_F32(cc, reg));
+ else
+ os_printf("f%d", no);
+ break;
+
+ case JIT_REG_KIND_F64:
+ if (jit_reg_is_const(reg))
+ os_printf("%fL", jit_cc_get_const_F64(cc, reg));
+ else
+ os_printf("D%d", no);
+ break;
+
+ case JIT_REG_KIND_L32:
+ os_printf("L%d", no);
+ break;
+
+ default:
+ bh_assert(!"Unsupported register kind.");
+ }
+}
+
+static void
+jit_dump_insn_Reg(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
+{
+ unsigned i;
+
+ for (i = 0; i < opnd_num; i++) {
+ os_printf(i == 0 ? " " : ", ");
+ jit_dump_reg(cc, *(jit_insn_opnd(insn, i)));
+ }
+
+ os_printf("\n");
+}
+
+static void
+jit_dump_insn_VReg(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
+{
+ unsigned i;
+
+ opnd_num = jit_insn_opndv_num(insn);
+
+ for (i = 0; i < opnd_num; i++) {
+ os_printf(i == 0 ? " " : ", ");
+ jit_dump_reg(cc, *(jit_insn_opndv(insn, i)));
+ }
+
+ os_printf("\n");
+}
+
+static void
+jit_dump_insn_LookupSwitch(JitCompContext *cc, JitInsn *insn, unsigned opnd_num)
+{
+ unsigned i;
+ JitOpndLookupSwitch *opnd = jit_insn_opndls(insn);
+
+ os_printf(" ");
+ jit_dump_reg(cc, opnd->value);
+ os_printf("\n%16s: ", "default");
+ jit_dump_reg(cc, opnd->default_target);
+ os_printf("\n");
+
+ for (i = 0; i < opnd->match_pairs_num; i++) {
+ os_printf("%18d: ", opnd->match_pairs[i].value);
+ jit_dump_reg(cc, opnd->match_pairs[i].target);
+ os_printf("\n");
+ }
+}
+
+void
+jit_dump_insn(JitCompContext *cc, JitInsn *insn)
+{
+ switch (insn->opcode) {
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE) \
+ case JIT_OP_##NAME: \
+ if (insn->flags_u8 & 0x1) \
+ os_printf(" ATOMIC %-8s", #NAME); \
+ else \
+ os_printf(" %-15s", #NAME); \
+ jit_dump_insn_##OPND_KIND(cc, insn, OPND_NUM); \
+ break;
+#include "jit_ir.def"
+#undef INSN
+ }
+}
+
+void
+jit_dump_basic_block(JitCompContext *cc, JitBasicBlock *block)
+{
+ unsigned i, label_index;
+ void *begin_addr, *end_addr;
+ JitBasicBlock *block_next;
+ JitInsn *insn;
+ JitRegVec preds = jit_basic_block_preds(block);
+ JitRegVec succs = jit_basic_block_succs(block);
+ JitReg label = jit_basic_block_label(block), label_next;
+ JitReg *reg;
+
+ jit_dump_reg(cc, label);
+ os_printf(":\n ; PREDS(");
+
+ JIT_REG_VEC_FOREACH(preds, i, reg)
+ {
+ if (i > 0)
+ os_printf(" ");
+ jit_dump_reg(cc, *reg);
+ }
+
+ os_printf(")\n ;");
+
+ if (jit_annl_is_enabled_begin_bcip(cc))
+ os_printf(" BEGIN_BCIP=0x%04tx",
+ *(jit_annl_begin_bcip(cc, label))
+ - (uint8 *)cc->cur_wasm_module->load_addr);
+
+ if (jit_annl_is_enabled_end_bcip(cc))
+ os_printf(" END_BCIP=0x%04tx",
+ *(jit_annl_end_bcip(cc, label))
+ - (uint8 *)cc->cur_wasm_module->load_addr);
+ os_printf("\n");
+
+ if (jit_annl_is_enabled_jitted_addr(cc)) {
+ begin_addr = *(jit_annl_jitted_addr(cc, label));
+
+ if (label == cc->entry_label) {
+ block_next = cc->_ann._label_basic_block[2];
+ label_next = jit_basic_block_label(block_next);
+ end_addr = *(jit_annl_jitted_addr(cc, label_next));
+ }
+ else if (label == cc->exit_label) {
+ end_addr = cc->jitted_addr_end;
+ }
+ else {
+ label_index = jit_reg_no(label);
+ if (label_index < jit_cc_label_num(cc) - 1)
+ block_next = cc->_ann._label_basic_block[label_index + 1];
+ else
+ block_next = cc->_ann._label_basic_block[1];
+ label_next = jit_basic_block_label(block_next);
+ end_addr = *(jit_annl_jitted_addr(cc, label_next));
+ }
+
+ jit_codegen_dump_native(begin_addr, end_addr);
+ }
+ else {
+ /* Dump IR. */
+ JIT_FOREACH_INSN(block, insn) jit_dump_insn(cc, insn);
+ }
+
+ os_printf(" ; SUCCS(");
+
+ JIT_REG_VEC_FOREACH(succs, i, reg)
+ {
+ if (i > 0)
+ os_printf(" ");
+ jit_dump_reg(cc, *reg);
+ }
+
+ os_printf(")\n\n");
+}
+
+static void
+dump_func_name(JitCompContext *cc)
+{
+ const char *func_name = NULL;
+ WASMModule *module = cc->cur_wasm_module;
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ func_name = cc->cur_wasm_func->field_name;
+#endif
+
+ /* if custom name section is not generated,
+ search symbols from export table */
+ if (!func_name) {
+ uint32 i;
+ for (i = 0; i < module->export_count; i++) {
+ if (module->exports[i].kind == EXPORT_KIND_FUNC
+ && module->exports[i].index == cc->cur_wasm_func_idx) {
+ func_name = module->exports[i].name;
+ break;
+ }
+ }
+ }
+
+ /* function name not exported, print number instead */
+ if (func_name == NULL) {
+ os_printf("$f%d", cc->cur_wasm_func_idx);
+ }
+ else {
+ os_printf("%s", func_name);
+ }
+}
+
+static void
+dump_cc_ir(JitCompContext *cc)
+{
+ unsigned i, end;
+ JitBasicBlock *block;
+ JitReg label;
+ const char *kind_names[] = { "VOID", "I32", "I64", "F32",
+ "F64", "V64", "V128", "V256" };
+
+ os_printf("; Function: ");
+ dump_func_name(cc);
+ os_printf("\n");
+
+ os_printf("; Constant table sizes:");
+
+ for (i = 0; i < JIT_REG_KIND_L32; i++)
+ os_printf(" %s=%d", kind_names[i], cc->_const_val._num[i]);
+
+ os_printf("\n; Label number: %d", jit_cc_label_num(cc));
+ os_printf("\n; Instruction number: %d", jit_cc_insn_num(cc));
+ os_printf("\n; Register numbers:");
+
+ for (i = 0; i < JIT_REG_KIND_L32; i++)
+ os_printf(" %s=%d", kind_names[i], jit_cc_reg_num(cc, i));
+
+ os_printf("\n; Label annotations:");
+#define ANN_LABEL(TYPE, NAME) \
+ if (jit_annl_is_enabled_##NAME(cc)) \
+ os_printf(" %s", #NAME);
+#include "jit_ir.def"
+#undef ANN_LABEL
+
+ os_printf("\n; Instruction annotations:");
+#define ANN_INSN(TYPE, NAME) \
+ if (jit_anni_is_enabled_##NAME(cc)) \
+ os_printf(" %s", #NAME);
+#include "jit_ir.def"
+#undef ANN_INSN
+
+ os_printf("\n; Register annotations:");
+#define ANN_REG(TYPE, NAME) \
+ if (jit_annr_is_enabled_##NAME(cc)) \
+ os_printf(" %s", #NAME);
+#include "jit_ir.def"
+#undef ANN_REG
+
+ os_printf("\n\n");
+
+ if (jit_annl_is_enabled_next_label(cc)) {
+ /* Blocks have been reordered, use that order to dump. */
+ for (label = cc->entry_label; label;
+ label = *(jit_annl_next_label(cc, label)))
+ jit_dump_basic_block(cc, *(jit_annl_basic_block(cc, label)));
+ }
+ else {
+ /* Otherwise, use the default order. */
+ jit_dump_basic_block(cc, jit_cc_entry_basic_block(cc));
+
+ JIT_FOREACH_BLOCK(cc, i, end, block) jit_dump_basic_block(cc, block);
+
+ jit_dump_basic_block(cc, jit_cc_exit_basic_block(cc));
+ }
+}
+
+void
+jit_dump_cc(JitCompContext *cc)
+{
+ if (jit_cc_label_num(cc) <= 2)
+ return;
+
+ dump_cc_ir(cc);
+}
+
+bool
+jit_pass_dump(JitCompContext *cc)
+{
+ const JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+ const uint8 *passes = jit_globals->passes;
+ uint8 pass_no = cc->cur_pass_no;
+ const char *pass_name =
+ pass_no > 0 ? jit_compiler_get_pass_name(passes[pass_no - 1]) : "NULL";
+
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+ if (!strcmp(pass_name, "lower_cg"))
+ /* Ignore lower codegen pass as it does nothing in x86-64 */
+ return true;
+#endif
+
+ os_printf("JIT.COMPILER.DUMP: PASS_NO=%d PREV_PASS=%s\n\n", pass_no,
+ pass_name);
+
+ jit_dump_cc(cc);
+
+ os_printf("\n");
+ return true;
+}
+
+bool
+jit_pass_update_cfg(JitCompContext *cc)
+{
+ return jit_cc_update_cfg(cc);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.h
new file mode 100644
index 000000000..8e572b88d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_dump.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_DUMP_H_
+#define _JIT_DUMP_H_
+
+#include "jit_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Dump a register.
+ *
+ * @param cc compilation context of the register
+ * @param reg register to be dumped
+ */
+void
+jit_dump_reg(JitCompContext *cc, JitReg reg);
+
+/**
+ * Dump an instruction.
+ *
+ * @param cc compilation context of the instruction
+ * @param insn instruction to be dumped
+ */
+void
+jit_dump_insn(JitCompContext *cc, JitInsn *insn);
+
+/**
+ * Dump a block.
+ *
+ * @param cc compilation context of the block
+ * @param block block to be dumped
+ */
+void
+jit_dump_block(JitCompContext *cc, JitBlock *block);
+
+/**
+ * Dump a compilation context.
+ *
+ * @param cc compilation context to be dumped
+ */
+void
+jit_dump_cc(JitCompContext *cc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _JIT_DUMP_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.c
new file mode 100644
index 000000000..ec68ad91d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.c
@@ -0,0 +1,2387 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_compiler.h"
+#include "jit_frontend.h"
+#include "fe/jit_emit_compare.h"
+#include "fe/jit_emit_const.h"
+#include "fe/jit_emit_control.h"
+#include "fe/jit_emit_conversion.h"
+#include "fe/jit_emit_exception.h"
+#include "fe/jit_emit_function.h"
+#include "fe/jit_emit_memory.h"
+#include "fe/jit_emit_numberic.h"
+#include "fe/jit_emit_parametric.h"
+#include "fe/jit_emit_table.h"
+#include "fe/jit_emit_variable.h"
+#include "../interpreter/wasm_interp.h"
+#include "../interpreter/wasm_opcode.h"
+#include "../interpreter/wasm_runtime.h"
+#include "../common/wasm_exec_env.h"
+
+static uint32
+get_global_base_offset(const WASMModule *module)
+{
+ uint32 module_inst_struct_size =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes);
+ uint32 mem_inst_size =
+ (uint32)sizeof(WASMMemoryInstance)
+ * (module->import_memory_count + module->memory_count);
+
+#if WASM_ENABLE_JIT != 0
+ /* If the module dosen't have memory, reserve one mem_info space
+ with empty content to align with llvm jit compiler */
+ if (mem_inst_size == 0)
+ mem_inst_size = (uint32)sizeof(WASMMemoryInstance);
+#endif
+
+ /* Size of module inst and memory instances */
+ return module_inst_struct_size + mem_inst_size;
+}
+
+static uint32
+get_first_table_inst_offset(const WASMModule *module)
+{
+ return get_global_base_offset(module) + module->global_data_size;
+}
+
+uint32
+jit_frontend_get_global_data_offset(const WASMModule *module, uint32 global_idx)
+{
+ uint32 global_base_offset = get_global_base_offset(module);
+
+ if (global_idx < module->import_global_count) {
+ const WASMGlobalImport *import_global =
+ &((module->import_globals + global_idx)->u.global);
+ return global_base_offset + import_global->data_offset;
+ }
+ else {
+ const WASMGlobal *global =
+ module->globals + (global_idx - module->import_global_count);
+ return global_base_offset + global->data_offset;
+ }
+}
+
+uint32
+jit_frontend_get_table_inst_offset(const WASMModule *module, uint32 tbl_idx)
+{
+ uint32 offset, i = 0;
+
+ offset = get_first_table_inst_offset(module);
+
+ while (i < tbl_idx && i < module->import_table_count) {
+ WASMTableImport *import_table = &module->import_tables[i].u.table;
+
+ offset += (uint32)offsetof(WASMTableInstance, elems);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ offset += (uint32)sizeof(uint32) * import_table->max_size;
+#else
+ offset += (uint32)sizeof(uint32)
+ * (import_table->possible_grow ? import_table->max_size
+ : import_table->init_size);
+#endif
+
+ i++;
+ }
+
+ if (i == tbl_idx) {
+ return offset;
+ }
+
+ tbl_idx -= module->import_table_count;
+ i -= module->import_table_count;
+ while (i < tbl_idx && i < module->table_count) {
+ WASMTable *table = module->tables + i;
+
+ offset += (uint32)offsetof(WASMTableInstance, elems);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ offset += (uint32)sizeof(uint32) * table->max_size;
+#else
+ offset += (uint32)sizeof(uint32)
+ * (table->possible_grow ? table->max_size : table->init_size);
+#endif
+
+ i++;
+ }
+
+ return offset;
+}
+
+uint32
+jit_frontend_get_module_inst_extra_offset(const WASMModule *module)
+{
+ uint32 offset = jit_frontend_get_table_inst_offset(
+ module, module->import_table_count + module->table_count);
+
+ return align_uint(offset, 8);
+}
+
+JitReg
+get_module_inst_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+
+ if (!frame->module_inst_reg) {
+ frame->module_inst_reg = cc->module_inst_reg;
+ GEN_INSN(LDPTR, frame->module_inst_reg, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, module_inst)));
+ }
+ return frame->module_inst_reg;
+}
+
+JitReg
+get_module_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+
+ if (!frame->module_reg) {
+ frame->module_reg = cc->module_reg;
+ GEN_INSN(LDPTR, frame->module_reg, module_inst_reg,
+ NEW_CONST(I32, offsetof(WASMModuleInstance, module)));
+ }
+ return frame->module_reg;
+}
+
+JitReg
+get_import_func_ptrs_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+
+ if (!frame->import_func_ptrs_reg) {
+ frame->import_func_ptrs_reg = cc->import_func_ptrs_reg;
+ GEN_INSN(
+ LDPTR, frame->import_func_ptrs_reg, module_inst_reg,
+ NEW_CONST(I32, offsetof(WASMModuleInstance, import_func_ptrs)));
+ }
+ return frame->import_func_ptrs_reg;
+}
+
+JitReg
+get_fast_jit_func_ptrs_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+
+ if (!frame->fast_jit_func_ptrs_reg) {
+ frame->fast_jit_func_ptrs_reg = cc->fast_jit_func_ptrs_reg;
+ GEN_INSN(
+ LDPTR, frame->fast_jit_func_ptrs_reg, module_inst_reg,
+ NEW_CONST(I32, offsetof(WASMModuleInstance, fast_jit_func_ptrs)));
+ }
+ return frame->fast_jit_func_ptrs_reg;
+}
+
+JitReg
+get_func_type_indexes_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+
+ if (!frame->func_type_indexes_reg) {
+ frame->func_type_indexes_reg = cc->func_type_indexes_reg;
+ GEN_INSN(
+ LDPTR, frame->func_type_indexes_reg, module_inst_reg,
+ NEW_CONST(I32, offsetof(WASMModuleInstance, func_type_indexes)));
+ }
+ return frame->func_type_indexes_reg;
+}
+
+JitReg
+get_aux_stack_bound_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+
+ if (!frame->aux_stack_bound_reg) {
+ frame->aux_stack_bound_reg = cc->aux_stack_bound_reg;
+ GEN_INSN(
+ LDI32, frame->aux_stack_bound_reg, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, aux_stack_boundary.boundary)));
+ }
+ return frame->aux_stack_bound_reg;
+}
+
+JitReg
+get_aux_stack_bottom_reg(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+
+ if (!frame->aux_stack_bottom_reg) {
+ frame->aux_stack_bottom_reg = cc->aux_stack_bottom_reg;
+ GEN_INSN(
+ LDI32, frame->aux_stack_bottom_reg, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, aux_stack_bottom.bottom)));
+ }
+ return frame->aux_stack_bottom_reg;
+}
+
+JitReg
+get_memory_data_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 memory_data_offset;
+
+ bh_assert(mem_idx == 0);
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ uint32 memories_offset = (uint32)offsetof(WASMModuleInstance, memories);
+ JitReg memories_addr = jit_cc_new_reg_ptr(cc);
+ JitReg memories_0_addr = jit_cc_new_reg_ptr(cc);
+ memory_data_offset = (uint32)offsetof(WASMMemoryInstance, memory_data);
+ if (!frame->memory_regs[mem_idx].memory_data) {
+ frame->memory_regs[mem_idx].memory_data =
+ cc->memory_regs[mem_idx].memory_data;
+ /* module_inst->memories */
+ GEN_INSN(LDPTR, memories_addr, module_inst_reg,
+ NEW_CONST(I32, memories_offset));
+ /* module_inst->memories[0] */
+ GEN_INSN(LDPTR, memories_0_addr, memories_addr, NEW_CONST(I32, 0));
+ /* memories[0]->memory_data */
+ GEN_INSN(LDPTR, frame->memory_regs[mem_idx].memory_data,
+ memories_0_addr, NEW_CONST(I32, memory_data_offset));
+ }
+#else
+ memory_data_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, memory_data);
+ if (!frame->memory_regs[mem_idx].memory_data) {
+ frame->memory_regs[mem_idx].memory_data =
+ cc->memory_regs[mem_idx].memory_data;
+ GEN_INSN(LDPTR, frame->memory_regs[mem_idx].memory_data,
+ module_inst_reg, NEW_CONST(I32, memory_data_offset));
+ }
+#endif
+ return frame->memory_regs[mem_idx].memory_data;
+}
+
+JitReg
+get_memory_data_end_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 memory_data_end_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, memory_data_end);
+
+ bh_assert(mem_idx == 0);
+
+ if (!frame->memory_regs[mem_idx].memory_data_end) {
+ frame->memory_regs[mem_idx].memory_data_end =
+ cc->memory_regs[mem_idx].memory_data_end;
+ GEN_INSN(LDPTR, frame->memory_regs[mem_idx].memory_data_end,
+ module_inst_reg, NEW_CONST(I32, memory_data_end_offset));
+ }
+ return frame->memory_regs[mem_idx].memory_data_end;
+}
+
+JitReg
+get_mem_bound_check_1byte_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 mem_bound_check_1byte_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, mem_bound_check_1byte);
+
+ bh_assert(mem_idx == 0);
+
+ if (!frame->memory_regs[mem_idx].mem_bound_check_1byte) {
+ frame->memory_regs[mem_idx].mem_bound_check_1byte =
+ cc->memory_regs[mem_idx].mem_bound_check_1byte;
+#if UINTPTR_MAX == UINT64_MAX
+ GEN_INSN(LDI64, frame->memory_regs[mem_idx].mem_bound_check_1byte,
+ module_inst_reg, NEW_CONST(I32, mem_bound_check_1byte_offset));
+#else
+ GEN_INSN(LDI32, frame->memory_regs[mem_idx].mem_bound_check_1byte,
+ module_inst_reg, NEW_CONST(I32, mem_bound_check_1byte_offset));
+#endif
+ }
+ return frame->memory_regs[mem_idx].mem_bound_check_1byte;
+}
+
+JitReg
+get_mem_bound_check_2bytes_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 mem_bound_check_2bytes_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, mem_bound_check_2bytes);
+
+ bh_assert(mem_idx == 0);
+
+ if (!frame->memory_regs[mem_idx].mem_bound_check_2bytes) {
+ frame->memory_regs[mem_idx].mem_bound_check_2bytes =
+ cc->memory_regs[mem_idx].mem_bound_check_2bytes;
+#if UINTPTR_MAX == UINT64_MAX
+ GEN_INSN(LDI64, frame->memory_regs[mem_idx].mem_bound_check_2bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_2bytes_offset));
+#else
+ GEN_INSN(LDI32, frame->memory_regs[mem_idx].mem_bound_check_2bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_2bytes_offset));
+#endif
+ }
+ return frame->memory_regs[mem_idx].mem_bound_check_2bytes;
+}
+
+JitReg
+get_mem_bound_check_4bytes_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 mem_bound_check_4bytes_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, mem_bound_check_4bytes);
+
+ bh_assert(mem_idx == 0);
+
+ if (!frame->memory_regs[mem_idx].mem_bound_check_4bytes) {
+ frame->memory_regs[mem_idx].mem_bound_check_4bytes =
+ cc->memory_regs[mem_idx].mem_bound_check_4bytes;
+#if UINTPTR_MAX == UINT64_MAX
+ GEN_INSN(LDI64, frame->memory_regs[mem_idx].mem_bound_check_4bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_4bytes_offset));
+#else
+ GEN_INSN(LDI32, frame->memory_regs[mem_idx].mem_bound_check_4bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_4bytes_offset));
+#endif
+ }
+ return frame->memory_regs[mem_idx].mem_bound_check_4bytes;
+}
+
+JitReg
+get_mem_bound_check_8bytes_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 mem_bound_check_8bytes_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, mem_bound_check_8bytes);
+
+ bh_assert(mem_idx == 0);
+
+ if (!frame->memory_regs[mem_idx].mem_bound_check_8bytes) {
+ frame->memory_regs[mem_idx].mem_bound_check_8bytes =
+ cc->memory_regs[mem_idx].mem_bound_check_8bytes;
+#if UINTPTR_MAX == UINT64_MAX
+ GEN_INSN(LDI64, frame->memory_regs[mem_idx].mem_bound_check_8bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_8bytes_offset));
+#else
+ GEN_INSN(LDI32, frame->memory_regs[mem_idx].mem_bound_check_8bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_8bytes_offset));
+#endif
+ }
+ return frame->memory_regs[mem_idx].mem_bound_check_8bytes;
+}
+
+JitReg
+get_mem_bound_check_16bytes_reg(JitFrame *frame, uint32 mem_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst_reg = get_module_inst_reg(frame);
+ uint32 mem_bound_check_16bytes_offset =
+ (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
+ + (uint32)offsetof(WASMMemoryInstance, mem_bound_check_16bytes);
+
+ bh_assert(mem_idx == 0);
+
+ if (!frame->memory_regs[mem_idx].mem_bound_check_16bytes) {
+ frame->memory_regs[mem_idx].mem_bound_check_16bytes =
+ cc->memory_regs[mem_idx].mem_bound_check_16bytes;
+#if UINTPTR_MAX == UINT64_MAX
+ GEN_INSN(LDI64, frame->memory_regs[mem_idx].mem_bound_check_16bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_16bytes_offset));
+#else
+ GEN_INSN(LDI32, frame->memory_regs[mem_idx].mem_bound_check_16bytes,
+ module_inst_reg,
+ NEW_CONST(I32, mem_bound_check_16bytes_offset));
+#endif
+ }
+ return frame->memory_regs[mem_idx].mem_bound_check_16bytes;
+}
+
+JitReg
+get_table_elems_reg(JitFrame *frame, uint32 tbl_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst = get_module_inst_reg(frame);
+ uint32 offset =
+ jit_frontend_get_table_inst_offset(cc->cur_wasm_module, tbl_idx)
+ + (uint32)offsetof(WASMTableInstance, elems);
+
+ if (!frame->table_regs[tbl_idx].table_elems) {
+ frame->table_regs[tbl_idx].table_elems =
+ cc->table_regs[tbl_idx].table_elems;
+ GEN_INSN(ADD, frame->table_regs[tbl_idx].table_elems, module_inst,
+ NEW_CONST(PTR, offset));
+ }
+ return frame->table_regs[tbl_idx].table_elems;
+}
+
+JitReg
+get_table_cur_size_reg(JitFrame *frame, uint32 tbl_idx)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg module_inst = get_module_inst_reg(frame);
+ uint32 offset =
+ jit_frontend_get_table_inst_offset(cc->cur_wasm_module, tbl_idx)
+ + (uint32)offsetof(WASMTableInstance, cur_size);
+
+ if (!frame->table_regs[tbl_idx].table_cur_size) {
+ frame->table_regs[tbl_idx].table_cur_size =
+ cc->table_regs[tbl_idx].table_cur_size;
+ GEN_INSN(LDI32, frame->table_regs[tbl_idx].table_cur_size, module_inst,
+ NEW_CONST(I32, offset));
+ }
+ return frame->table_regs[tbl_idx].table_cur_size;
+}
+
+void
+clear_fixed_virtual_regs(JitFrame *frame)
+{
+ WASMModule *module = frame->cc->cur_wasm_module;
+ uint32 count, i;
+
+ frame->module_inst_reg = 0;
+ frame->module_reg = 0;
+ frame->import_func_ptrs_reg = 0;
+ frame->fast_jit_func_ptrs_reg = 0;
+ frame->func_type_indexes_reg = 0;
+ frame->aux_stack_bound_reg = 0;
+ frame->aux_stack_bottom_reg = 0;
+
+ count = module->import_memory_count + module->memory_count;
+ for (i = 0; i < count; i++) {
+ frame->memory_regs[i].memory_data = 0;
+ frame->memory_regs[i].memory_data_end = 0;
+ frame->memory_regs[i].mem_bound_check_1byte = 0;
+ frame->memory_regs[i].mem_bound_check_2bytes = 0;
+ frame->memory_regs[i].mem_bound_check_4bytes = 0;
+ frame->memory_regs[i].mem_bound_check_8bytes = 0;
+ frame->memory_regs[i].mem_bound_check_16bytes = 0;
+ }
+
+ count = module->import_table_count + module->table_count;
+ for (i = 0; i < count; i++) {
+ frame->table_regs[i].table_elems = 0;
+ frame->table_regs[i].table_cur_size = 0;
+ }
+}
+
+void
+clear_memory_regs(JitFrame *frame)
+{
+ WASMModule *module = frame->cc->cur_wasm_module;
+ uint32 count, i;
+
+ count = module->import_memory_count + module->memory_count;
+ for (i = 0; i < count; i++) {
+ frame->memory_regs[i].memory_data = 0;
+ frame->memory_regs[i].memory_data_end = 0;
+ frame->memory_regs[i].mem_bound_check_1byte = 0;
+ frame->memory_regs[i].mem_bound_check_2bytes = 0;
+ frame->memory_regs[i].mem_bound_check_4bytes = 0;
+ frame->memory_regs[i].mem_bound_check_8bytes = 0;
+ frame->memory_regs[i].mem_bound_check_16bytes = 0;
+ }
+}
+
+void
+clear_table_regs(JitFrame *frame)
+{
+ WASMModule *module = frame->cc->cur_wasm_module;
+ uint32 count, i;
+
+ count = module->import_table_count + module->table_count;
+ for (i = 0; i < count; i++) {
+ frame->table_regs[i].table_cur_size = 0;
+ }
+}
+
+JitReg
+gen_load_i32(JitFrame *frame, unsigned n)
+{
+ if (!frame->lp[n].reg) {
+ JitCompContext *cc = frame->cc;
+ frame->lp[n].reg = jit_cc_new_reg_I32(cc);
+ GEN_INSN(LDI32, frame->lp[n].reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+
+ return frame->lp[n].reg;
+}
+
+JitReg
+gen_load_i64(JitFrame *frame, unsigned n)
+{
+ if (!frame->lp[n].reg) {
+ JitCompContext *cc = frame->cc;
+ frame->lp[n].reg = frame->lp[n + 1].reg = jit_cc_new_reg_I64(cc);
+ GEN_INSN(LDI64, frame->lp[n].reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+
+ return frame->lp[n].reg;
+}
+
+JitReg
+gen_load_f32(JitFrame *frame, unsigned n)
+{
+ if (!frame->lp[n].reg) {
+ JitCompContext *cc = frame->cc;
+ frame->lp[n].reg = jit_cc_new_reg_F32(cc);
+ GEN_INSN(LDF32, frame->lp[n].reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+
+ return frame->lp[n].reg;
+}
+
+JitReg
+gen_load_f64(JitFrame *frame, unsigned n)
+{
+ if (!frame->lp[n].reg) {
+ JitCompContext *cc = frame->cc;
+ frame->lp[n].reg = frame->lp[n + 1].reg = jit_cc_new_reg_F64(cc);
+ GEN_INSN(LDF64, frame->lp[n].reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ }
+
+ return frame->lp[n].reg;
+}
+
+void
+gen_commit_values(JitFrame *frame, JitValueSlot *begin, JitValueSlot *end)
+{
+ JitCompContext *cc = frame->cc;
+ JitValueSlot *p;
+ int n;
+
+ for (p = begin; p < end; p++) {
+ if (!p->dirty)
+ continue;
+
+ p->dirty = 0;
+ n = p - frame->lp;
+
+ switch (jit_reg_kind(p->reg)) {
+ case JIT_REG_KIND_I32:
+ GEN_INSN(STI32, p->reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+
+ case JIT_REG_KIND_I64:
+ GEN_INSN(STI64, p->reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ (++p)->dirty = 0;
+ break;
+
+ case JIT_REG_KIND_F32:
+ GEN_INSN(STF32, p->reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ break;
+
+ case JIT_REG_KIND_F64:
+ GEN_INSN(STF64, p->reg, cc->fp_reg,
+ NEW_CONST(I32, offset_of_local(n)));
+ (++p)->dirty = 0;
+ break;
+ }
+ }
+}
+
+/**
+ * Generate instructions to commit SP and IP pointers to the frame.
+ *
+ * @param frame the frame information
+ */
+void
+gen_commit_sp_ip(JitFrame *frame)
+{
+ JitCompContext *cc = frame->cc;
+ JitReg sp;
+
+ if (frame->sp != frame->committed_sp) {
+ sp = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(ADD, sp, cc->fp_reg,
+ NEW_CONST(PTR, offset_of_local(frame->sp - frame->lp)));
+ GEN_INSN(STPTR, sp, cc->fp_reg,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
+ frame->committed_sp = frame->sp;
+ }
+
+#if 0 /* Disable committing ip currently */
+ if (frame->ip != frame->committed_ip) {
+ GEN_INSN(STPTR, NEW_CONST(PTR, (uintptr_t)frame->ip), cc->fp_reg,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, ip)));
+ frame->committed_ip = frame->ip;
+ }
+#endif
+}
+
+static bool
+create_fixed_virtual_regs(JitCompContext *cc)
+{
+ WASMModule *module = cc->cur_wasm_module;
+ uint64 total_size;
+ uint32 i, count;
+
+ cc->module_inst_reg = jit_cc_new_reg_ptr(cc);
+ cc->module_reg = jit_cc_new_reg_ptr(cc);
+ cc->import_func_ptrs_reg = jit_cc_new_reg_ptr(cc);
+ cc->fast_jit_func_ptrs_reg = jit_cc_new_reg_ptr(cc);
+ cc->func_type_indexes_reg = jit_cc_new_reg_ptr(cc);
+ cc->aux_stack_bound_reg = jit_cc_new_reg_I32(cc);
+ cc->aux_stack_bottom_reg = jit_cc_new_reg_I32(cc);
+
+ count = module->import_memory_count + module->memory_count;
+ if (count > 0) {
+ total_size = (uint64)sizeof(JitMemRegs) * count;
+ if (total_size > UINT32_MAX
+ || !(cc->memory_regs = jit_calloc((uint32)total_size))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ return false;
+ }
+
+ for (i = 0; i < count; i++) {
+ cc->memory_regs[i].memory_data = jit_cc_new_reg_ptr(cc);
+ cc->memory_regs[i].memory_data_end = jit_cc_new_reg_ptr(cc);
+ cc->memory_regs[i].mem_bound_check_1byte = jit_cc_new_reg_ptr(cc);
+ cc->memory_regs[i].mem_bound_check_2bytes = jit_cc_new_reg_ptr(cc);
+ cc->memory_regs[i].mem_bound_check_4bytes = jit_cc_new_reg_ptr(cc);
+ cc->memory_regs[i].mem_bound_check_8bytes = jit_cc_new_reg_ptr(cc);
+ cc->memory_regs[i].mem_bound_check_16bytes = jit_cc_new_reg_ptr(cc);
+ }
+ }
+
+ count = module->import_table_count + module->table_count;
+ if (count > 0) {
+ total_size = (uint64)sizeof(JitTableRegs) * count;
+ if (total_size > UINT32_MAX
+ || !(cc->table_regs = jit_calloc((uint32)total_size))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ return false;
+ }
+
+ for (i = 0; i < count; i++) {
+ cc->table_regs[i].table_elems = jit_cc_new_reg_ptr(cc);
+ cc->table_regs[i].table_cur_size = jit_cc_new_reg_I32(cc);
+ }
+ }
+
+ return true;
+}
+
+static bool
+form_and_translate_func(JitCompContext *cc)
+{
+ JitBasicBlock *func_entry_basic_block;
+ JitReg func_entry_label;
+ JitInsn *insn;
+ JitIncomingInsn *incoming_insn, *incoming_insn_next;
+ uint32 i;
+
+ if (!create_fixed_virtual_regs(cc))
+ return false;
+
+ if (!(func_entry_basic_block = jit_frontend_translate_func(cc)))
+ return false;
+
+ jit_cc_reset_insn_hash(cc);
+
+ /* The label of the func entry basic block. */
+ func_entry_label = jit_basic_block_label(func_entry_basic_block);
+
+ /* Create a JMP instruction jumping to the func entry. */
+ if (!(insn = jit_cc_new_insn(cc, JMP, func_entry_label)))
+ return false;
+
+ /* Insert the instruction into the cc entry block. */
+ jit_basic_block_append_insn(jit_cc_entry_basic_block(cc), insn);
+
+ /* Patch INSNs jumping to exception basic blocks. */
+ for (i = 0; i < EXCE_NUM; i++) {
+ incoming_insn = cc->incoming_insns_for_exec_bbs[i];
+ if (incoming_insn) {
+ if (!(cc->exce_basic_blocks[i] = jit_cc_new_basic_block(cc, 0))) {
+ jit_set_last_error(cc, "create basic block failed");
+ return false;
+ }
+ while (incoming_insn) {
+ incoming_insn_next = incoming_insn->next;
+ insn = incoming_insn->insn;
+ if (insn->opcode == JIT_OP_JMP) {
+ *(jit_insn_opnd(insn, 0)) =
+ jit_basic_block_label(cc->exce_basic_blocks[i]);
+ }
+ else if (insn->opcode >= JIT_OP_BEQ
+ && insn->opcode <= JIT_OP_BLEU) {
+ *(jit_insn_opnd(insn, 1)) =
+ jit_basic_block_label(cc->exce_basic_blocks[i]);
+ }
+ incoming_insn = incoming_insn_next;
+ }
+ cc->cur_basic_block = cc->exce_basic_blocks[i];
+ if (i != EXCE_ALREADY_THROWN) {
+ JitReg module_inst_reg = jit_cc_new_reg_ptr(cc);
+ GEN_INSN(LDPTR, module_inst_reg, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, module_inst)));
+ insn = GEN_INSN(
+ CALLNATIVE, 0,
+ NEW_CONST(PTR, (uintptr_t)jit_set_exception_with_id), 2);
+ if (insn) {
+ *(jit_insn_opndv(insn, 2)) = module_inst_reg;
+ *(jit_insn_opndv(insn, 3)) = NEW_CONST(I32, i);
+ }
+ }
+ GEN_INSN(RETURN, NEW_CONST(I32, JIT_INTERP_ACTION_THROWN));
+
+ *(jit_annl_begin_bcip(cc,
+ jit_basic_block_label(cc->cur_basic_block))) =
+ *(jit_annl_end_bcip(
+ cc, jit_basic_block_label(cc->cur_basic_block))) =
+ cc->cur_wasm_module->load_addr;
+ }
+ }
+
+ *(jit_annl_begin_bcip(cc, cc->entry_label)) =
+ *(jit_annl_end_bcip(cc, cc->entry_label)) =
+ *(jit_annl_begin_bcip(cc, cc->exit_label)) =
+ *(jit_annl_end_bcip(cc, cc->exit_label)) =
+ cc->cur_wasm_module->load_addr;
+
+ if (jit_get_last_error(cc)) {
+ return false;
+ }
+ return true;
+}
+
+bool
+jit_pass_frontend(JitCompContext *cc)
+{
+ /* Enable necessary annotations required at the current stage. */
+ if (!jit_annl_enable_begin_bcip(cc) || !jit_annl_enable_end_bcip(cc)
+ || !jit_annl_enable_end_sp(cc) || !jit_annr_enable_def_insn(cc)
+ || !jit_cc_enable_insn_hash(cc, 127))
+ return false;
+
+ if (!(form_and_translate_func(cc)))
+ return false;
+
+ /* Release the annotations after local CSE and translation. */
+ jit_cc_disable_insn_hash(cc);
+ jit_annl_disable_end_sp(cc);
+
+ return true;
+}
+
+static JitFrame *
+init_func_translation(JitCompContext *cc)
+{
+ JitFrame *jit_frame;
+ JitReg top, top_boundary, new_top, frame_boundary, frame_sp;
+ WASMModule *cur_wasm_module = cc->cur_wasm_module;
+ WASMFunction *cur_wasm_func = cc->cur_wasm_func;
+ uint32 cur_wasm_func_idx = cc->cur_wasm_func_idx;
+ uint32 max_locals =
+ cur_wasm_func->param_cell_num + cur_wasm_func->local_cell_num;
+ uint32 max_stacks = cur_wasm_func->max_stack_cell_num;
+ uint64 total_cell_num =
+ (uint64)cur_wasm_func->param_cell_num
+ + (uint64)cur_wasm_func->local_cell_num
+ + (uint64)cur_wasm_func->max_stack_cell_num
+ + ((uint64)cur_wasm_func->max_block_num) * sizeof(WASMBranchBlock) / 4;
+ uint32 frame_size, outs_size, local_size, count;
+ uint32 i, local_off;
+ uint64 total_size;
+#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
+ JitReg module_inst, func_inst;
+ uint32 func_insts_offset;
+#if WASM_ENABLE_PERF_PROFILING != 0
+ JitReg time_started;
+#endif
+#endif
+
+ if ((uint64)max_locals + (uint64)max_stacks >= UINT32_MAX
+ || total_cell_num >= UINT32_MAX
+ || !(jit_frame = jit_calloc(offsetof(JitFrame, lp)
+ + sizeof(*jit_frame->lp)
+ * (max_locals + max_stacks)))) {
+ os_printf("allocate jit frame failed\n");
+ return NULL;
+ }
+
+ count =
+ cur_wasm_module->import_memory_count + cur_wasm_module->memory_count;
+ if (count > 0) {
+ total_size = (uint64)sizeof(JitMemRegs) * count;
+ if (total_size > UINT32_MAX
+ || !(jit_frame->memory_regs = jit_calloc((uint32)total_size))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ jit_free(jit_frame);
+ return NULL;
+ }
+ }
+
+ count = cur_wasm_module->import_table_count + cur_wasm_module->table_count;
+ if (count > 0) {
+ total_size = (uint64)sizeof(JitTableRegs) * count;
+ if (total_size > UINT32_MAX
+ || !(jit_frame->table_regs = jit_calloc((uint32)total_size))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ if (jit_frame->memory_regs)
+ jit_free(jit_frame->memory_regs);
+ jit_free(jit_frame);
+ return NULL;
+ }
+ }
+
+ jit_frame->cur_wasm_module = cur_wasm_module;
+ jit_frame->cur_wasm_func = cur_wasm_func;
+ jit_frame->cur_wasm_func_idx = cur_wasm_func_idx;
+ jit_frame->cc = cc;
+ jit_frame->max_locals = max_locals;
+ jit_frame->max_stacks = max_stacks;
+ jit_frame->sp = jit_frame->lp + max_locals;
+ jit_frame->ip = cur_wasm_func->code;
+
+ cc->jit_frame = jit_frame;
+ cc->cur_basic_block = jit_cc_entry_basic_block(cc);
+ cc->spill_cache_offset = wasm_interp_interp_frame_size(total_cell_num);
+ /* Set spill cache size according to max local cell num, max stack cell
+ num and virtual fixed register num */
+ cc->spill_cache_size = (max_locals + max_stacks) * 4 + sizeof(void *) * 16;
+ cc->total_frame_size = cc->spill_cache_offset + cc->spill_cache_size;
+ cc->jitted_return_address_offset =
+ offsetof(WASMInterpFrame, jitted_return_addr);
+ cc->cur_basic_block = jit_cc_entry_basic_block(cc);
+
+ frame_size = outs_size = cc->total_frame_size;
+ local_size =
+ (cur_wasm_func->param_cell_num + cur_wasm_func->local_cell_num) * 4;
+
+ top = jit_cc_new_reg_ptr(cc);
+ top_boundary = jit_cc_new_reg_ptr(cc);
+ new_top = jit_cc_new_reg_ptr(cc);
+ frame_boundary = jit_cc_new_reg_ptr(cc);
+ frame_sp = jit_cc_new_reg_ptr(cc);
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
+ module_inst = jit_cc_new_reg_ptr(cc);
+ func_inst = jit_cc_new_reg_ptr(cc);
+#if WASM_ENABLE_PERF_PROFILING != 0
+ time_started = jit_cc_new_reg_I64(cc);
+ /* Call os_time_get_boot_microsecond() to get time_started firstly
+ as there is stack frame switching below, calling native in them
+ may cause register spilling work inproperly */
+ if (!jit_emit_callnative(cc, os_time_get_boot_microsecond, time_started,
+ NULL, 0)) {
+ return NULL;
+ }
+#endif
+#endif
+
+ /* top = exec_env->wasm_stack.s.top */
+ GEN_INSN(LDPTR, top, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
+ /* top_boundary = exec_env->wasm_stack.s.top_boundary */
+ GEN_INSN(LDPTR, top_boundary, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top_boundary)));
+ /* frame_boundary = top + frame_size + outs_size */
+ GEN_INSN(ADD, frame_boundary, top, NEW_CONST(PTR, frame_size + outs_size));
+ /* if frame_boundary > top_boundary, throw stack overflow exception */
+ GEN_INSN(CMP, cc->cmp_reg, frame_boundary, top_boundary);
+ if (!jit_emit_exception(cc, EXCE_OPERAND_STACK_OVERFLOW, JIT_OP_BGTU,
+ cc->cmp_reg, NULL)) {
+ return NULL;
+ }
+
+ /* Add first and then sub to reduce one used register */
+ /* new_top = frame_boundary - outs_size = top + frame_size */
+ GEN_INSN(SUB, new_top, frame_boundary, NEW_CONST(PTR, outs_size));
+ /* exec_env->wasm_stack.s.top = new_top */
+ GEN_INSN(STPTR, new_top, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
+ /* frame_sp = frame->lp + local_size */
+ GEN_INSN(ADD, frame_sp, top,
+ NEW_CONST(PTR, offsetof(WASMInterpFrame, lp) + local_size));
+ /* frame->sp = frame_sp */
+ GEN_INSN(STPTR, frame_sp, top,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, sp)));
+ /* frame->prev_frame = fp_reg */
+ GEN_INSN(STPTR, cc->fp_reg, top,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, prev_frame)));
+#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
+ /* module_inst = exec_env->module_inst */
+ GEN_INSN(LDPTR, module_inst, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, module_inst)));
+ func_insts_offset =
+ jit_frontend_get_module_inst_extra_offset(cur_wasm_module)
+ + (uint32)offsetof(WASMModuleInstanceExtra, functions);
+ /* func_inst = module_inst->e->functions */
+ GEN_INSN(LDPTR, func_inst, module_inst, NEW_CONST(I32, func_insts_offset));
+ /* func_inst = func_inst + cur_wasm_func_idx */
+ GEN_INSN(ADD, func_inst, func_inst,
+ NEW_CONST(PTR, (uint32)sizeof(WASMFunctionInstance)
+ * cur_wasm_func_idx));
+ /* frame->function = func_inst */
+ GEN_INSN(STPTR, func_inst, top,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, function)));
+#if WASM_ENABLE_PERF_PROFILING != 0
+ /* frame->time_started = time_started */
+ GEN_INSN(STI64, time_started, top,
+ NEW_CONST(I32, offsetof(WASMInterpFrame, time_started)));
+#endif
+#endif
+ /* exec_env->cur_frame = top */
+ GEN_INSN(STPTR, top, cc->exec_env_reg,
+ NEW_CONST(I32, offsetof(WASMExecEnv, cur_frame)));
+ /* fp_reg = top */
+ GEN_INSN(MOV, cc->fp_reg, top);
+
+ /* Initialize local variables, set them to 0 */
+ local_off = (uint32)offsetof(WASMInterpFrame, lp)
+ + cur_wasm_func->param_cell_num * 4;
+ for (i = 0; i < cur_wasm_func->local_cell_num / 2; i++, local_off += 8) {
+ GEN_INSN(STI64, NEW_CONST(I64, 0), cc->fp_reg,
+ NEW_CONST(I32, local_off));
+ }
+ if (cur_wasm_func->local_cell_num & 1) {
+ GEN_INSN(STI32, NEW_CONST(I32, 0), cc->fp_reg,
+ NEW_CONST(I32, local_off));
+ }
+
+ return jit_frame;
+}
+
+static void
+free_block_memory(JitBlock *block)
+{
+ if (block->param_types)
+ jit_free(block->param_types);
+ if (block->result_types)
+ jit_free(block->result_types);
+ jit_free(block);
+}
+
+static JitBasicBlock *
+create_func_block(JitCompContext *cc)
+{
+ JitBlock *jit_block;
+ WASMFunction *cur_func = cc->cur_wasm_func;
+ WASMType *func_type = cur_func->func_type;
+ uint32 param_count = func_type->param_count;
+ uint32 result_count = func_type->result_count;
+
+ if (!(jit_block = jit_calloc(sizeof(JitBlock)))) {
+ return NULL;
+ }
+
+ if (param_count && !(jit_block->param_types = jit_calloc(param_count))) {
+ goto fail;
+ }
+ if (result_count && !(jit_block->result_types = jit_calloc(result_count))) {
+ goto fail;
+ }
+
+ /* Set block data */
+ jit_block->label_type = LABEL_TYPE_FUNCTION;
+ jit_block->param_count = param_count;
+ if (param_count) {
+ bh_memcpy_s(jit_block->param_types, param_count, func_type->types,
+ param_count);
+ }
+ jit_block->result_count = result_count;
+ if (result_count) {
+ bh_memcpy_s(jit_block->result_types, result_count,
+ func_type->types + param_count, result_count);
+ }
+ jit_block->wasm_code_end = cur_func->code + cur_func->code_size;
+ jit_block->frame_sp_begin = cc->jit_frame->sp;
+
+ /* Add function entry block */
+ if (!(jit_block->basic_block_entry = jit_cc_new_basic_block(cc, 0))) {
+ goto fail;
+ }
+ *(jit_annl_begin_bcip(
+ cc, jit_basic_block_label(jit_block->basic_block_entry))) =
+ cur_func->code;
+ jit_block_stack_push(&cc->block_stack, jit_block);
+ cc->cur_basic_block = jit_block->basic_block_entry;
+
+ return jit_block->basic_block_entry;
+
+fail:
+ free_block_memory(jit_block);
+ return NULL;
+}
+
+#define CHECK_BUF(buf, buf_end, length) \
+ do { \
+ if (buf + length > buf_end) { \
+ jit_set_last_error(cc, "read leb failed: unexpected end."); \
+ return false; \
+ } \
+ } while (0)
+
+static bool
+read_leb(JitCompContext *cc, 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 + 6) / 7) {
+ jit_set_last_error(cc, "read leb failed: "
+ "integer representation too long");
+ return false;
+ }
+ if (sign && (shift < maxbits) && (byte & 0x40)) {
+ /* Sign extend */
+ result |= (~((uint64)0)) << shift;
+ }
+ *p_result = result;
+ return true;
+}
+
+#define read_leb_uint32(p, p_end, res) \
+ do { \
+ uint32 off = 0; \
+ uint64 res64; \
+ if (!read_leb(cc, 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(cc, 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(cc, p, p_end, &off, 64, true, &res64)) \
+ return false; \
+ p += off; \
+ res = (int64)res64; \
+ } while (0)
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#define COMPILE_ATOMIC_RMW(OP, NAME) \
+ case WASM_OP_ATOMIC_RMW_I32_##NAME: \
+ bytes = 4; \
+ op_type = VALUE_TYPE_I32; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME: \
+ bytes = 8; \
+ op_type = VALUE_TYPE_I64; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I32_##NAME##8_U: \
+ bytes = 1; \
+ op_type = VALUE_TYPE_I32; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I32_##NAME##16_U: \
+ bytes = 2; \
+ op_type = VALUE_TYPE_I32; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME##8_U: \
+ bytes = 1; \
+ op_type = VALUE_TYPE_I64; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME##16_U: \
+ bytes = 2; \
+ op_type = VALUE_TYPE_I64; \
+ goto OP_ATOMIC_##OP; \
+ case WASM_OP_ATOMIC_RMW_I64_##NAME##32_U: \
+ bytes = 4; \
+ op_type = VALUE_TYPE_I64; \
+ OP_ATOMIC_##OP : bin_op = AtomicRMWBinOp##OP; \
+ goto build_atomic_rmw;
+#endif
+
+static bool
+jit_compile_func(JitCompContext *cc)
+{
+ WASMFunction *cur_func = cc->cur_wasm_func;
+ WASMType *func_type = NULL;
+ uint8 *frame_ip = cur_func->code, opcode, *p_f32, *p_f64;
+ uint8 *frame_ip_end = frame_ip + cur_func->code_size;
+ uint8 *param_types = NULL, *result_types = NULL, value_type;
+ uint16 param_count, result_count;
+ uint32 br_depth, *br_depths, br_count;
+ uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i;
+ uint32 bytes = 4, align, offset;
+ bool merge_cmp_and_if = false, merge_cmp_and_br_if = false;
+ bool sign = true;
+ int32 i32_const;
+ int64 i64_const;
+ float32 f32_const;
+ float64 f64_const;
+
+ while (frame_ip < frame_ip_end) {
+ cc->jit_frame->ip = frame_ip;
+ opcode = *frame_ip++;
+
+#if 0 /* TODO */
+#if WASM_ENABLE_THREAD_MGR != 0
+ /* Insert suspend check point */
+ if (cc->enable_thread_mgr) {
+ if (!check_suspend_flags(cc, func_ctx))
+ return false;
+ }
+#endif
+#endif
+
+ switch (opcode) {
+ case WASM_OP_UNREACHABLE:
+ if (!jit_compile_op_unreachable(cc, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_NOP:
+ break;
+
+ case WASM_OP_BLOCK:
+ case WASM_OP_LOOP:
+ case WASM_OP_IF:
+ {
+ value_type = *frame_ip++;
+ if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_I64
+ || value_type == VALUE_TYPE_F32
+ || value_type == VALUE_TYPE_F64
+ || value_type == VALUE_TYPE_V128
+ || value_type == VALUE_TYPE_VOID
+ || value_type == VALUE_TYPE_FUNCREF
+ || value_type == VALUE_TYPE_EXTERNREF) {
+ param_count = 0;
+ param_types = NULL;
+ if (value_type == VALUE_TYPE_VOID) {
+ result_count = 0;
+ result_types = NULL;
+ }
+ else {
+ result_count = 1;
+ result_types = &value_type;
+ }
+ }
+ else {
+ jit_set_last_error(cc, "unsupported value type");
+ return false;
+ }
+ if (!jit_compile_op_block(
+ cc, &frame_ip, frame_ip_end,
+ (uint32)(LABEL_TYPE_BLOCK + opcode - WASM_OP_BLOCK),
+ param_count, param_types, result_count, result_types,
+ merge_cmp_and_if))
+ return false;
+ /* Clear flag */
+ merge_cmp_and_if = false;
+ break;
+ }
+ case EXT_OP_BLOCK:
+ case EXT_OP_LOOP:
+ case EXT_OP_IF:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, type_idx);
+ func_type = cc->cur_wasm_module->types[type_idx];
+ param_count = func_type->param_count;
+ param_types = func_type->types;
+ result_count = func_type->result_count;
+ result_types = func_type->types + param_count;
+ if (!jit_compile_op_block(
+ cc, &frame_ip, frame_ip_end,
+ (uint32)(LABEL_TYPE_BLOCK + opcode - EXT_OP_BLOCK),
+ param_count, param_types, result_count, result_types,
+ merge_cmp_and_if))
+ return false;
+ /* Clear flag */
+ merge_cmp_and_if = false;
+ break;
+ }
+
+ case WASM_OP_ELSE:
+ if (!jit_compile_op_else(cc, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_END:
+ if (!jit_compile_op_end(cc, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_BR:
+ read_leb_uint32(frame_ip, frame_ip_end, br_depth);
+ if (!jit_compile_op_br(cc, br_depth, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_BR_IF:
+ read_leb_uint32(frame_ip, frame_ip_end, br_depth);
+ if (!jit_compile_op_br_if(cc, br_depth, merge_cmp_and_br_if,
+ &frame_ip))
+ return false;
+ /* Clear flag */
+ merge_cmp_and_br_if = false;
+ break;
+
+ case WASM_OP_BR_TABLE:
+ read_leb_uint32(frame_ip, frame_ip_end, br_count);
+ if (!(br_depths = jit_calloc((uint32)sizeof(uint32)
+ * (br_count + 1)))) {
+ jit_set_last_error(cc, "allocate memory failed.");
+ goto fail;
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ for (i = 0; i <= br_count; i++)
+ read_leb_uint32(frame_ip, frame_ip_end, br_depths[i]);
+#else
+ for (i = 0; i <= br_count; i++)
+ br_depths[i] = *frame_ip++;
+#endif
+
+ if (!jit_compile_op_br_table(cc, br_depths, br_count,
+ &frame_ip)) {
+ jit_free(br_depths);
+ return false;
+ }
+
+ jit_free(br_depths);
+ break;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ case EXT_OP_BR_TABLE_CACHE:
+ {
+ BrTableCache *node = bh_list_first_elem(
+ cc->cur_wasm_module->br_table_cache_list);
+ BrTableCache *node_next;
+ uint8 *p_opcode = frame_ip - 1;
+
+ read_leb_uint32(frame_ip, frame_ip_end, br_count);
+
+ while (node) {
+ node_next = bh_list_elem_next(node);
+ if (node->br_table_op_addr == p_opcode) {
+ br_depths = node->br_depths;
+ if (!jit_compile_op_br_table(cc, br_depths, br_count,
+ &frame_ip)) {
+ return false;
+ }
+ break;
+ }
+ node = node_next;
+ }
+ bh_assert(node);
+
+ break;
+ }
+#endif
+
+ case WASM_OP_RETURN:
+ if (!jit_compile_op_return(cc, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_CALL:
+ read_leb_uint32(frame_ip, frame_ip_end, func_idx);
+ if (!jit_compile_op_call(cc, func_idx, false))
+ return false;
+ break;
+
+ case WASM_OP_CALL_INDIRECT:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, type_idx);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+#else
+ frame_ip++;
+ tbl_idx = 0;
+#endif
+
+ if (!jit_compile_op_call_indirect(cc, type_idx, tbl_idx))
+ return false;
+ break;
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL:
+ read_leb_uint32(frame_ip, frame_ip_end, func_idx);
+
+ if (!jit_compile_op_call(cc, func_idx, true))
+ return false;
+ if (!jit_compile_op_return(cc, &frame_ip))
+ return false;
+ break;
+
+ case WASM_OP_RETURN_CALL_INDIRECT:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, type_idx);
+#if WASM_ENABLE_REF_TYPES != 0
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+#else
+ frame_ip++;
+ tbl_idx = 0;
+#endif
+
+ if (!jit_compile_op_call_indirect(cc, type_idx, tbl_idx))
+ return false;
+ if (!jit_compile_op_return(cc, &frame_ip))
+ return false;
+ break;
+ }
+#endif /* end of WASM_ENABLE_TAIL_CALL */
+
+ case WASM_OP_DROP:
+ if (!jit_compile_op_drop(cc, true))
+ return false;
+ break;
+
+ case WASM_OP_DROP_64:
+ if (!jit_compile_op_drop(cc, false))
+ return false;
+ break;
+
+ case WASM_OP_SELECT:
+ if (!jit_compile_op_select(cc, true))
+ return false;
+ break;
+
+ case WASM_OP_SELECT_64:
+ if (!jit_compile_op_select(cc, false))
+ return false;
+ break;
+
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_SELECT_T:
+ {
+ uint32 vec_len;
+
+ read_leb_uint32(frame_ip, frame_ip_end, vec_len);
+ bh_assert(vec_len == 1);
+ (void)vec_len;
+
+ type_idx = *frame_ip++;
+ if (!jit_compile_op_select(cc,
+ (type_idx != VALUE_TYPE_I64)
+ && (type_idx != VALUE_TYPE_F64)))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_GET:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!jit_compile_op_table_get(cc, tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_SET:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!jit_compile_op_table_set(cc, tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_REF_NULL:
+ {
+ uint32 ref_type;
+ read_leb_uint32(frame_ip, frame_ip_end, ref_type);
+ if (!jit_compile_op_ref_null(cc, ref_type))
+ return false;
+ break;
+ }
+ case WASM_OP_REF_IS_NULL:
+ {
+ if (!jit_compile_op_ref_is_null(cc))
+ return false;
+ break;
+ }
+ case WASM_OP_REF_FUNC:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, func_idx);
+ if (!jit_compile_op_ref_func(cc, func_idx))
+ return false;
+ break;
+ }
+#endif
+
+ case WASM_OP_GET_LOCAL:
+ read_leb_uint32(frame_ip, frame_ip_end, local_idx);
+ if (!jit_compile_op_get_local(cc, local_idx))
+ return false;
+ break;
+
+ case WASM_OP_SET_LOCAL:
+ read_leb_uint32(frame_ip, frame_ip_end, local_idx);
+ if (!jit_compile_op_set_local(cc, local_idx))
+ return false;
+ break;
+
+ case WASM_OP_TEE_LOCAL:
+ read_leb_uint32(frame_ip, frame_ip_end, local_idx);
+ if (!jit_compile_op_tee_local(cc, local_idx))
+ return false;
+ break;
+
+ case WASM_OP_GET_GLOBAL:
+ case WASM_OP_GET_GLOBAL_64:
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ if (!jit_compile_op_get_global(cc, global_idx))
+ return false;
+ break;
+
+ case WASM_OP_SET_GLOBAL:
+ case WASM_OP_SET_GLOBAL_64:
+ case WASM_OP_SET_GLOBAL_AUX_STACK:
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ if (!jit_compile_op_set_global(
+ cc, global_idx,
+ opcode == WASM_OP_SET_GLOBAL_AUX_STACK ? true : false))
+ 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 (!jit_compile_op_i32_load(cc, align, offset, bytes, sign,
+ false))
+ 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 (!jit_compile_op_i64_load(cc, align, offset, bytes, sign,
+ false))
+ 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 (!jit_compile_op_f32_load(cc, 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 (!jit_compile_op_f64_load(cc, 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 (!jit_compile_op_i32_store(cc, align, offset, bytes, false))
+ 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 (!jit_compile_op_i64_store(cc, align, offset, bytes, false))
+ 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 (!jit_compile_op_f32_store(cc, 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 (!jit_compile_op_f64_store(cc, align, offset))
+ return false;
+ break;
+
+ case WASM_OP_MEMORY_SIZE:
+ read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+ if (!jit_compile_op_memory_size(cc, mem_idx))
+ return false;
+ break;
+
+ case WASM_OP_MEMORY_GROW:
+ read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+ if (!jit_compile_op_memory_grow(cc, mem_idx))
+ return false;
+ break;
+
+ case WASM_OP_I32_CONST:
+ read_leb_int32(frame_ip, frame_ip_end, i32_const);
+ if (!jit_compile_op_i32_const(cc, i32_const))
+ return false;
+ break;
+
+ case WASM_OP_I64_CONST:
+ read_leb_int64(frame_ip, frame_ip_end, i64_const);
+ if (!jit_compile_op_i64_const(cc, 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 (!jit_compile_op_f32_const(cc, 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 (!jit_compile_op_f64_const(cc, 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 (!jit_compile_op_i32_compare(cc, INT_EQZ + opcode
+ - WASM_OP_I32_EQZ))
+ return false;
+ if (frame_ip < frame_ip_end) {
+ /* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
+ if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
+ merge_cmp_and_if = true;
+ if (*frame_ip == WASM_OP_BR_IF)
+ merge_cmp_and_br_if = true;
+ }
+ 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 (!jit_compile_op_i64_compare(cc, INT_EQZ + opcode
+ - WASM_OP_I64_EQZ))
+ return false;
+ if (frame_ip < frame_ip_end) {
+ /* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
+ if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
+ merge_cmp_and_if = true;
+ if (*frame_ip == WASM_OP_BR_IF)
+ merge_cmp_and_br_if = true;
+ }
+ 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 (!jit_compile_op_f32_compare(cc, FLOAT_EQ + opcode
+ - WASM_OP_F32_EQ))
+ return false;
+ if (frame_ip < frame_ip_end) {
+ /* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
+ if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
+ merge_cmp_and_if = true;
+ if (*frame_ip == WASM_OP_BR_IF)
+ merge_cmp_and_br_if = true;
+ }
+ 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 (!jit_compile_op_f64_compare(cc, FLOAT_EQ + opcode
+ - WASM_OP_F64_EQ))
+ return false;
+ if (frame_ip < frame_ip_end) {
+ /* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
+ if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
+ merge_cmp_and_if = true;
+ if (*frame_ip == WASM_OP_BR_IF)
+ merge_cmp_and_br_if = true;
+ }
+ break;
+
+ case WASM_OP_I32_CLZ:
+ if (!jit_compile_op_i32_clz(cc))
+ return false;
+ break;
+
+ case WASM_OP_I32_CTZ:
+ if (!jit_compile_op_i32_ctz(cc))
+ return false;
+ break;
+
+ case WASM_OP_I32_POPCNT:
+ if (!jit_compile_op_i32_popcnt(cc))
+ 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 (!jit_compile_op_i32_arithmetic(
+ cc, 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 (!jit_compile_op_i32_bitwise(cc, 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 (!jit_compile_op_i32_shift(cc, INT_SHL + opcode
+ - WASM_OP_I32_SHL))
+ return false;
+ break;
+
+ case WASM_OP_I64_CLZ:
+ if (!jit_compile_op_i64_clz(cc))
+ return false;
+ break;
+
+ case WASM_OP_I64_CTZ:
+ if (!jit_compile_op_i64_ctz(cc))
+ return false;
+ break;
+
+ case WASM_OP_I64_POPCNT:
+ if (!jit_compile_op_i64_popcnt(cc))
+ 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 (!jit_compile_op_i64_arithmetic(
+ cc, 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 (!jit_compile_op_i64_bitwise(cc, 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 (!jit_compile_op_i64_shift(cc, 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 (!jit_compile_op_f32_math(cc, 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 (!jit_compile_op_f32_arithmetic(cc, FLOAT_ADD + opcode
+ - WASM_OP_F32_ADD))
+ return false;
+ break;
+
+ case WASM_OP_F32_COPYSIGN:
+ if (!jit_compile_op_f32_copysign(cc))
+ 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 (!jit_compile_op_f64_math(cc, 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 (!jit_compile_op_f64_arithmetic(cc, FLOAT_ADD + opcode
+ - WASM_OP_F64_ADD))
+ return false;
+ break;
+
+ case WASM_OP_F64_COPYSIGN:
+ if (!jit_compile_op_f64_copysign(cc))
+ return false;
+ break;
+
+ case WASM_OP_I32_WRAP_I64:
+ if (!jit_compile_op_i32_wrap_i64(cc))
+ 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 (!jit_compile_op_i32_trunc_f32(cc, sign, false))
+ 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 (!jit_compile_op_i32_trunc_f64(cc, sign, false))
+ 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 (!jit_compile_op_i64_extend_i32(cc, 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 (!jit_compile_op_i64_trunc_f32(cc, sign, false))
+ 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 (!jit_compile_op_i64_trunc_f64(cc, sign, false))
+ 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 (!jit_compile_op_f32_convert_i32(cc, 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 (!jit_compile_op_f32_convert_i64(cc, sign))
+ return false;
+ break;
+
+ case WASM_OP_F32_DEMOTE_F64:
+ if (!jit_compile_op_f32_demote_f64(cc))
+ 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 (!jit_compile_op_f64_convert_i32(cc, 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 (!jit_compile_op_f64_convert_i64(cc, sign))
+ return false;
+ break;
+
+ case WASM_OP_F64_PROMOTE_F32:
+ if (!jit_compile_op_f64_promote_f32(cc))
+ return false;
+ break;
+
+ case WASM_OP_I32_REINTERPRET_F32:
+ if (!jit_compile_op_i32_reinterpret_f32(cc))
+ return false;
+ break;
+
+ case WASM_OP_I64_REINTERPRET_F64:
+ if (!jit_compile_op_i64_reinterpret_f64(cc))
+ return false;
+ break;
+
+ case WASM_OP_F32_REINTERPRET_I32:
+ if (!jit_compile_op_f32_reinterpret_i32(cc))
+ return false;
+ break;
+
+ case WASM_OP_F64_REINTERPRET_I64:
+ if (!jit_compile_op_f64_reinterpret_i64(cc))
+ return false;
+ break;
+
+ case WASM_OP_I32_EXTEND8_S:
+ if (!jit_compile_op_i32_extend_i32(cc, 8))
+ return false;
+ break;
+
+ case WASM_OP_I32_EXTEND16_S:
+ if (!jit_compile_op_i32_extend_i32(cc, 16))
+ return false;
+ break;
+
+ case WASM_OP_I64_EXTEND8_S:
+ if (!jit_compile_op_i64_extend_i64(cc, 8))
+ return false;
+ break;
+
+ case WASM_OP_I64_EXTEND16_S:
+ if (!jit_compile_op_i64_extend_i64(cc, 16))
+ return false;
+ break;
+
+ case WASM_OP_I64_EXTEND32_S:
+ if (!jit_compile_op_i64_extend_i64(cc, 32))
+ return false;
+ break;
+
+ case WASM_OP_MISC_PREFIX:
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(frame_ip, frame_ip_end, opcode1);
+ opcode = (uint32)opcode1;
+
+ switch (opcode) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F32) ? true
+ : false;
+ if (!jit_compile_op_i32_trunc_f32(cc, sign, true))
+ return false;
+ break;
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F64) ? true
+ : false;
+ if (!jit_compile_op_i32_trunc_f64(cc, sign, true))
+ return false;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F32) ? true
+ : false;
+ if (!jit_compile_op_i64_trunc_f32(cc, sign, true))
+ return false;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F64) ? true
+ : false;
+ if (!jit_compile_op_i64_trunc_f64(cc, sign, true))
+ return false;
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ {
+ uint32 seg_idx = 0;
+ read_leb_uint32(frame_ip, frame_ip_end, seg_idx);
+ read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+ if (!jit_compile_op_memory_init(cc, mem_idx, seg_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_DATA_DROP:
+ {
+ uint32 seg_idx;
+ read_leb_uint32(frame_ip, frame_ip_end, seg_idx);
+ if (!jit_compile_op_data_drop(cc, seg_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_MEMORY_COPY:
+ {
+ uint32 src_mem_idx, dst_mem_idx;
+ read_leb_uint32(frame_ip, frame_ip_end, src_mem_idx);
+ read_leb_uint32(frame_ip, frame_ip_end, dst_mem_idx);
+ if (!jit_compile_op_memory_copy(cc, src_mem_idx,
+ dst_mem_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_MEMORY_FILL:
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
+ if (!jit_compile_op_memory_fill(cc, mem_idx))
+ return false;
+ break;
+ }
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ {
+ uint32 tbl_idx, tbl_seg_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx);
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!jit_compile_op_table_init(cc, tbl_idx,
+ tbl_seg_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_ELEM_DROP:
+ {
+ uint32 tbl_seg_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx);
+ if (!jit_compile_op_elem_drop(cc, tbl_seg_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_COPY:
+ {
+ uint32 src_tbl_idx, dst_tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
+ read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx);
+ if (!jit_compile_op_table_copy(cc, src_tbl_idx,
+ dst_tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_GROW:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!jit_compile_op_table_grow(cc, tbl_idx))
+ return false;
+ break;
+ }
+
+ case WASM_OP_TABLE_SIZE:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!jit_compile_op_table_size(cc, tbl_idx))
+ return false;
+ break;
+ }
+ case WASM_OP_TABLE_FILL:
+ {
+ uint32 tbl_idx;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ if (!jit_compile_op_table_fill(cc, tbl_idx))
+ return false;
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ jit_set_last_error(cc, "unsupported opcode");
+ return false;
+ }
+ break;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case WASM_OP_ATOMIC_PREFIX:
+ {
+ uint8 bin_op, op_type;
+
+ if (frame_ip < frame_ip_end) {
+ opcode = *frame_ip++;
+ }
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ }
+ switch (opcode) {
+ case WASM_OP_ATOMIC_WAIT32:
+ if (!jit_compile_op_atomic_wait(cc, VALUE_TYPE_I32,
+ align, offset, 4))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_WAIT64:
+ if (!jit_compile_op_atomic_wait(cc, VALUE_TYPE_I64,
+ align, offset, 8))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_NOTIFY:
+ if (!jit_compiler_op_atomic_notify(cc, align, offset,
+ bytes))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_FENCE:
+ /* Skip memory index */
+ frame_ip++;
+ if (!jit_compiler_op_atomic_fence(cc))
+ return false;
+ break;
+ case WASM_OP_ATOMIC_I32_LOAD:
+ bytes = 4;
+ goto op_atomic_i32_load;
+ case WASM_OP_ATOMIC_I32_LOAD8_U:
+ bytes = 1;
+ goto op_atomic_i32_load;
+ case WASM_OP_ATOMIC_I32_LOAD16_U:
+ bytes = 2;
+ op_atomic_i32_load:
+ if (!jit_compile_op_i32_load(cc, align, offset, bytes,
+ sign, true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_I64_LOAD:
+ bytes = 8;
+ goto op_atomic_i64_load;
+ case WASM_OP_ATOMIC_I64_LOAD8_U:
+ bytes = 1;
+ goto op_atomic_i64_load;
+ case WASM_OP_ATOMIC_I64_LOAD16_U:
+ bytes = 2;
+ goto op_atomic_i64_load;
+ case WASM_OP_ATOMIC_I64_LOAD32_U:
+ bytes = 4;
+ op_atomic_i64_load:
+ if (!jit_compile_op_i64_load(cc, align, offset, bytes,
+ sign, true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_I32_STORE:
+ bytes = 4;
+ goto op_atomic_i32_store;
+ case WASM_OP_ATOMIC_I32_STORE8:
+ bytes = 1;
+ goto op_atomic_i32_store;
+ case WASM_OP_ATOMIC_I32_STORE16:
+ bytes = 2;
+ op_atomic_i32_store:
+ if (!jit_compile_op_i32_store(cc, align, offset, bytes,
+ true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_I64_STORE:
+ bytes = 8;
+ goto op_atomic_i64_store;
+ case WASM_OP_ATOMIC_I64_STORE8:
+ bytes = 1;
+ goto op_atomic_i64_store;
+ case WASM_OP_ATOMIC_I64_STORE16:
+ bytes = 2;
+ goto op_atomic_i64_store;
+ case WASM_OP_ATOMIC_I64_STORE32:
+ bytes = 4;
+ op_atomic_i64_store:
+ if (!jit_compile_op_i64_store(cc, align, offset, bytes,
+ true))
+ return false;
+ break;
+
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
+ bytes = 4;
+ op_type = VALUE_TYPE_I32;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
+ bytes = 8;
+ op_type = VALUE_TYPE_I64;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U:
+ bytes = 1;
+ op_type = VALUE_TYPE_I32;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
+ bytes = 2;
+ op_type = VALUE_TYPE_I32;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U:
+ bytes = 1;
+ op_type = VALUE_TYPE_I64;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U:
+ bytes = 2;
+ op_type = VALUE_TYPE_I64;
+ goto op_atomic_cmpxchg;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
+ bytes = 4;
+ op_type = VALUE_TYPE_I64;
+ op_atomic_cmpxchg:
+ if (!jit_compile_op_atomic_cmpxchg(cc, op_type, align,
+ offset, bytes))
+ return false;
+ break;
+
+ COMPILE_ATOMIC_RMW(Add, ADD);
+ COMPILE_ATOMIC_RMW(Sub, SUB);
+ COMPILE_ATOMIC_RMW(And, AND);
+ COMPILE_ATOMIC_RMW(Or, OR);
+ COMPILE_ATOMIC_RMW(Xor, XOR);
+ COMPILE_ATOMIC_RMW(Xchg, XCHG);
+
+ build_atomic_rmw:
+ if (!jit_compile_op_atomic_rmw(cc, bin_op, op_type,
+ align, offset, bytes))
+ return false;
+ break;
+
+ default:
+ jit_set_last_error(cc, "unsupported opcode");
+ return false;
+ }
+ break;
+ }
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
+
+ default:
+ jit_set_last_error(cc, "unsupported opcode");
+ return false;
+ }
+ /* Error may occur when creating registers, basic blocks, insns,
+ consts and labels, in which the return value may be unchecked,
+ here we check again */
+ if (jit_get_last_error(cc)) {
+ return false;
+ }
+ }
+
+ (void)func_idx;
+ return true;
+fail:
+ return false;
+}
+
+JitBasicBlock *
+jit_frontend_translate_func(JitCompContext *cc)
+{
+ JitFrame *jit_frame;
+ JitBasicBlock *basic_block_entry;
+
+ if (!(jit_frame = init_func_translation(cc))) {
+ return NULL;
+ }
+
+ if (!(basic_block_entry = create_func_block(cc))) {
+ return NULL;
+ }
+
+ if (!jit_compile_func(cc)) {
+ return NULL;
+ }
+
+ return basic_block_entry;
+}
+
+uint32
+jit_frontend_get_jitted_return_addr_offset()
+{
+ return (uint32)offsetof(WASMInterpFrame, jitted_return_addr);
+}
+
+#if 0
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+check_suspend_flags(JitCompContext *cc, JITFuncContext *func_ctx)
+{
+ LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
+ JitBasicBlock *terminate_check_block, non_terminate_block;
+ JITFuncType *jit_func_type = func_ctx->jit_func->func_type;
+ JitBasicBlock *terminate_block;
+
+ /* Offset of suspend_flags */
+ offset = I32_FIVE;
+
+ if (!(terminate_addr = LLVMBuildInBoundsGEP(
+ cc->builder, func_ctx->exec_env, &offset, 1, "terminate_addr"))) {
+ jit_set_last_error("llvm build in bounds gep failed");
+ return false;
+ }
+ if (!(terminate_addr =
+ LLVMBuildBitCast(cc->builder, terminate_addr, INT32_PTR_TYPE,
+ "terminate_addr_ptr"))) {
+ jit_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+
+ if (!(terminate_flags =
+ LLVMBuildLoad(cc->builder, terminate_addr, "terminate_flags"))) {
+ jit_set_last_error("llvm build bit cast failed");
+ return false;
+ }
+ /* Set terminate_flags memory accecc to volatile, so that the value
+ will always be loaded from memory rather than register */
+ LLVMSetVolatile(terminate_flags, true);
+
+ CREATE_BASIC_BLOCK(terminate_check_block, "terminate_check");
+ MOVE_BASIC_BLOCK_AFTER_CURR(terminate_check_block);
+
+ CREATE_BASIC_BLOCK(non_terminate_block, "non_terminate");
+ MOVE_BASIC_BLOCK_AFTER_CURR(non_terminate_block);
+
+ BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate");
+ BUILD_COND_BR(res, terminate_check_block, non_terminate_block);
+
+ /* Move builder to terminate check block */
+ SET_BUILDER_POS(terminate_check_block);
+
+ CREATE_BASIC_BLOCK(terminate_block, "terminate");
+ MOVE_BASIC_BLOCK_AFTER_CURR(terminate_block);
+
+ if (!(flag = LLVMBuildAnd(cc->builder, terminate_flags, I32_ONE,
+ "termination_flag"))) {
+ jit_set_last_error("llvm build AND failed");
+ return false;
+ }
+
+ BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate");
+ BUILD_COND_BR(res, terminate_block, non_terminate_block);
+
+ /* Move builder to terminate block */
+ SET_BUILDER_POS(terminate_block);
+ if (!jit_build_zero_function_ret(cc, func_ctx, jit_func_type)) {
+ goto fail;
+ }
+
+ /* Move builder to terminate block */
+ SET_BUILDER_POS(non_terminate_block);
+ return true;
+
+fail:
+ return false;
+}
+#endif /* End of WASM_ENABLE_THREAD_MGR */
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.h
new file mode 100644
index 000000000..7aa460fd9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_frontend.h
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_FRONTEND_H_
+#define _JIT_FRONTEND_H_
+
+#include "jit_utils.h"
+#include "jit_ir.h"
+#include "../interpreter/wasm_interp.h"
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if WASM_ENABLE_AOT == 0
+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,
+ FLOAT_UNO
+} FloatCond;
+#else
+#define IntCond AOTIntCond
+#define FloatCond AOTFloatCond
+#endif
+
+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 V128Arithmetic {
+ V128_ADD = 0,
+ V128_SUB,
+ V128_MUL,
+ V128_DIV,
+ V128_NEG,
+ V128_MIN,
+ V128_MAX,
+} V128Arithmetic;
+
+typedef enum IntBitwise {
+ INT_AND = 0,
+ INT_OR,
+ INT_XOR,
+} IntBitwise;
+
+typedef enum V128Bitwise {
+ V128_NOT,
+ V128_AND,
+ V128_ANDNOT,
+ V128_OR,
+ V128_XOR,
+ V128_BITSELECT,
+} V128Bitwise;
+
+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;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+typedef enum AtomicRMWBinOp {
+ AtomicRMWBinOpAdd,
+ AtomicRMWBinOpSub,
+ AtomicRMWBinOpAnd,
+ AtomicRMWBinOpOr,
+ AtomicRMWBinOpXor,
+ AtomicRMWBinOpXchg
+} AtomicRMWBinOp;
+#endif
+
+/**
+ * Translate instructions in a function. The translated block must
+ * end with a branch instruction whose targets are offsets relating to
+ * the end bcip of the translated block, which are integral constants.
+ * If a target of a branch is really a constant value (which should be
+ * rare), put it into a register and then jump to the register instead
+ * of using the constant value directly in the target. In the
+ * translation process, don't create any new labels. The code bcip of
+ * the begin and end of the translated block is stored in the
+ * jit_annl_begin_bcip and jit_annl_end_bcip annotations of the label
+ * of the block, which must be the same as the bcips used in
+ * profiling.
+ *
+ * NOTE: the function must explicitly set SP to correct value when the
+ * entry's bcip is the function's entry address.
+ *
+ * @param cc containing compilation context of generated IR
+ * @param entry entry of the basic block to be translated. If its
+ * value is NULL, the function will clean up any pass local data that
+ * might be created previously.
+ * @param is_reached a bitmap recording which bytecode has been
+ * reached as a block entry
+ *
+ * @return IR block containing translated instructions if succeeds,
+ * NULL otherwise
+ */
+JitBasicBlock *
+jit_frontend_translate_func(JitCompContext *cc);
+
+/**
+ * Lower the IR of the given compilation context.
+ *
+ * @param cc the compilation context
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jit_frontend_lower(JitCompContext *cc);
+
+uint32
+jit_frontend_get_jitted_return_addr_offset();
+
+uint32
+jit_frontend_get_global_data_offset(const WASMModule *module,
+ uint32 global_idx);
+
+uint32
+jit_frontend_get_table_inst_offset(const WASMModule *module, uint32 tbl_idx);
+
+uint32
+jit_frontend_get_module_inst_extra_offset(const WASMModule *module);
+
+JitReg
+get_module_inst_reg(JitFrame *frame);
+
+JitReg
+get_module_reg(JitFrame *frame);
+
+JitReg
+get_import_func_ptrs_reg(JitFrame *frame);
+
+JitReg
+get_fast_jit_func_ptrs_reg(JitFrame *frame);
+
+JitReg
+get_func_type_indexes_reg(JitFrame *frame);
+
+JitReg
+get_aux_stack_bound_reg(JitFrame *frame);
+
+JitReg
+get_aux_stack_bottom_reg(JitFrame *frame);
+
+JitReg
+get_memory_data_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_memory_data_end_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_mem_bound_check_1byte_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_mem_bound_check_2bytes_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_mem_bound_check_4bytes_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_mem_bound_check_8bytes_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_mem_bound_check_16bytes_reg(JitFrame *frame, uint32 mem_idx);
+
+JitReg
+get_table_elems_reg(JitFrame *frame, uint32 table_idx);
+
+JitReg
+get_table_cur_size_reg(JitFrame *frame, uint32 table_idx);
+
+void
+clear_fixed_virtual_regs(JitFrame *frame);
+
+void
+clear_memory_regs(JitFrame *frame);
+
+void
+clear_table_regs(JitFrame *frame);
+
+/**
+ * Get the offset from frame pointer to the n-th local variable slot.
+ *
+ * @param n the index to the local variable array
+ *
+ * @return the offset from frame pointer to the local variable slot
+ */
+static inline unsigned
+offset_of_local(unsigned n)
+{
+ return offsetof(WASMInterpFrame, lp) + n * 4;
+}
+
+/**
+ * Generate instruction to load an integer from the frame.
+ *
+ * This and the below gen_load_X functions generate instructions to
+ * load values from the frame into registers if the values have not
+ * been loaded yet.
+ *
+ * @param frame the frame information
+ * @param n slot index to the local variable array
+ *
+ * @return register holding the loaded value
+ */
+JitReg
+gen_load_i32(JitFrame *frame, unsigned n);
+
+/**
+ * Generate instruction to load a i64 integer from the frame.
+ *
+ * @param frame the frame information
+ * @param n slot index to the local variable array
+ *
+ * @return register holding the loaded value
+ */
+JitReg
+gen_load_i64(JitFrame *frame, unsigned n);
+
+/**
+ * Generate instruction to load a floating point value from the frame.
+ *
+ * @param frame the frame information
+ * @param n slot index to the local variable array
+ *
+ * @return register holding the loaded value
+ */
+JitReg
+gen_load_f32(JitFrame *frame, unsigned n);
+
+/**
+ * Generate instruction to load a double value from the frame.
+ *
+ * @param frame the frame information
+ * @param n slot index to the local variable array
+ *
+ * @return register holding the loaded value
+ */
+JitReg
+gen_load_f64(JitFrame *frame, unsigned n);
+
+/**
+ * Generate instructions to commit computation result to the frame.
+ * The general principle is to only commit values that will be used
+ * through the frame.
+ *
+ * @param frame the frame information
+ * @param begin the begin value slot to commit
+ * @param end the end value slot to commit
+ */
+void
+gen_commit_values(JitFrame *frame, JitValueSlot *begin, JitValueSlot *end);
+
+/**
+ * Generate instructions to commit SP and IP pointers to the frame.
+ *
+ * @param frame the frame information
+ */
+void
+gen_commit_sp_ip(JitFrame *frame);
+
+/**
+ * Generate commit instructions for the block end.
+ *
+ * @param frame the frame information
+ */
+static inline void
+gen_commit_for_branch(JitFrame *frame)
+{
+ gen_commit_values(frame, frame->lp, frame->sp);
+}
+
+/**
+ * Generate commit instructions for exception checks.
+ *
+ * @param frame the frame information
+ */
+static inline void
+gen_commit_for_exception(JitFrame *frame)
+{
+ gen_commit_values(frame, frame->lp, frame->lp + frame->max_locals);
+ gen_commit_sp_ip(frame);
+}
+
+/**
+ * Generate commit instructions to commit all status.
+ *
+ * @param frame the frame information
+ */
+static inline void
+gen_commit_for_all(JitFrame *frame)
+{
+ gen_commit_values(frame, frame->lp, frame->sp);
+ gen_commit_sp_ip(frame);
+}
+
+static inline void
+clear_values(JitFrame *frame)
+{
+ size_t total_size =
+ sizeof(JitValueSlot) * (frame->max_locals + frame->max_stacks);
+ memset(frame->lp, 0, total_size);
+ frame->committed_sp = NULL;
+ frame->committed_ip = NULL;
+ clear_fixed_virtual_regs(frame);
+}
+
+static inline void
+push_i32(JitFrame *frame, JitReg value)
+{
+ frame->sp->reg = value;
+ frame->sp->dirty = 1;
+ frame->sp++;
+}
+
+static inline void
+push_i64(JitFrame *frame, JitReg value)
+{
+ frame->sp->reg = value;
+ frame->sp->dirty = 1;
+ frame->sp++;
+ frame->sp->reg = value;
+ frame->sp->dirty = 1;
+ frame->sp++;
+}
+
+static inline void
+push_f32(JitFrame *frame, JitReg value)
+{
+ push_i32(frame, value);
+}
+
+static inline void
+push_f64(JitFrame *frame, JitReg value)
+{
+ push_i64(frame, value);
+}
+
+static inline JitReg
+pop_i32(JitFrame *frame)
+{
+ frame->sp--;
+ return gen_load_i32(frame, frame->sp - frame->lp);
+}
+
+static inline JitReg
+pop_i64(JitFrame *frame)
+{
+ frame->sp -= 2;
+ return gen_load_i64(frame, frame->sp - frame->lp);
+}
+
+static inline JitReg
+pop_f32(JitFrame *frame)
+{
+ frame->sp--;
+ return gen_load_f32(frame, frame->sp - frame->lp);
+}
+
+static inline JitReg
+pop_f64(JitFrame *frame)
+{
+ frame->sp -= 2;
+ return gen_load_f64(frame, frame->sp - frame->lp);
+}
+
+static inline void
+pop(JitFrame *frame, int n)
+{
+ frame->sp -= n;
+ memset(frame->sp, 0, n * sizeof(*frame->sp));
+}
+
+static inline JitReg
+local_i32(JitFrame *frame, int n)
+{
+ return gen_load_i32(frame, n);
+}
+
+static inline JitReg
+local_i64(JitFrame *frame, int n)
+{
+ return gen_load_i64(frame, n);
+}
+
+static inline JitReg
+local_f32(JitFrame *frame, int n)
+{
+ return gen_load_f32(frame, n);
+}
+
+static inline JitReg
+local_f64(JitFrame *frame, int n)
+{
+ return gen_load_f64(frame, n);
+}
+
+static void
+set_local_i32(JitFrame *frame, int n, JitReg val)
+{
+ frame->lp[n].reg = val;
+ frame->lp[n].dirty = 1;
+}
+
+static void
+set_local_i64(JitFrame *frame, int n, JitReg val)
+{
+ frame->lp[n].reg = val;
+ frame->lp[n].dirty = 1;
+ frame->lp[n + 1].reg = val;
+ frame->lp[n + 1].dirty = 1;
+}
+
+static inline void
+set_local_f32(JitFrame *frame, int n, JitReg val)
+{
+ set_local_i32(frame, n, val);
+}
+
+static inline void
+set_local_f64(JitFrame *frame, int n, JitReg val)
+{
+ set_local_i64(frame, n, val);
+}
+
+#define POP(jit_value, value_type) \
+ do { \
+ if (!jit_cc_pop_value(cc, value_type, &jit_value)) \
+ goto fail; \
+ } 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_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
+#define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)
+
+#define PUSH(jit_value, value_type) \
+ do { \
+ if (!jit_value) \
+ goto fail; \
+ if (!jit_cc_push_value(cc, value_type, jit_value)) \
+ goto fail; \
+ } 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_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
+#define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.c
new file mode 100644
index 000000000..68503e3f5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.c
@@ -0,0 +1,1427 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_ir.h"
+#include "jit_codegen.h"
+#include "jit_frontend.h"
+
+/**
+ * Operand kinds of instructions.
+ */
+enum {
+ JIT_OPND_KIND_Reg,
+ JIT_OPND_KIND_VReg,
+ JIT_OPND_KIND_LookupSwitch,
+};
+
+/**
+ * Operand kind of each instruction.
+ */
+static const uint8 insn_opnd_kind[] = {
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE) JIT_OPND_KIND_##OPND_KIND,
+#include "jit_ir.def"
+#undef INSN
+};
+
+/**
+ * Operand number of each instruction.
+ */
+static const uint8 insn_opnd_num[] = {
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE) OPND_NUM,
+#include "jit_ir.def"
+#undef INSN
+};
+
+/**
+ * Operand number of each instruction.
+ */
+static const uint8 insn_opnd_first_use[] = {
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE) FIRST_USE,
+#include "jit_ir.def"
+#undef INSN
+};
+
+#define JIT_INSN_NEW_Reg(OPND_NUM) \
+ jit_calloc(offsetof(JitInsn, _opnd) + sizeof(JitReg) * (OPND_NUM))
+#define JIT_INSN_NEW_VReg(OPND_NUM) \
+ jit_calloc(offsetof(JitInsn, _opnd._opnd_VReg._reg) \
+ + sizeof(JitReg) * (OPND_NUM))
+
+JitInsn *
+_jit_insn_new_Reg_0(JitOpcode opc)
+{
+ JitInsn *insn = JIT_INSN_NEW_Reg(0);
+
+ if (insn) {
+ insn->opcode = opc;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_Reg_1(JitOpcode opc, JitReg r0)
+{
+ JitInsn *insn = JIT_INSN_NEW_Reg(1);
+
+ if (insn) {
+ insn->opcode = opc;
+ *jit_insn_opnd(insn, 0) = r0;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_Reg_2(JitOpcode opc, JitReg r0, JitReg r1)
+{
+ JitInsn *insn = JIT_INSN_NEW_Reg(2);
+
+ if (insn) {
+ insn->opcode = opc;
+ *jit_insn_opnd(insn, 0) = r0;
+ *jit_insn_opnd(insn, 1) = r1;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_Reg_3(JitOpcode opc, JitReg r0, JitReg r1, JitReg r2)
+{
+ JitInsn *insn = JIT_INSN_NEW_Reg(3);
+
+ if (insn) {
+ insn->opcode = opc;
+ *jit_insn_opnd(insn, 0) = r0;
+ *jit_insn_opnd(insn, 1) = r1;
+ *jit_insn_opnd(insn, 2) = r2;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_Reg_4(JitOpcode opc, JitReg r0, JitReg r1, JitReg r2, JitReg r3)
+{
+ JitInsn *insn = JIT_INSN_NEW_Reg(4);
+
+ if (insn) {
+ insn->opcode = opc;
+ *jit_insn_opnd(insn, 0) = r0;
+ *jit_insn_opnd(insn, 1) = r1;
+ *jit_insn_opnd(insn, 2) = r2;
+ *jit_insn_opnd(insn, 3) = r3;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_Reg_5(JitOpcode opc, JitReg r0, JitReg r1, JitReg r2, JitReg r3,
+ JitReg r4)
+{
+ JitInsn *insn = JIT_INSN_NEW_Reg(5);
+
+ if (insn) {
+ insn->opcode = opc;
+ *jit_insn_opnd(insn, 0) = r0;
+ *jit_insn_opnd(insn, 1) = r1;
+ *jit_insn_opnd(insn, 2) = r2;
+ *jit_insn_opnd(insn, 3) = r3;
+ *jit_insn_opnd(insn, 4) = r4;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_VReg_1(JitOpcode opc, JitReg r0, int n)
+{
+ JitInsn *insn = JIT_INSN_NEW_VReg(1 + n);
+
+ if (insn) {
+ insn->opcode = opc;
+ insn->_opnd._opnd_VReg._reg_num = 1 + n;
+ *(jit_insn_opndv(insn, 0)) = r0;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_VReg_2(JitOpcode opc, JitReg r0, JitReg r1, int n)
+{
+ JitInsn *insn = JIT_INSN_NEW_VReg(2 + n);
+
+ if (insn) {
+ insn->opcode = opc;
+ insn->_opnd._opnd_VReg._reg_num = 2 + n;
+ *(jit_insn_opndv(insn, 0)) = r0;
+ *(jit_insn_opndv(insn, 1)) = r1;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_insn_new_LookupSwitch_1(JitOpcode opc, JitReg value, uint32 num)
+{
+ JitOpndLookupSwitch *opnd = NULL;
+ JitInsn *insn =
+ jit_calloc(offsetof(JitInsn, _opnd._opnd_LookupSwitch.match_pairs)
+ + sizeof(opnd->match_pairs[0]) * num);
+
+ if (insn) {
+ insn->opcode = opc;
+ opnd = jit_insn_opndls(insn);
+ opnd->value = value;
+ opnd->match_pairs_num = num;
+ }
+
+ return insn;
+}
+
+#undef JIT_INSN_NEW_Reg
+#undef JIT_INSN_NEW_VReg
+
+void
+jit_insn_insert_before(JitInsn *insn1, JitInsn *insn2)
+{
+ bh_assert(insn1->prev);
+ insn1->prev->next = insn2;
+ insn2->prev = insn1->prev;
+ insn2->next = insn1;
+ insn1->prev = insn2;
+}
+
+void
+jit_insn_insert_after(JitInsn *insn1, JitInsn *insn2)
+{
+ bh_assert(insn1->next);
+ insn1->next->prev = insn2;
+ insn2->next = insn1->next;
+ insn2->prev = insn1;
+ insn1->next = insn2;
+}
+
+void
+jit_insn_unlink(JitInsn *insn)
+{
+ bh_assert(insn->prev);
+ insn->prev->next = insn->next;
+ bh_assert(insn->next);
+ insn->next->prev = insn->prev;
+ insn->prev = insn->next = NULL;
+}
+
+unsigned
+jit_insn_hash(JitInsn *insn)
+{
+ const uint8 opcode = insn->opcode;
+ unsigned hash = opcode, i;
+
+ /* Currently, only instructions with Reg kind operand require
+ hashing. For others, simply use opcode as the hash value. */
+ if (insn_opnd_kind[opcode] != JIT_OPND_KIND_Reg
+ || insn_opnd_num[opcode] < 1)
+ return hash;
+
+ /* All the instructions with hashing support must be in the
+ assignment format, i.e. the first operand is the result (hence
+ being ignored) and all the others are operands. This is also
+ true for CHK instructions, whose first operand is the instruction
+ pointer. */
+ for (i = 1; i < insn_opnd_num[opcode]; i++)
+ hash = ((hash << 5) - hash) + *(jit_insn_opnd(insn, i));
+
+ return hash;
+}
+
+bool
+jit_insn_equal(JitInsn *insn1, JitInsn *insn2)
+{
+ const uint8 opcode = insn1->opcode;
+ unsigned i;
+
+ if (insn2->opcode != opcode)
+ return false;
+
+ if (insn_opnd_kind[opcode] != JIT_OPND_KIND_Reg
+ || insn_opnd_num[opcode] < 1)
+ return false;
+
+ for (i = 1; i < insn_opnd_num[opcode]; i++)
+ if (*(jit_insn_opnd(insn1, i)) != *(jit_insn_opnd(insn2, i)))
+ return false;
+
+ return true;
+}
+
+JitRegVec
+jit_insn_opnd_regs(JitInsn *insn)
+{
+ JitRegVec vec = { 0 };
+ JitOpndLookupSwitch *ls;
+
+ vec._stride = 1;
+
+ switch (insn_opnd_kind[insn->opcode]) {
+ case JIT_OPND_KIND_Reg:
+ vec.num = insn_opnd_num[insn->opcode];
+ vec._base = jit_insn_opnd(insn, 0);
+ break;
+
+ case JIT_OPND_KIND_VReg:
+ vec.num = jit_insn_opndv_num(insn);
+ vec._base = jit_insn_opndv(insn, 0);
+ break;
+
+ case JIT_OPND_KIND_LookupSwitch:
+ ls = jit_insn_opndls(insn);
+ vec.num = ls->match_pairs_num + 2;
+ vec._base = &ls->value;
+ vec._stride = sizeof(ls->match_pairs[0]) / sizeof(*vec._base);
+ break;
+ }
+
+ return vec;
+}
+
+unsigned
+jit_insn_opnd_first_use(JitInsn *insn)
+{
+ return insn_opnd_first_use[insn->opcode];
+}
+
+JitBasicBlock *
+jit_basic_block_new(JitReg label, int n)
+{
+ JitBasicBlock *block = jit_insn_new_PHI(label, n);
+ if (!block)
+ return NULL;
+
+ block->prev = block->next = block;
+ return block;
+}
+
+void
+jit_basic_block_delete(JitBasicBlock *block)
+{
+ JitInsn *insn, *next_insn, *end;
+
+ if (!block)
+ return;
+
+ insn = jit_basic_block_first_insn(block);
+ end = jit_basic_block_end_insn(block);
+
+ for (; insn != end; insn = next_insn) {
+ next_insn = insn->next;
+ jit_insn_delete(insn);
+ }
+
+ jit_insn_delete(block);
+}
+
+JitRegVec
+jit_basic_block_preds(JitBasicBlock *block)
+{
+ JitRegVec vec;
+
+ vec.num = jit_insn_opndv_num(block) - 1;
+ vec._base = vec.num > 0 ? jit_insn_opndv(block, 1) : NULL;
+ vec._stride = 1;
+
+ return vec;
+}
+
+JitRegVec
+jit_basic_block_succs(JitBasicBlock *block)
+{
+ JitInsn *last_insn = jit_basic_block_last_insn(block);
+ JitRegVec vec;
+
+ vec.num = 0;
+ vec._base = NULL;
+ vec._stride = 1;
+
+ switch (last_insn->opcode) {
+ case JIT_OP_JMP:
+ vec.num = 1;
+ vec._base = jit_insn_opnd(last_insn, 0);
+ break;
+
+ case JIT_OP_BEQ:
+ case JIT_OP_BNE:
+ case JIT_OP_BGTS:
+ case JIT_OP_BGES:
+ case JIT_OP_BLTS:
+ case JIT_OP_BLES:
+ case JIT_OP_BGTU:
+ case JIT_OP_BGEU:
+ case JIT_OP_BLTU:
+ case JIT_OP_BLEU:
+ vec.num = 2;
+ vec._base = jit_insn_opnd(last_insn, 1);
+ break;
+
+ case JIT_OP_LOOKUPSWITCH:
+ {
+ JitOpndLookupSwitch *opnd = jit_insn_opndls(last_insn);
+ vec.num = opnd->match_pairs_num + 1;
+ vec._base = &opnd->default_target;
+ vec._stride = sizeof(opnd->match_pairs[0]) / sizeof(*vec._base);
+ break;
+ }
+
+ default:
+ vec._stride = 0;
+ }
+
+ return vec;
+}
+
+JitCompContext *
+jit_cc_init(JitCompContext *cc, unsigned htab_size)
+{
+ JitBasicBlock *entry_block, *exit_block;
+ unsigned i, num;
+
+ memset(cc, 0, sizeof(*cc));
+ cc->_reference_count = 1;
+ jit_annl_enable_basic_block(cc);
+
+ /* Create entry and exit blocks. They must be the first two
+ blocks respectively. */
+ if (!(entry_block = jit_cc_new_basic_block(cc, 0)))
+ goto fail;
+
+ if (!(exit_block = jit_cc_new_basic_block(cc, 0))) {
+ jit_basic_block_delete(entry_block);
+ goto fail;
+ }
+
+ /* Record the entry and exit labels, whose indexes must be 0 and 1
+ respectively. */
+ cc->entry_label = jit_basic_block_label(entry_block);
+ cc->exit_label = jit_basic_block_label(exit_block);
+ bh_assert(jit_reg_no(cc->entry_label) == 0
+ && jit_reg_no(cc->exit_label) == 1);
+
+ if (!(cc->exce_basic_blocks =
+ jit_calloc(sizeof(JitBasicBlock *) * EXCE_NUM)))
+ goto fail;
+
+ if (!(cc->incoming_insns_for_exec_bbs =
+ jit_calloc(sizeof(JitIncomingInsnList) * EXCE_NUM)))
+ goto fail;
+
+ cc->hreg_info = jit_codegen_get_hreg_info();
+ bh_assert(cc->hreg_info->info[JIT_REG_KIND_I32].num > 3);
+
+ /* Initialize virtual registers for hard registers. */
+ for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
+ if ((num = cc->hreg_info->info[i].num)) {
+ /* Initialize the capacity to be large enough. */
+ jit_cc_new_reg(cc, i);
+ bh_assert(cc->_ann._reg_capacity[i] > num);
+ cc->_ann._reg_num[i] = num;
+ }
+ }
+
+ /* Create registers for frame pointer, exec_env and cmp. */
+ cc->fp_reg = jit_reg_new(JIT_REG_KIND_PTR, cc->hreg_info->fp_hreg_index);
+ cc->exec_env_reg =
+ jit_reg_new(JIT_REG_KIND_PTR, cc->hreg_info->exec_env_hreg_index);
+ cc->cmp_reg = jit_reg_new(JIT_REG_KIND_I32, cc->hreg_info->cmp_hreg_index);
+
+ cc->_const_val._hash_table_size = htab_size;
+
+ if (!(cc->_const_val._hash_table =
+ jit_calloc(htab_size * sizeof(*cc->_const_val._hash_table))))
+ goto fail;
+
+ return cc;
+
+fail:
+ jit_cc_destroy(cc);
+ return NULL;
+}
+
+void
+jit_cc_destroy(JitCompContext *cc)
+{
+ unsigned i, end;
+ JitBasicBlock *block;
+ JitIncomingInsn *incoming_insn, *incoming_insn_next;
+
+ jit_block_stack_destroy(&cc->block_stack);
+
+ if (cc->jit_frame) {
+ if (cc->jit_frame->memory_regs)
+ jit_free(cc->jit_frame->memory_regs);
+ if (cc->jit_frame->table_regs)
+ jit_free(cc->jit_frame->table_regs);
+ jit_free(cc->jit_frame);
+ }
+
+ if (cc->memory_regs)
+ jit_free(cc->memory_regs);
+
+ if (cc->table_regs)
+ jit_free(cc->table_regs);
+
+ jit_free(cc->_const_val._hash_table);
+
+ /* Release the instruction hash table. */
+ jit_cc_disable_insn_hash(cc);
+
+ jit_free(cc->exce_basic_blocks);
+
+ if (cc->incoming_insns_for_exec_bbs) {
+ for (i = 0; i < EXCE_NUM; i++) {
+ incoming_insn = cc->incoming_insns_for_exec_bbs[i];
+ while (incoming_insn) {
+ incoming_insn_next = incoming_insn->next;
+ jit_free(incoming_insn);
+ incoming_insn = incoming_insn_next;
+ }
+ }
+ jit_free(cc->incoming_insns_for_exec_bbs);
+ }
+
+ /* Release entry and exit blocks. */
+ if (0 != cc->entry_label)
+ jit_basic_block_delete(jit_cc_entry_basic_block(cc));
+ if (0 != cc->exit_label)
+ jit_basic_block_delete(jit_cc_exit_basic_block(cc));
+
+ /* clang-format off */
+ /* Release blocks and instructions. */
+ JIT_FOREACH_BLOCK(cc, i, end, block)
+ {
+ jit_basic_block_delete(block);
+ }
+ /* clang-format on */
+
+ /* Release constant values. */
+ for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
+ jit_free(cc->_const_val._value[i]);
+ jit_free(cc->_const_val._next[i]);
+ }
+
+ /* Release storage of annotations. */
+#define ANN_LABEL(TYPE, NAME) jit_annl_disable_##NAME(cc);
+#define ANN_INSN(TYPE, NAME) jit_anni_disable_##NAME(cc);
+#define ANN_REG(TYPE, NAME) jit_annr_disable_##NAME(cc);
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+}
+
+void
+jit_cc_delete(JitCompContext *cc)
+{
+ if (cc && --cc->_reference_count == 0) {
+ jit_cc_destroy(cc);
+ jit_free(cc);
+ }
+}
+
+/*
+ * Reallocate a memory block with the new_size.
+ * TODO: replace this with imported jit_realloc when it's available.
+ */
+static void *
+_jit_realloc(void *ptr, unsigned new_size, unsigned old_size)
+{
+ void *new_ptr = jit_malloc(new_size);
+
+ if (new_ptr) {
+ bh_assert(new_size > old_size);
+
+ if (ptr) {
+ memcpy(new_ptr, ptr, old_size);
+ memset((uint8 *)new_ptr + old_size, 0, new_size - old_size);
+ jit_free(ptr);
+ }
+ else
+ memset(new_ptr, 0, new_size);
+ }
+
+ return new_ptr;
+}
+
+static unsigned
+hash_of_const(unsigned kind, unsigned size, void *val)
+{
+ uint8 *p = (uint8 *)val, *end = p + size;
+ unsigned hash = kind;
+
+ do
+ hash = ((hash << 5) - hash) + *p++;
+ while (p != end);
+
+ return hash;
+}
+
+static inline void *
+address_of_const(JitCompContext *cc, JitReg reg, unsigned size)
+{
+ int kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+ unsigned idx = no & ~_JIT_REG_CONST_IDX_FLAG;
+
+ bh_assert(kind < JIT_REG_KIND_L32);
+ bh_assert(jit_reg_is_const_idx(reg) && idx < cc->_const_val._num[kind]);
+
+ return cc->_const_val._value[kind] + size * idx;
+}
+
+static inline JitReg
+next_of_const(JitCompContext *cc, JitReg reg)
+{
+ int kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+ unsigned idx = no & ~_JIT_REG_CONST_IDX_FLAG;
+
+ bh_assert(kind < JIT_REG_KIND_L32);
+ bh_assert(jit_reg_is_const_idx(reg) && idx < cc->_const_val._num[kind]);
+
+ return cc->_const_val._next[kind][idx];
+}
+
+/**
+ * Put a constant value into the compilation context.
+ *
+ * @param cc compilation context
+ * @param kind register kind
+ * @param size size of the value
+ * @param val pointer to value which must be aligned
+ *
+ * @return a constant register containing the value
+ */
+static JitReg
+_jit_cc_new_const(JitCompContext *cc, int kind, unsigned size, void *val)
+{
+ unsigned num = cc->_const_val._num[kind], slot;
+ unsigned capacity = cc->_const_val._capacity[kind];
+ uint8 *new_value;
+ JitReg r, *new_next;
+
+ bh_assert(num <= capacity);
+
+ /* Find the existing value first. */
+ slot = hash_of_const(kind, size, val) % cc->_const_val._hash_table_size;
+ r = cc->_const_val._hash_table[slot];
+
+ for (; r; r = next_of_const(cc, r))
+ if (jit_reg_kind(r) == kind
+ && !memcmp(val, address_of_const(cc, r, size), size))
+ return r;
+
+ if (num == capacity) {
+ /* Increase the space of value and next. */
+ capacity = capacity > 0 ? (capacity + capacity / 2) : 16;
+ new_value = _jit_realloc(cc->_const_val._value[kind], size * capacity,
+ size * num);
+ new_next =
+ _jit_realloc(cc->_const_val._next[kind],
+ sizeof(*new_next) * capacity, sizeof(*new_next) * num);
+
+ if (new_value && new_next) {
+ cc->_const_val._value[kind] = new_value;
+ cc->_const_val._next[kind] = new_next;
+ }
+ else {
+ jit_set_last_error(cc, "create const register failed");
+ jit_free(new_value);
+ jit_free(new_next);
+ return 0;
+ }
+
+ cc->_const_val._capacity[kind] = capacity;
+ }
+
+ bh_assert(num + 1 < (uint32)_JIT_REG_CONST_IDX_FLAG);
+ r = jit_reg_new(kind, _JIT_REG_CONST_IDX_FLAG | num);
+ memcpy(cc->_const_val._value[kind] + size * num, val, size);
+ cc->_const_val._next[kind][num] = cc->_const_val._hash_table[slot];
+ cc->_const_val._hash_table[slot] = r;
+ cc->_const_val._num[kind] = num + 1;
+
+ return r;
+}
+
+static inline int32
+get_const_val_in_reg(JitReg reg)
+{
+ int shift = 8 * sizeof(reg) - _JIT_REG_KIND_SHIFT + 1;
+ return ((int32)(reg << shift)) >> shift;
+}
+
+#define _JIT_CC_NEW_CONST_HELPER(KIND, TYPE, val) \
+ do { \
+ JitReg reg = jit_reg_new( \
+ JIT_REG_KIND_##KIND, \
+ (_JIT_REG_CONST_VAL_FLAG | ((JitReg)val & ~_JIT_REG_KIND_MASK))); \
+ \
+ if ((TYPE)get_const_val_in_reg(reg) == val) \
+ return reg; \
+ return _jit_cc_new_const(cc, JIT_REG_KIND_##KIND, sizeof(val), &val); \
+ } while (0)
+
+JitReg
+jit_cc_new_const_I32_rel(JitCompContext *cc, int32 val, uint32 rel)
+{
+ uint64 val64 = (uint64)(uint32)val | ((uint64)rel << 32);
+ _JIT_CC_NEW_CONST_HELPER(I32, uint64, val64);
+}
+
+JitReg
+jit_cc_new_const_I64(JitCompContext *cc, int64 val)
+{
+ _JIT_CC_NEW_CONST_HELPER(I64, int64, val);
+}
+
+JitReg
+jit_cc_new_const_F32(JitCompContext *cc, float val)
+{
+ int32 float_neg_zero = 0x80000000;
+
+ if (!memcmp(&val, &float_neg_zero, sizeof(float)))
+ /* Create const -0.0f */
+ return _jit_cc_new_const(cc, JIT_REG_KIND_F32, sizeof(float), &val);
+
+ _JIT_CC_NEW_CONST_HELPER(F32, float, val);
+}
+
+JitReg
+jit_cc_new_const_F64(JitCompContext *cc, double val)
+{
+ int64 double_neg_zero = 0x8000000000000000ll;
+
+ if (!memcmp(&val, &double_neg_zero, sizeof(double)))
+ /* Create const -0.0d */
+ return _jit_cc_new_const(cc, JIT_REG_KIND_F64, sizeof(double), &val);
+
+ _JIT_CC_NEW_CONST_HELPER(F64, double, val);
+}
+
+#undef _JIT_CC_NEW_CONST_HELPER
+
+#define _JIT_CC_GET_CONST_HELPER(KIND, TYPE) \
+ do { \
+ bh_assert(jit_reg_kind(reg) == JIT_REG_KIND_##KIND); \
+ bh_assert(jit_reg_is_const(reg)); \
+ \
+ return (jit_reg_is_const_val(reg) \
+ ? (TYPE)get_const_val_in_reg(reg) \
+ : *(TYPE *)(address_of_const(cc, reg, sizeof(TYPE)))); \
+ } while (0)
+
+static uint64
+jit_cc_get_const_I32_helper(JitCompContext *cc, JitReg reg)
+{
+ _JIT_CC_GET_CONST_HELPER(I32, uint64);
+}
+
+uint32
+jit_cc_get_const_I32_rel(JitCompContext *cc, JitReg reg)
+{
+ return (uint32)(jit_cc_get_const_I32_helper(cc, reg) >> 32);
+}
+
+int32
+jit_cc_get_const_I32(JitCompContext *cc, JitReg reg)
+{
+ return (int32)(jit_cc_get_const_I32_helper(cc, reg));
+}
+
+int64
+jit_cc_get_const_I64(JitCompContext *cc, JitReg reg)
+{
+ _JIT_CC_GET_CONST_HELPER(I64, int64);
+}
+
+float
+jit_cc_get_const_F32(JitCompContext *cc, JitReg reg)
+{
+ _JIT_CC_GET_CONST_HELPER(F32, float);
+}
+
+double
+jit_cc_get_const_F64(JitCompContext *cc, JitReg reg)
+{
+ _JIT_CC_GET_CONST_HELPER(F64, double);
+}
+
+#undef _JIT_CC_GET_CONST_HELPER
+
+#define _JIT_REALLOC_ANN(TYPE, NAME, ANN, POSTFIX) \
+ if (successful && cc->_ann._##ANN##_##NAME##_enabled) { \
+ TYPE *ptr = _jit_realloc(cc->_ann._##ANN##_##NAME POSTFIX, \
+ sizeof(TYPE) * capacity, sizeof(TYPE) * num); \
+ if (ptr) \
+ cc->_ann._##ANN##_##NAME POSTFIX = ptr; \
+ else \
+ successful = false; \
+ }
+
+JitReg
+jit_cc_new_label(JitCompContext *cc)
+{
+ unsigned num = cc->_ann._label_num;
+ unsigned capacity = cc->_ann._label_capacity;
+ bool successful = true;
+
+ bh_assert(num <= capacity);
+
+ if (num == capacity) {
+ capacity = capacity > 0 ? (capacity + capacity / 2) : 16;
+
+#define EMPTY_POSTFIX
+#define ANN_LABEL(TYPE, NAME) _JIT_REALLOC_ANN(TYPE, NAME, label, EMPTY_POSTFIX)
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef EMPTY_POSTFIX
+
+ if (!successful) {
+ jit_set_last_error(cc, "create label register failed");
+ return 0;
+ }
+
+ cc->_ann._label_capacity = capacity;
+ }
+
+ cc->_ann._label_num = num + 1;
+
+ return jit_reg_new(JIT_REG_KIND_L32, num);
+}
+
+JitBasicBlock *
+jit_cc_new_basic_block(JitCompContext *cc, int n)
+{
+ JitReg label = jit_cc_new_label(cc);
+ JitBasicBlock *block = NULL;
+
+ if (label && (block = jit_basic_block_new(label, n)))
+ /* Void 0 register indicates error in creation. */
+ *(jit_annl_basic_block(cc, label)) = block;
+ else
+ jit_set_last_error(cc, "create basic block failed");
+
+ return block;
+}
+
+JitBasicBlock *
+jit_cc_resize_basic_block(JitCompContext *cc, JitBasicBlock *block, int n)
+{
+ JitReg label = jit_basic_block_label(block);
+ JitInsn *insn = jit_basic_block_first_insn(block);
+ JitBasicBlock *new_block = jit_basic_block_new(label, n);
+
+ if (!new_block) {
+ jit_set_last_error(cc, "resize basic block failed");
+ return NULL;
+ }
+
+ jit_insn_unlink(block);
+
+ if (insn != block)
+ jit_insn_insert_before(insn, new_block);
+
+ bh_assert(*(jit_annl_basic_block(cc, label)) == block);
+ *(jit_annl_basic_block(cc, label)) = new_block;
+ jit_insn_delete(block);
+
+ return new_block;
+}
+
+bool
+jit_cc_enable_insn_hash(JitCompContext *cc, unsigned n)
+{
+ if (jit_anni_is_enabled__hash_link(cc))
+ return true;
+
+ if (!jit_anni_enable__hash_link(cc))
+ return false;
+
+ /* The table must not exist. */
+ bh_assert(!cc->_insn_hash_table._table);
+
+ /* Integer overflow cannot happen because n << 4G (at most several
+ times of 64K in the most extreme case). */
+ if (!(cc->_insn_hash_table._table =
+ jit_calloc(n * sizeof(*cc->_insn_hash_table._table)))) {
+ jit_anni_disable__hash_link(cc);
+ return false;
+ }
+
+ cc->_insn_hash_table._size = n;
+ return true;
+}
+
+void
+jit_cc_disable_insn_hash(JitCompContext *cc)
+{
+ jit_anni_disable__hash_link(cc);
+ jit_free(cc->_insn_hash_table._table);
+ cc->_insn_hash_table._table = NULL;
+ cc->_insn_hash_table._size = 0;
+}
+
+void
+jit_cc_reset_insn_hash(JitCompContext *cc)
+{
+ if (jit_anni_is_enabled__hash_link(cc))
+ memset(cc->_insn_hash_table._table, 0,
+ cc->_insn_hash_table._size
+ * sizeof(*cc->_insn_hash_table._table));
+}
+
+JitInsn *
+jit_cc_set_insn_uid(JitCompContext *cc, JitInsn *insn)
+{
+ if (insn) {
+ unsigned num = cc->_ann._insn_num;
+ unsigned capacity = cc->_ann._insn_capacity;
+ bool successful = true;
+
+ bh_assert(num <= capacity);
+
+ if (num == capacity) {
+ capacity = capacity > 0 ? (capacity + capacity / 2) : 64;
+
+#define EMPTY_POSTFIX
+#define ANN_INSN(TYPE, NAME) _JIT_REALLOC_ANN(TYPE, NAME, insn, EMPTY_POSTFIX)
+#include "jit_ir.def"
+#undef ANN_INSN
+#undef EMPTY_POSTFIX
+
+ if (!successful) {
+ jit_set_last_error(cc, "set insn uid failed");
+ return NULL;
+ }
+
+ cc->_ann._insn_capacity = capacity;
+ }
+
+ cc->_ann._insn_num = num + 1;
+ insn->uid = num;
+ }
+
+ return insn;
+}
+
+JitInsn *
+_jit_cc_set_insn_uid_for_new_insn(JitCompContext *cc, JitInsn *insn)
+{
+ if (jit_cc_set_insn_uid(cc, insn))
+ return insn;
+
+ jit_insn_delete(insn);
+ return NULL;
+}
+
+JitReg
+jit_cc_new_reg(JitCompContext *cc, unsigned kind)
+{
+ unsigned num = jit_cc_reg_num(cc, kind);
+ unsigned capacity = cc->_ann._reg_capacity[kind];
+ bool successful = true;
+
+ bh_assert(num <= capacity);
+
+ if (num == capacity) {
+ capacity = (capacity == 0
+ /* Initialize the capacity to be larger than hard
+ register number. */
+ ? cc->hreg_info->info[kind].num + 16
+ : capacity + capacity / 2);
+
+#define ANN_REG(TYPE, NAME) _JIT_REALLOC_ANN(TYPE, NAME, reg, [kind])
+#include "jit_ir.def"
+#undef ANN_REG
+
+ if (!successful) {
+ jit_set_last_error(cc, "create register failed");
+ return 0;
+ }
+
+ cc->_ann._reg_capacity[kind] = capacity;
+ }
+
+ cc->_ann._reg_num[kind] = num + 1;
+
+ return jit_reg_new(kind, num);
+}
+
+#undef _JIT_REALLOC_ANN
+
+#define ANN_LABEL(TYPE, NAME) \
+ bool jit_annl_enable_##NAME(JitCompContext *cc) \
+ { \
+ if (cc->_ann._label_##NAME##_enabled) \
+ return true; \
+ \
+ if (cc->_ann._label_capacity > 0 \
+ && !(cc->_ann._label_##NAME = \
+ jit_calloc(cc->_ann._label_capacity * sizeof(TYPE)))) { \
+ jit_set_last_error(cc, "annl enable " #NAME "failed"); \
+ return false; \
+ } \
+ \
+ cc->_ann._label_##NAME##_enabled = 1; \
+ return true; \
+ }
+#define ANN_INSN(TYPE, NAME) \
+ bool jit_anni_enable_##NAME(JitCompContext *cc) \
+ { \
+ if (cc->_ann._insn_##NAME##_enabled) \
+ return true; \
+ \
+ if (cc->_ann._insn_capacity > 0 \
+ && !(cc->_ann._insn_##NAME = \
+ jit_calloc(cc->_ann._insn_capacity * sizeof(TYPE)))) { \
+ jit_set_last_error(cc, "anni enable " #NAME "failed"); \
+ return false; \
+ } \
+ \
+ cc->_ann._insn_##NAME##_enabled = 1; \
+ return true; \
+ }
+#define ANN_REG(TYPE, NAME) \
+ bool jit_annr_enable_##NAME(JitCompContext *cc) \
+ { \
+ unsigned k; \
+ \
+ if (cc->_ann._reg_##NAME##_enabled) \
+ return true; \
+ \
+ for (k = JIT_REG_KIND_VOID; k < JIT_REG_KIND_L32; k++) \
+ if (cc->_ann._reg_capacity[k] > 0 \
+ && !(cc->_ann._reg_##NAME[k] = jit_calloc( \
+ cc->_ann._reg_capacity[k] * sizeof(TYPE)))) { \
+ jit_set_last_error(cc, "annr enable " #NAME "failed"); \
+ jit_annr_disable_##NAME(cc); \
+ return false; \
+ } \
+ \
+ cc->_ann._reg_##NAME##_enabled = 1; \
+ return true; \
+ }
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+#define ANN_LABEL(TYPE, NAME) \
+ void jit_annl_disable_##NAME(JitCompContext *cc) \
+ { \
+ jit_free(cc->_ann._label_##NAME); \
+ cc->_ann._label_##NAME = NULL; \
+ cc->_ann._label_##NAME##_enabled = 0; \
+ }
+#define ANN_INSN(TYPE, NAME) \
+ void jit_anni_disable_##NAME(JitCompContext *cc) \
+ { \
+ jit_free(cc->_ann._insn_##NAME); \
+ cc->_ann._insn_##NAME = NULL; \
+ cc->_ann._insn_##NAME##_enabled = 0; \
+ }
+#define ANN_REG(TYPE, NAME) \
+ void jit_annr_disable_##NAME(JitCompContext *cc) \
+ { \
+ unsigned k; \
+ \
+ for (k = JIT_REG_KIND_VOID; k < JIT_REG_KIND_L32; k++) { \
+ jit_free(cc->_ann._reg_##NAME[k]); \
+ cc->_ann._reg_##NAME[k] = NULL; \
+ } \
+ \
+ cc->_ann._reg_##NAME##_enabled = 0; \
+ }
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+char *
+jit_get_last_error(JitCompContext *cc)
+{
+ return cc->last_error[0] == '\0' ? NULL : cc->last_error;
+}
+
+void
+jit_set_last_error_v(JitCompContext *cc, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vsnprintf(cc->last_error, sizeof(cc->last_error), format, args);
+ va_end(args);
+}
+
+void
+jit_set_last_error(JitCompContext *cc, const char *error)
+{
+ if (error)
+ snprintf(cc->last_error, sizeof(cc->last_error), "Error: %s", error);
+ else
+ cc->last_error[0] = '\0';
+}
+
+bool
+jit_cc_update_cfg(JitCompContext *cc)
+{
+ JitBasicBlock *block;
+ unsigned block_index, end, succ_index, idx;
+ JitReg *target;
+ bool retval = false;
+
+ if (!jit_annl_enable_pred_num(cc))
+ return false;
+
+ /* Update pred_num of all blocks. */
+ JIT_FOREACH_BLOCK_ENTRY_EXIT(cc, block_index, end, block)
+ {
+ JitRegVec succs = jit_basic_block_succs(block);
+
+ JIT_REG_VEC_FOREACH(succs, succ_index, target)
+ if (jit_reg_is_kind(L32, *target))
+ *(jit_annl_pred_num(cc, *target)) += 1;
+ }
+
+ /* Resize predecessor vectors of body blocks. */
+ JIT_FOREACH_BLOCK(cc, block_index, end, block)
+ {
+ if (!jit_cc_resize_basic_block(
+ cc, block,
+ *(jit_annl_pred_num(cc, jit_basic_block_label(block)))))
+ goto cleanup_and_return;
+ }
+
+ /* Fill in predecessor vectors all blocks. */
+ JIT_FOREACH_BLOCK_REVERSE_ENTRY_EXIT(cc, block_index, block)
+ {
+ JitRegVec succs = jit_basic_block_succs(block), preds;
+
+ JIT_REG_VEC_FOREACH(succs, succ_index, target)
+ if (jit_reg_is_kind(L32, *target)) {
+ preds = jit_basic_block_preds(*(jit_annl_basic_block(cc, *target)));
+ bh_assert(*(jit_annl_pred_num(cc, *target)) > 0);
+ idx = *(jit_annl_pred_num(cc, *target)) - 1;
+ *(jit_annl_pred_num(cc, *target)) = idx;
+ *(jit_reg_vec_at(&preds, idx)) = jit_basic_block_label(block);
+ }
+ }
+
+ retval = true;
+
+cleanup_and_return:
+ jit_annl_disable_pred_num(cc);
+ return retval;
+}
+
+void
+jit_value_stack_push(JitValueStack *stack, JitValue *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;
+ }
+}
+
+JitValue *
+jit_value_stack_pop(JitValueStack *stack)
+{
+ JitValue *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
+jit_value_stack_destroy(JitValueStack *stack)
+{
+ JitValue *value = stack->value_list_head, *p;
+
+ while (value) {
+ p = value->next;
+ jit_free(value);
+ value = p;
+ }
+
+ stack->value_list_head = NULL;
+ stack->value_list_end = NULL;
+}
+
+void
+jit_block_stack_push(JitBlockStack *stack, JitBlock *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;
+ }
+}
+
+JitBlock *
+jit_block_stack_top(JitBlockStack *stack)
+{
+ return stack->block_list_end;
+}
+
+JitBlock *
+jit_block_stack_pop(JitBlockStack *stack)
+{
+ JitBlock *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
+jit_block_stack_destroy(JitBlockStack *stack)
+{
+ JitBlock *block = stack->block_list_head, *p;
+
+ while (block) {
+ p = block->next;
+ jit_value_stack_destroy(&block->value_stack);
+ jit_block_destroy(block);
+ block = p;
+ }
+
+ stack->block_list_head = NULL;
+ stack->block_list_end = NULL;
+}
+
+bool
+jit_block_add_incoming_insn(JitBlock *block, JitInsn *insn, uint32 opnd_idx)
+{
+ JitIncomingInsn *incoming_insn;
+
+ if (!(incoming_insn = jit_calloc((uint32)sizeof(JitIncomingInsn))))
+ return false;
+
+ incoming_insn->insn = insn;
+ incoming_insn->opnd_idx = opnd_idx;
+ incoming_insn->next = block->incoming_insns_for_end_bb;
+ block->incoming_insns_for_end_bb = incoming_insn;
+ return true;
+}
+
+void
+jit_block_destroy(JitBlock *block)
+{
+ JitIncomingInsn *incoming_insn, *incoming_insn_next;
+
+ jit_value_stack_destroy(&block->value_stack);
+ if (block->param_types)
+ jit_free(block->param_types);
+ if (block->result_types)
+ jit_free(block->result_types);
+
+ incoming_insn = block->incoming_insns_for_end_bb;
+ while (incoming_insn) {
+ incoming_insn_next = incoming_insn->next;
+ jit_free(incoming_insn);
+ incoming_insn = incoming_insn_next;
+ }
+
+ jit_free(block);
+}
+
+static inline uint8
+to_stack_value_type(uint8 type)
+{
+#if WASM_ENABLE_REF_TYPES != 0
+ if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF)
+ return VALUE_TYPE_I32;
+#endif
+ return type;
+}
+
+bool
+jit_cc_pop_value(JitCompContext *cc, uint8 type, JitReg *p_value)
+{
+ JitValue *jit_value = NULL;
+ JitReg value = 0;
+
+ if (!jit_block_stack_top(&cc->block_stack)) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return false;
+ }
+ if (!jit_block_stack_top(&cc->block_stack)->value_stack.value_list_end) {
+ jit_set_last_error(cc, "WASM data stack underflow");
+ return false;
+ }
+
+ jit_value = jit_value_stack_pop(
+ &jit_block_stack_top(&cc->block_stack)->value_stack);
+ bh_assert(jit_value);
+
+ if (jit_value->type != to_stack_value_type(type)) {
+ jit_set_last_error(cc, "invalid WASM stack data type");
+ jit_free(jit_value);
+ return false;
+ }
+
+ switch (jit_value->type) {
+ case VALUE_TYPE_I32:
+ value = pop_i32(cc->jit_frame);
+ break;
+ case VALUE_TYPE_I64:
+ value = pop_i64(cc->jit_frame);
+ break;
+ case VALUE_TYPE_F32:
+ value = pop_f32(cc->jit_frame);
+ break;
+ case VALUE_TYPE_F64:
+ value = pop_f64(cc->jit_frame);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ bh_assert(cc->jit_frame->sp == jit_value->value);
+ bh_assert(value == jit_value->value->reg);
+ *p_value = value;
+ jit_free(jit_value);
+ return true;
+}
+
+bool
+jit_cc_push_value(JitCompContext *cc, uint8 type, JitReg value)
+{
+ JitValue *jit_value;
+
+ if (!jit_block_stack_top(&cc->block_stack)) {
+ jit_set_last_error(cc, "WASM block stack underflow");
+ return false;
+ }
+
+ if (!(jit_value = jit_calloc(sizeof(JitValue)))) {
+ jit_set_last_error(cc, "allocate memory failed");
+ return false;
+ }
+
+ bh_assert(value);
+
+ jit_value->type = to_stack_value_type(type);
+ jit_value->value = cc->jit_frame->sp;
+ jit_value_stack_push(&jit_block_stack_top(&cc->block_stack)->value_stack,
+ jit_value);
+
+ switch (jit_value->type) {
+ case VALUE_TYPE_I32:
+ push_i32(cc->jit_frame, value);
+ break;
+ case VALUE_TYPE_I64:
+ push_i64(cc->jit_frame, value);
+ break;
+ case VALUE_TYPE_F32:
+ push_f32(cc->jit_frame, value);
+ break;
+ case VALUE_TYPE_F64:
+ push_f64(cc->jit_frame, value);
+ break;
+ }
+
+ return true;
+}
+
+bool
+_jit_insn_check_opnd_access_Reg(const JitInsn *insn, unsigned n)
+{
+ unsigned opcode = insn->opcode;
+ return (insn_opnd_kind[opcode] == JIT_OPND_KIND_Reg
+ && n < insn_opnd_num[opcode]);
+}
+
+bool
+_jit_insn_check_opnd_access_VReg(const JitInsn *insn, unsigned n)
+{
+ unsigned opcode = insn->opcode;
+ return (insn_opnd_kind[opcode] == JIT_OPND_KIND_VReg
+ && n < insn->_opnd._opnd_VReg._reg_num);
+}
+
+bool
+_jit_insn_check_opnd_access_LookupSwitch(const JitInsn *insn)
+{
+ unsigned opcode = insn->opcode;
+ return (insn_opnd_kind[opcode] == JIT_OPND_KIND_LookupSwitch);
+}
+
+bool
+jit_lock_reg_in_insn(JitCompContext *cc, JitInsn *the_insn, JitReg reg_to_lock)
+{
+ bool ret = false;
+ JitInsn *prevent_spill = NULL;
+ JitInsn *indicate_using = NULL;
+
+ if (!the_insn)
+ goto just_return;
+
+ if (jit_cc_is_hreg_fixed(cc, reg_to_lock)) {
+ ret = true;
+ goto just_return;
+ }
+
+ /**
+ * give the virtual register of the locked hard register a minimum, non-zero
+ * distance, * so as to prevent it from being spilled out
+ */
+ prevent_spill = jit_insn_new_MOV(reg_to_lock, reg_to_lock);
+ if (!prevent_spill)
+ goto just_return;
+
+ jit_insn_insert_before(the_insn, prevent_spill);
+
+ /**
+ * announce the locked hard register is being used, and do necessary spill
+ * ASAP
+ */
+ indicate_using = jit_insn_new_MOV(reg_to_lock, reg_to_lock);
+ if (!indicate_using)
+ goto just_return;
+
+ jit_insn_insert_after(the_insn, indicate_using);
+
+ ret = true;
+
+just_return:
+ if (!ret)
+ jit_set_last_error(cc, "generate insn failed");
+ return ret;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.def b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.def
new file mode 100644
index 000000000..046bea1ff
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.def
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/**
+ * @file jit-ir.def
+ *
+ * @brief Definition of JIT IR instructions and annotations.
+ */
+
+/**
+ * @def INSN (NAME, OPND_KIND, OPND_NUM, FIRST_USE)
+ *
+ * Definition of IR instructions
+ *
+ * @param NAME name of the opcode
+ * @param OPND_KIND kind of the operand(s)
+ * @param OPND_NUM number of the operand(s)
+ * @param FIRST_USE index of the first use register
+ *
+ * @p OPND_KIND and @p OPND_NUM together determine the format of an
+ * instruction. There are four kinds of formats:
+ *
+ * 1) Reg: fixed-number register operands, @p OPND_NUM specifies the
+ * number of operands;
+ *
+ * 2) VReg: variable-number register operands, @p OPND_NUM specifies
+ * the number of fixed register operands;
+ *
+ * 3) TableSwitch: tableswitch instruction's format, @p OPND_NUM must
+ * be 1;
+ *
+ * 4) LookupSwitch: lookupswitch instruction's format, @p OPND_NUM
+ * must be 1.
+ *
+ * Instruction operands are all registers and they are organized in an
+ * order that all registers defined by the instruction, if any, appear
+ * before the registers used by the instruction. The @p FIRST_USE is
+ * the index of the first use register in the register vector sorted
+ * in this order. Use @c jit_insn_opnd_regs to get the register
+ * vector in this order and use @c jit_insn_opnd_first_use to get the
+ * index of the first use register.
+ *
+ * Every instruction with name @p NAME has the following definitions:
+ *
+ * @c JEFF_OP_NAME: the enum opcode of insn NAME
+ * @c jit_insn_new_NAME (...): creates a new instance of insn NAME
+ *
+ * An instruction is deleted by function:
+ *
+ * @c jit_insn_delete (@p insn)
+ *
+ * In the scope of this IR's terminology, operand and argument have
+ * different meanings. The operand is a general notation, which
+ * denotes every raw operand of an instruction, while the argument
+ * only denotes the variable part of operands of instructions of VReg
+ * kind. For example, a VReg instruction phi node "r0 = phi(r1, r2)"
+ * has three operands opnd[0]: r0, opnd[1]: r1 and opnd[2]: r2, but
+ * only two arguments arg[0]: r1 and arg[1]: r2. Operands or
+ * arguments of instructions with various formats can be access
+ * through the following APIs:
+ *
+ * @c jit_insn_opnd (@p insn, @p n): for Reg_N formats
+ * @c jit_insn_opndv (@p insn, @p n): for VReg_N formats
+ * @c jit_insn_opndv_num (@p insn): for VReg_N formats
+ * @c jit_insn_opndts (@p insn): for TableSwitch_1 format
+ * @c jit_insn_opndls (@p insn): for LookupSwitch_1 format
+ */
+
+#ifndef INSN
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE)
+#endif
+
+/* Move and conversion instructions that transfer values among
+ registers of the same kind (move) or different kinds (convert) */
+INSN(MOV, Reg, 2, 1)
+INSN(PHI, VReg, 1, 1)
+
+/* conversion. will extend or truncate */
+INSN(I8TOI32, Reg, 2, 1)
+INSN(I8TOI64, Reg, 2, 1)
+INSN(I16TOI32, Reg, 2, 1)
+INSN(I16TOI64, Reg, 2, 1)
+INSN(I32TOI8, Reg, 2, 1)
+INSN(I32TOU8, Reg, 2, 1)
+INSN(I32TOI16, Reg, 2, 1)
+INSN(I32TOU16, Reg, 2, 1)
+INSN(I32TOI64, Reg, 2, 1)
+INSN(I32TOF32, Reg, 2, 1)
+INSN(I32TOF64, Reg, 2, 1)
+INSN(U32TOI64, Reg, 2, 1)
+INSN(U32TOF32, Reg, 2, 1)
+INSN(U32TOF64, Reg, 2, 1)
+INSN(I64TOI8, Reg, 2, 1)
+INSN(I64TOI16, Reg, 2, 1)
+INSN(I64TOI32, Reg, 2, 1)
+INSN(I64TOF32, Reg, 2, 1)
+INSN(I64TOF64, Reg, 2, 1)
+INSN(F32TOI32, Reg, 2, 1)
+INSN(F32TOI64, Reg, 2, 1)
+INSN(F32TOF64, Reg, 2, 1)
+INSN(F32TOU32, Reg, 2, 1)
+INSN(F64TOI32, Reg, 2, 1)
+INSN(F64TOI64, Reg, 2, 1)
+INSN(F64TOF32, Reg, 2, 1)
+INSN(F64TOU32, Reg, 2, 1)
+
+/**
+ * Re-interpret binary presentations:
+ * *(i32 *)&f32, *(i64 *)&f64, *(f32 *)&i32, *(f64 *)&i64
+ */
+INSN(I32CASTF32, Reg, 2, 1)
+INSN(I64CASTF64, Reg, 2, 1)
+INSN(F32CASTI32, Reg, 2, 1)
+INSN(F64CASTI64, Reg, 2, 1)
+
+/* Arithmetic and bitwise instructions: */
+INSN(NEG, Reg, 2, 1)
+INSN(NOT, Reg, 2, 1)
+INSN(ADD, Reg, 3, 1)
+INSN(SUB, Reg, 3, 1)
+INSN(MUL, Reg, 3, 1)
+INSN(DIV_S, Reg, 3, 1)
+INSN(REM_S, Reg, 3, 1)
+INSN(DIV_U, Reg, 3, 1)
+INSN(REM_U, Reg, 3, 1)
+INSN(SHL, Reg, 3, 1)
+INSN(SHRS, Reg, 3, 1)
+INSN(SHRU, Reg, 3, 1)
+INSN(ROTL, Reg, 3, 1)
+INSN(ROTR, Reg, 3, 1)
+INSN(OR, Reg, 3, 1)
+INSN(XOR, Reg, 3, 1)
+INSN(AND, Reg, 3, 1)
+INSN(CMP, Reg, 3, 1)
+INSN(MAX, Reg, 3, 1)
+INSN(MIN, Reg, 3, 1)
+INSN(CLZ, Reg, 2, 1)
+INSN(CTZ, Reg, 2, 1)
+INSN(POPCNT, Reg, 2, 1)
+
+/* Select instruction: */
+INSN(SELECTEQ, Reg, 4, 1)
+INSN(SELECTNE, Reg, 4, 1)
+INSN(SELECTGTS, Reg, 4, 1)
+INSN(SELECTGES, Reg, 4, 1)
+INSN(SELECTLTS, Reg, 4, 1)
+INSN(SELECTLES, Reg, 4, 1)
+INSN(SELECTGTU, Reg, 4, 1)
+INSN(SELECTGEU, Reg, 4, 1)
+INSN(SELECTLTU, Reg, 4, 1)
+INSN(SELECTLEU, Reg, 4, 1)
+
+/* Memory access instructions: */
+INSN(LDEXECENV, Reg, 1, 1)
+INSN(LDJITINFO, Reg, 1, 1)
+INSN(LDI8, Reg, 3, 1)
+INSN(LDU8, Reg, 3, 1)
+INSN(LDI16, Reg, 3, 1)
+INSN(LDU16, Reg, 3, 1)
+INSN(LDI32, Reg, 3, 1)
+INSN(LDU32, Reg, 3, 1)
+INSN(LDI64, Reg, 3, 1)
+INSN(LDU64, Reg, 3, 1)
+INSN(LDF32, Reg, 3, 1)
+INSN(LDF64, Reg, 3, 1)
+INSN(LDPTR, Reg, 3, 1)
+INSN(LDV64, Reg, 3, 1)
+INSN(LDV128, Reg, 3, 1)
+INSN(LDV256, Reg, 3, 1)
+INSN(STI8, Reg, 3, 0)
+INSN(STI16, Reg, 3, 0)
+INSN(STI32, Reg, 3, 0)
+INSN(STI64, Reg, 3, 0)
+INSN(STF32, Reg, 3, 0)
+INSN(STF64, Reg, 3, 0)
+INSN(STPTR, Reg, 3, 0)
+INSN(STV64, Reg, 3, 1)
+INSN(STV128, Reg, 3, 1)
+INSN(STV256, Reg, 3, 1)
+
+/* Control instructions */
+INSN(JMP, Reg, 1, 0)
+INSN(BEQ, Reg, 3, 0)
+INSN(BNE, Reg, 3, 0)
+INSN(BGTS, Reg, 3, 0)
+INSN(BGES, Reg, 3, 0)
+INSN(BLTS, Reg, 3, 0)
+INSN(BLES, Reg, 3, 0)
+INSN(BGTU, Reg, 3, 0)
+INSN(BGEU, Reg, 3, 0)
+INSN(BLTU, Reg, 3, 0)
+INSN(BLEU, Reg, 3, 0)
+INSN(LOOKUPSWITCH, LookupSwitch, 1, 0)
+
+/* Call and return instructions */
+INSN(CALLNATIVE, VReg, 2, 1)
+INSN(CALLBC, Reg, 4, 2)
+INSN(RETURNBC, Reg, 3, 0)
+INSN(RETURN, Reg, 1, 0)
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+/* Atomic Memory Accesses */
+/* op1(replacement val) op2(expected val) op3(mem data) op4(offset)
+ * and in x86, the result is stored in register al/ax/eax/rax */
+INSN(AT_CMPXCHGU8, Reg, 4, 0)
+INSN(AT_CMPXCHGU16, Reg, 4, 0)
+INSN(AT_CMPXCHGI32, Reg, 4, 0)
+INSN(AT_CMPXCHGU32, Reg, 4, 0)
+INSN(AT_CMPXCHGI64, Reg, 4, 0)
+/* rmw operations:
+ * op1(read value) op2(operand value) op3(mem data) op4(offset) */
+INSN(AT_ADDU8, Reg, 4, 1)
+INSN(AT_ADDU16, Reg, 4, 1)
+INSN(AT_ADDI32, Reg, 4, 1)
+INSN(AT_ADDU32, Reg, 4, 1)
+INSN(AT_ADDI64, Reg, 4, 1)
+INSN(AT_SUBU8, Reg, 4, 1)
+INSN(AT_SUBU16, Reg, 4, 1)
+INSN(AT_SUBI32, Reg, 4, 1)
+INSN(AT_SUBU32, Reg, 4, 1)
+INSN(AT_SUBI64, Reg, 4, 1)
+INSN(AT_ANDU8, Reg, 4, 1)
+INSN(AT_ANDU16, Reg, 4, 1)
+INSN(AT_ANDI32, Reg, 4, 1)
+INSN(AT_ANDU32, Reg, 4, 1)
+INSN(AT_ANDI64, Reg, 4, 1)
+INSN(AT_ORU8, Reg, 4, 1)
+INSN(AT_ORU16, Reg, 4, 1)
+INSN(AT_ORI32, Reg, 4, 1)
+INSN(AT_ORU32, Reg, 4, 1)
+INSN(AT_ORI64, Reg, 4, 1)
+INSN(AT_XORU8, Reg, 4, 1)
+INSN(AT_XORU16, Reg, 4, 1)
+INSN(AT_XORI32, Reg, 4, 1)
+INSN(AT_XORU32, Reg, 4, 1)
+INSN(AT_XORI64, Reg, 4, 1)
+INSN(AT_XCHGU8, Reg, 4, 1)
+INSN(AT_XCHGU16, Reg, 4, 1)
+INSN(AT_XCHGI32, Reg, 4, 1)
+INSN(AT_XCHGU32, Reg, 4, 1)
+INSN(AT_XCHGI64, Reg, 4, 1)
+INSN(FENCE, Reg, 0, 0)
+#endif
+
+#undef INSN
+
+/**
+ * @def ANN_LABEL (TYPE, NAME)
+ *
+ * Definition of label annotations.
+ *
+ * @param TYPE type of the annotation
+ * @param NAME name of the annotation
+ *
+ * Each defined annotation with name NAME has the following APIs:
+ *
+ * @c jit_annl_NAME (cc, label): accesses the annotation NAME of
+ * label @p label
+ * @c jit_annl_enable_NAME (cc): enables the annotation NAME
+ * @c jit_annl_disable_NAME (cc): disables the annotation NAME
+ * @c jit_annl_is_enabled_NAME (cc): check whether the annotation NAME
+ * is enabled
+ */
+
+#ifndef ANN_LABEL
+#define ANN_LABEL(TYPE, NAME)
+#endif
+
+/* Basic Block of a label. */
+ANN_LABEL(JitBasicBlock *, basic_block)
+/* Predecessor number of the block that is only used in
+ jit_cc_update_cfg for updating the CFG. */
+ANN_LABEL(uint16, pred_num)
+/* Execution frequency of a block. We can split critical edges with
+ empty blocks so we don't need to store frequencies of edges. */
+ANN_LABEL(uint16, freq)
+/* Begin bytecode instruction pointer of the block. */
+ANN_LABEL(uint8 *, begin_bcip)
+/* End bytecode instruction pointer of the block. */
+ANN_LABEL(uint8 *, end_bcip)
+/* Stack pointer offset at the end of the block. */
+ANN_LABEL(uint16, end_sp)
+/* The label of the next physically adjacent block. */
+ANN_LABEL(JitReg, next_label)
+/* Compiled code address of the block. */
+ANN_LABEL(void *, jitted_addr)
+
+#undef ANN_LABEL
+
+/**
+ * @def ANN_INSN (TYPE, NAME)
+ *
+ * Definition of instruction annotations.
+ *
+ * @param TYPE type of the annotation
+ * @param NAME name of the annotation
+ *
+ * Each defined annotation with name NAME has the following APIs:
+ *
+ * @c jit_anni_NAME (cc, insn): accesses the annotation NAME of
+ * instruction @p insn
+ * @c jit_anni_enable_NAME (cc): enables the annotation NAME
+ * @c jit_anni_disable_NAME (cc): disables the annotation NAME
+ * @c jit_anni_is_enabled_NAME (cc): check whether the annotation NAME
+ * is enabled
+ */
+
+#ifndef ANN_INSN
+#define ANN_INSN(TYPE, NAME)
+#endif
+
+/* A private annotation for linking instructions with the same hash
+ value, which is only used by the compilation context's hash table
+ of instructions. */
+ANN_INSN(JitInsn *, _hash_link)
+
+#undef ANN_INSN
+
+/**
+ * @def ANN_REG (TYPE, NAME)
+ *
+ * Definition of register annotations.
+ *
+ * @param TYPE type of the annotation
+ * @param NAME name of the annotation
+ *
+ * Each defined annotation with name NAME has the following APIs:
+ *
+ * @c jit_annr_NAME (cc, reg): accesses the annotation NAME of
+ * register @p reg
+ * @c jit_annr_enable_NAME (cc): enables the annotation NAME
+ * @c jit_annr_disable_NAME (cc): disables the annotation NAME
+ * @c jit_annr_is_enabled_NAME (cc): check whether the annotation NAME
+ * is enabled
+ */
+
+#ifndef ANN_REG
+#define ANN_REG(TYPE, NAME)
+#endif
+
+/* Defining instruction of registers satisfying SSA property. */
+ANN_REG(JitInsn *, def_insn)
+
+#undef ANN_REG
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.h
new file mode 100644
index 000000000..e13a41d1d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_ir.h
@@ -0,0 +1,1880 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_IR_H_
+#define _JIT_IR_H_
+
+#include "bh_platform.h"
+#include "../interpreter/wasm.h"
+#include "jit_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Register (operand) representation of JIT IR.
+ *
+ * Encoding: [4-bit: kind, 28-bit register no.]
+ *
+ * Registers in JIT IR are classified into different kinds according
+ * to types of values they can hold. The classification is based on
+ * most processors' hardware register classifications, which include
+ * various sets of integer, floating point and vector registers with
+ * different sizes. These registers can be mapped onto corresponding
+ * kinds of hardware registers by register allocator. Instructions
+ * can only operate on allowed kinds of registers. For example, an
+ * integer instruction cannot operate on floating point or vector
+ * registers. Some encodings of these kinds of registers also
+ * represent immediate constant values and indexes to constant tables
+ * (see below). In that case, those registers are read-only. Writing
+ * to them is illegal. Reading from an immediate constant value
+ * register always returns the constant value encoded in the register
+ * no. Reading from a constant table index register always returns
+ * the constant value stored at the encoded index of the constant
+ * table of the register's kind. Immediate constant values and values
+ * indexed by constant table indexes can only be loaded into the
+ * corresponding kinds of registers if they must be loaded into
+ * registers. Besides these common kinds of registers, labels of
+ * basic blocks are also treated as registers of a special kind, which
+ * hold code addresses of basic block labels and are read-only. Each
+ * basic block is assigned one unique label register. With this
+ * unification, we can use the same set of load instructions to load
+ * values either from addresses stored in normal registers or from
+ * addresses of labels. Besides these register kinds, the void kind
+ * is a special kind of registers to denote some error occurs when a
+ * normal register is expected. Or it can be used as result operand
+ * of call and invoke instructions to denote no return values. The
+ * variable registers are classified into two sets: the hard registers
+ * whose register numbers are less than the hard register numbers of
+ * their kinds and the virtual registers whose register numbers are
+ * greater than or equal to the hard register numbers. Before
+ * register allocation is done, hard registers may appear in the IR
+ * due to special usages of passes frontend (e.g. fp_reg and exec_env_reg)
+ * or lower_cg. In the mean time (including during register
+ * allocation), those hard registers are treated same as virtual
+ * registers except that they may not be SSA and they can only be
+ * allocated to the hard registers of themselves.
+ *
+ * Classification of registers:
+ * + void register (kind == JIT_REG_KIND_VOID, no. must be 0)
+ * + label registers (kind == JIT_REG_KIND_L32)
+ * + value registers (kind == JIT_REG_KIND_I32/I64/F32/F64/V64/V128/V256)
+ * | + constants (_JIT_REG_CONST_VAL_FLAG | _JIT_REG_CONST_IDX_FLAG)
+ * | | + constant values (_JIT_REG_CONST_VAL_FLAG)
+ * | | + constant indexes (_JIT_REG_CONST_IDX_FLAG)
+ * | + variables (!(_JIT_REG_CONST_VAL_FLAG | _JIT_REG_CONST_IDX_FLAG))
+ * | | + hard registers (no. < hard register number)
+ * | | + virtual registers (no. >= hard register number)
+ */
+typedef uint32 JitReg;
+
+/*
+ * Mask and shift bits of register kind.
+ */
+#define _JIT_REG_KIND_MASK 0xf0000000
+#define _JIT_REG_KIND_SHIFT 28
+
+/*
+ * Mask of register no. which must be the least significant bits.
+ */
+#define _JIT_REG_NO_MASK (~_JIT_REG_KIND_MASK)
+
+/*
+ * Constant value flag (the most significant bit) of register
+ * no. field of integer, floating point and vector registers. If this
+ * flag is set in the register no., the rest bits of register
+ * no. represent a signed (27-bit) integer constant value of the
+ * corresponding type of the register and the register is read-only.
+ */
+#define _JIT_REG_CONST_VAL_FLAG ((_JIT_REG_NO_MASK >> 1) + 1)
+
+/*
+ * Constant index flag of non-constant-value (constant value flag is
+ * not set in register no. field) integer, floating point and vector
+ * regisers. If this flag is set, the rest bits of the register
+ * no. represent an index to the constant value table of the
+ * corresponding type of the register and the register is read-only.
+ */
+#define _JIT_REG_CONST_IDX_FLAG (_JIT_REG_CONST_VAL_FLAG >> 1)
+
+/**
+ * Register kinds. Don't change the order of the defined values. The
+ * L32 kind must be after all normal kinds (see _const_val and _reg_ann
+ * of JitCompContext).
+ */
+typedef enum JitRegKind {
+ JIT_REG_KIND_VOID = 0x00, /* void type */
+ JIT_REG_KIND_I32 = 0x01, /* 32-bit signed or unsigned integer */
+ JIT_REG_KIND_I64 = 0x02, /* 64-bit signed or unsigned integer */
+ JIT_REG_KIND_F32 = 0x03, /* 32-bit floating point */
+ JIT_REG_KIND_F64 = 0x04, /* 64-bit floating point */
+ JIT_REG_KIND_V64 = 0x05, /* 64-bit vector */
+ JIT_REG_KIND_V128 = 0x06, /* 128-bit vector */
+ JIT_REG_KIND_V256 = 0x07, /* 256-bit vector */
+ JIT_REG_KIND_L32 = 0x08, /* 32-bit label address */
+ JIT_REG_KIND_NUM /* number of register kinds */
+} JitRegKind;
+
+#if UINTPTR_MAX == UINT64_MAX
+#define JIT_REG_KIND_PTR JIT_REG_KIND_I64
+#else
+#define JIT_REG_KIND_PTR JIT_REG_KIND_I32
+#endif
+
+/**
+ * Construct a new JIT IR register from the kind and no.
+ *
+ * @param reg_kind register kind
+ * @param reg_no register no.
+ *
+ * @return the new register with the given kind and no.
+ */
+static inline JitReg
+jit_reg_new(unsigned reg_kind, unsigned reg_no)
+{
+ return (JitReg)((reg_kind << _JIT_REG_KIND_SHIFT) | reg_no);
+}
+
+/**
+ * Get the register kind of the given register.
+ *
+ * @param r a JIT IR register
+ *
+ * @return the register kind of register r
+ */
+static inline int
+jit_reg_kind(JitReg r)
+{
+ return (r & _JIT_REG_KIND_MASK) >> _JIT_REG_KIND_SHIFT;
+}
+
+/**
+ * Get the register no. of the given JIT IR register.
+ *
+ * @param r a JIT IR register
+ *
+ * @return the register no. of register r
+ */
+static inline int
+jit_reg_no(JitReg r)
+{
+ return r & _JIT_REG_NO_MASK;
+}
+
+/**
+ * Check whether the given register is a normal value register.
+ *
+ * @param r a JIT IR register
+ *
+ * @return true iff the register is a normal value register
+ */
+static inline bool
+jit_reg_is_value(JitReg r)
+{
+ unsigned kind = jit_reg_kind(r);
+ return kind > JIT_REG_KIND_VOID && kind < JIT_REG_KIND_L32;
+}
+
+/**
+ * Check whether the given register is a constant value.
+ *
+ * @param r a JIT IR register
+ *
+ * @return true iff register r is a constant value
+ */
+static inline bool
+jit_reg_is_const_val(JitReg r)
+{
+ return jit_reg_is_value(r) && (r & _JIT_REG_CONST_VAL_FLAG);
+}
+
+/**
+ * Check whether the given register is a constant table index.
+ *
+ * @param r a JIT IR register
+ *
+ * @return true iff register r is a constant table index
+ */
+static inline bool
+jit_reg_is_const_idx(JitReg r)
+{
+ return (jit_reg_is_value(r) && !jit_reg_is_const_val(r)
+ && (r & _JIT_REG_CONST_IDX_FLAG));
+}
+
+/**
+ * Check whether the given register is a constant.
+ *
+ * @param r a JIT IR register
+ *
+ * @return true iff register r is a constant
+ */
+static inline bool
+jit_reg_is_const(JitReg r)
+{
+ return (jit_reg_is_value(r)
+ && (r & (_JIT_REG_CONST_VAL_FLAG | _JIT_REG_CONST_IDX_FLAG)));
+}
+
+/**
+ * Check whether the given register is a normal variable register.
+ *
+ * @param r a JIT IR register
+ *
+ * @return true iff the register is a normal variable register
+ */
+static inline bool
+jit_reg_is_variable(JitReg r)
+{
+ return (jit_reg_is_value(r)
+ && !(r & (_JIT_REG_CONST_VAL_FLAG | _JIT_REG_CONST_IDX_FLAG)));
+}
+
+/**
+ * Test whether the register is the given kind.
+ *
+ * @param KIND register kind name
+ * @param R register
+ *
+ * @return true if the register is the given kind
+ */
+#define jit_reg_is_kind(KIND, R) (jit_reg_kind(R) == JIT_REG_KIND_##KIND)
+
+/**
+ * Construct a zero IR register with given the kind.
+ *
+ * @param kind the kind of the value
+ *
+ * @return a constant register of zero
+ */
+static inline JitReg
+jit_reg_new_zero(unsigned kind)
+{
+ bh_assert(kind != JIT_REG_KIND_VOID && kind < JIT_REG_KIND_L32);
+ return jit_reg_new(kind, _JIT_REG_CONST_VAL_FLAG);
+}
+
+/**
+ * Test whether the register is a zero constant value.
+ *
+ * @param reg an IR register
+ *
+ * @return true iff the register is a constant zero
+ */
+static inline JitReg
+jit_reg_is_zero(JitReg reg)
+{
+ return (jit_reg_is_value(reg)
+ && jit_reg_no(reg) == _JIT_REG_CONST_VAL_FLAG);
+}
+
+/**
+ * Operand of instructions with fixed-number register operand(s).
+ */
+typedef JitReg JitOpndReg;
+
+/**
+ * Operand of instructions with variable-number register operand(s).
+ */
+typedef struct JitOpndVReg {
+ uint32 _reg_num;
+ JitReg _reg[1];
+} JitOpndVReg;
+
+/**
+ * Operand of lookupswitch instruction.
+ */
+typedef struct JitOpndLookupSwitch {
+ /* NOTE: distance between JitReg operands must be the same (see
+ jit_insn_opnd_regs). */
+ JitReg value; /* the value to be compared */
+ uint32 match_pairs_num; /* match pairs number */
+ /* NOTE: offset between adjacent targets must be sizeof
+ (match_pairs[0]) (see implementation of jit_basic_block_succs),
+ so the default_target field must be here. */
+ JitReg default_target; /* default target BB */
+ struct {
+ int32 value; /* match value of the match pair */
+ JitReg target; /* target BB of the match pair */
+ } match_pairs[1]; /* match pairs of the instruction */
+} JitOpndLookupSwitch;
+
+/**
+ * Instruction of JIT IR.
+ */
+typedef struct JitInsn {
+ /* Pointers to the previous and next instructions. */
+ struct JitInsn *prev;
+ struct JitInsn *next;
+
+ /* Opcode of the instruction. */
+ uint16 opcode;
+
+ /* Reserved field that may be used by optimizations locally.
+ * bit_0(Least Significant Bit) is atomic flag for load/store */
+ uint8 flags_u8;
+
+ /* The unique ID of the instruction. */
+ uint16 uid;
+
+ /* Operands for different kinds of instructions. */
+ union {
+ /* For instructions with fixed-number register operand(s). */
+ JitOpndReg _opnd_Reg[1];
+
+ /* For instructions with variable-number register operand(s). */
+ JitOpndVReg _opnd_VReg;
+
+ /* For lookupswitch instruction. */
+ JitOpndLookupSwitch _opnd_LookupSwitch;
+ } _opnd;
+} JitInsn;
+
+/**
+ * Opcodes of IR instructions.
+ */
+typedef enum JitOpcode {
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE) JIT_OP_##NAME,
+#include "jit_ir.def"
+#undef INSN
+ JIT_OP_OPCODE_NUMBER
+} JitOpcode;
+
+/*
+ * Helper functions for creating new instructions. Don't call them
+ * directly. Use jit_insn_new_NAME, such as jit_insn_new_MOV instead.
+ */
+
+JitInsn *
+_jit_insn_new_Reg_0(JitOpcode opc);
+JitInsn *
+_jit_insn_new_Reg_1(JitOpcode opc, JitReg r0);
+JitInsn *
+_jit_insn_new_Reg_2(JitOpcode opc, JitReg r0, JitReg r1);
+JitInsn *
+_jit_insn_new_Reg_3(JitOpcode opc, JitReg r0, JitReg r1, JitReg r2);
+JitInsn *
+_jit_insn_new_Reg_4(JitOpcode opc, JitReg r0, JitReg r1, JitReg r2, JitReg r3);
+JitInsn *
+_jit_insn_new_Reg_5(JitOpcode opc, JitReg r0, JitReg r1, JitReg r2, JitReg r3,
+ JitReg r4);
+JitInsn *
+_jit_insn_new_VReg_1(JitOpcode opc, JitReg r0, int n);
+JitInsn *
+_jit_insn_new_VReg_2(JitOpcode opc, JitReg r0, JitReg r1, int n);
+JitInsn *
+_jit_insn_new_LookupSwitch_1(JitOpcode opc, JitReg value, uint32 num);
+
+/*
+ * Instruction creation functions jit_insn_new_NAME, where NAME is the
+ * name of the instruction defined in jit_ir.def.
+ */
+#define ARG_DECL_Reg_0
+#define ARG_LIST_Reg_0
+#define ARG_DECL_Reg_1 JitReg r0
+#define ARG_LIST_Reg_1 , r0
+#define ARG_DECL_Reg_2 JitReg r0, JitReg r1
+#define ARG_LIST_Reg_2 , r0, r1
+#define ARG_DECL_Reg_3 JitReg r0, JitReg r1, JitReg r2
+#define ARG_LIST_Reg_3 , r0, r1, r2
+#define ARG_DECL_Reg_4 JitReg r0, JitReg r1, JitReg r2, JitReg r3
+#define ARG_LIST_Reg_4 , r0, r1, r2, r3
+#define ARG_DECL_Reg_5 JitReg r0, JitReg r1, JitReg r2, JitReg r3, JitReg r4
+#define ARG_LIST_Reg_5 , r0, r1, r2, r3, r4
+#define ARG_DECL_VReg_1 JitReg r0, int n
+#define ARG_LIST_VReg_1 , r0, n
+#define ARG_DECL_VReg_2 JitReg r0, JitReg r1, int n
+#define ARG_LIST_VReg_2 , r0, r1, n
+#define ARG_DECL_LookupSwitch_1 JitReg value, uint32 num
+#define ARG_LIST_LookupSwitch_1 , value, num
+#define INSN(NAME, OPND_KIND, OPND_NUM, FIRST_USE) \
+ static inline JitInsn *jit_insn_new_##NAME( \
+ ARG_DECL_##OPND_KIND##_##OPND_NUM) \
+ { \
+ return _jit_insn_new_##OPND_KIND##_##OPND_NUM( \
+ JIT_OP_##NAME ARG_LIST_##OPND_KIND##_##OPND_NUM); \
+ }
+#include "jit_ir.def"
+#undef INSN
+#undef ARG_DECL_Reg_0
+#undef ARG_LIST_Reg_0
+#undef ARG_DECL_Reg_1
+#undef ARG_LIST_Reg_1
+#undef ARG_DECL_Reg_2
+#undef ARG_LIST_Reg_2
+#undef ARG_DECL_Reg_3
+#undef ARG_LIST_Reg_3
+#undef ARG_DECL_Reg_4
+#undef ARG_LIST_Reg_4
+#undef ARG_DECL_Reg_5
+#undef ARG_LIST_Reg_5
+#undef ARG_DECL_VReg_1
+#undef ARG_LIST_VReg_1
+#undef ARG_DECL_VReg_2
+#undef ARG_LIST_VReg_2
+#undef ARG_DECL_LookupSwitch_1
+#undef ARG_LIST_LookupSwitch_1
+
+/**
+ * Delete an instruction
+ *
+ * @param insn an instruction to be deleted
+ */
+static inline void
+jit_insn_delete(JitInsn *insn)
+{
+ jit_free(insn);
+}
+
+/*
+ * Runtime type check functions that check whether accessing the n-th
+ * operand is legal. They are only used for in self-verification
+ * mode.
+ *
+ * @param insn any JIT IR instruction
+ * @param n index of the operand to access
+ *
+ * @return true if the access is legal
+ */
+bool
+_jit_insn_check_opnd_access_Reg(const JitInsn *insn, unsigned n);
+bool
+_jit_insn_check_opnd_access_VReg(const JitInsn *insn, unsigned n);
+bool
+_jit_insn_check_opnd_access_LookupSwitch(const JitInsn *insn);
+
+/**
+ * Get the pointer to the n-th register operand of the given
+ * instruction. The instruction format must be Reg.
+ *
+ * @param insn a Reg format instruction
+ * @param n index of the operand to get
+ *
+ * @return pointer to the n-th operand
+ */
+static inline JitReg *
+jit_insn_opnd(JitInsn *insn, int n)
+{
+ bh_assert(_jit_insn_check_opnd_access_Reg(insn, n));
+ return &insn->_opnd._opnd_Reg[n];
+}
+
+/**
+ * Get the pointer to the n-th register operand of the given
+ * instruction. The instruction format must be VReg.
+ *
+ * @param insn a VReg format instruction
+ * @param n index of the operand to get
+ *
+ * @return pointer to the n-th operand
+ */
+static inline JitReg *
+jit_insn_opndv(JitInsn *insn, int n)
+{
+ bh_assert(_jit_insn_check_opnd_access_VReg(insn, n));
+ return &insn->_opnd._opnd_VReg._reg[n];
+}
+
+/**
+ * Get the operand number of the given instruction. The instruction
+ * format must be VReg.
+ *
+ * @param insn a VReg format instruction
+ *
+ * @return operand number of the instruction
+ */
+static inline unsigned
+jit_insn_opndv_num(const JitInsn *insn)
+{
+ bh_assert(_jit_insn_check_opnd_access_VReg(insn, 0));
+ return insn->_opnd._opnd_VReg._reg_num;
+}
+
+/**
+ * Get the pointer to the LookupSwitch operand of the given
+ * instruction. The instruction format must be LookupSwitch.
+ *
+ * @param insn a LookupSwitch format instruction
+ *
+ * @return pointer to the operand
+ */
+static inline JitOpndLookupSwitch *
+jit_insn_opndls(JitInsn *insn)
+{
+ bh_assert(_jit_insn_check_opnd_access_LookupSwitch(insn));
+ return &insn->_opnd._opnd_LookupSwitch;
+}
+
+/**
+ * Insert instruction @p insn2 before instruction @p insn1.
+ *
+ * @param insn1 any instruction
+ * @param insn2 any instruction
+ */
+void
+jit_insn_insert_before(JitInsn *insn1, JitInsn *insn2);
+
+/**
+ * Insert instruction @p insn2 after instruction @p insn1.
+ *
+ * @param insn1 any instruction
+ * @param insn2 any instruction
+ */
+void
+jit_insn_insert_after(JitInsn *insn1, JitInsn *insn2);
+
+/**
+ * Unlink the instruction @p insn from the containing list.
+ *
+ * @param insn an instruction
+ */
+void
+jit_insn_unlink(JitInsn *insn);
+
+/**
+ * Get the hash value of the comparable instruction (pure functions
+ * and exception check instructions).
+ *
+ * @param insn an instruction
+ *
+ * @return hash value of the instruction
+ */
+unsigned
+jit_insn_hash(JitInsn *insn);
+
+/**
+ * Compare whether the two comparable instructions are the same.
+ *
+ * @param insn1 the first instruction
+ * @param insn2 the second instruction
+ *
+ * @return true if the two instructions are the same
+ */
+bool
+jit_insn_equal(JitInsn *insn1, JitInsn *insn2);
+
+/**
+ * Register vector for accessing predecessors and successors of a
+ * basic block.
+ */
+typedef struct JitRegVec {
+ JitReg *_base; /* points to the first register */
+ int32 _stride; /* stride to the next register */
+ uint32 num; /* number of registers */
+} JitRegVec;
+
+/**
+ * Get the address of the i-th register in the register vector.
+ *
+ * @param vec a register vector
+ * @param i index to the register vector
+ *
+ * @return the address of the i-th register in the vector
+ */
+static inline JitReg *
+jit_reg_vec_at(const JitRegVec *vec, unsigned i)
+{
+ bh_assert(i < vec->num);
+ return vec->_base + vec->_stride * i;
+}
+
+/**
+ * Visit each element in a register vector.
+ *
+ * @param V (JitRegVec) the register vector
+ * @param I (unsigned) index variable in the vector
+ * @param R (JitReg *) resiger pointer variable
+ */
+#define JIT_REG_VEC_FOREACH(V, I, R) \
+ for ((I) = 0, (R) = (V)._base; (I) < (V).num; (I)++, (R) += (V)._stride)
+
+/**
+ * Visit each register defined by an instruction.
+ *
+ * @param V (JitRegVec) register vector of the instruction
+ * @param I (unsigned) index variable in the vector
+ * @param R (JitReg *) resiger pointer variable
+ * @param F index of the first used register
+ */
+#define JIT_REG_VEC_FOREACH_DEF(V, I, R, F) \
+ for ((I) = 0, (R) = (V)._base; (I) < (F); (I)++, (R) += (V)._stride)
+
+/**
+ * Visit each register used by an instruction.
+ *
+ * @param V (JitRegVec) register vector of the instruction
+ * @param I (unsigned) index variable in the vector
+ * @param R (JitReg *) resiger pointer variable
+ * @param F index of the first used register
+ */
+#define JIT_REG_VEC_FOREACH_USE(V, I, R, F) \
+ for ((I) = (F), (R) = (V)._base + (F) * (V)._stride; (I) < (V).num; \
+ (I)++, (R) += (V)._stride)
+
+/**
+ * Get a generic register vector that contains all register operands.
+ * The registers defined by the instruction, if any, appear before the
+ * registers used by the instruction.
+ *
+ * @param insn an instruction
+ *
+ * @return a register vector containing register operands
+ */
+JitRegVec
+jit_insn_opnd_regs(JitInsn *insn);
+
+/**
+ * Get the index of the first use register in the register vector
+ * returned by jit_insn_opnd_regs.
+ *
+ * @param insn an instruction
+ *
+ * @return the index of the first use register in the register vector
+ */
+unsigned
+jit_insn_opnd_first_use(JitInsn *insn);
+
+/**
+ * Basic Block of JIT IR. It is a basic block only if the IR is not in
+ * non-BB form. The block is represented by a special phi node, whose
+ * result and arguments are label registers. The result label is the
+ * containing block's label. The arguments are labels of predecessors
+ * of the block. Successor labels are stored in the last instruction,
+ * which must be a control flow instruction. Instructions of a block
+ * are linked in a circular linked list with the block phi node as the
+ * end of the list. The next and prev field of the block phi node
+ * point to the first and last instructions of the block.
+ */
+typedef JitInsn JitBasicBlock;
+
+/**
+ * Create a new basic block instance.
+ *
+ * @param label the label of the new basic block
+ * @param n number of predecessors
+ *
+ * @return the created new basic block instance
+ */
+JitBasicBlock *
+jit_basic_block_new(JitReg label, int n);
+
+/**
+ * Delete a basic block instance and all instructions init.
+ *
+ * @param block the basic block to be deleted
+ */
+void
+jit_basic_block_delete(JitBasicBlock *block);
+
+/**
+ * Get the label of the basic block.
+ *
+ * @param block a basic block instance
+ *
+ * @return the label of the basic block
+ */
+static inline JitReg
+jit_basic_block_label(JitBasicBlock *block)
+{
+ return *(jit_insn_opndv(block, 0));
+}
+
+/**
+ * Get the first instruction of the basic block.
+ *
+ * @param block a basic block instance
+ *
+ * @return the first instruction of the basic block
+ */
+static inline JitInsn *
+jit_basic_block_first_insn(JitBasicBlock *block)
+{
+ return block->next;
+}
+
+/**
+ * Get the last instruction of the basic block.
+ *
+ * @param block a basic block instance
+ *
+ * @return the last instruction of the basic block
+ */
+static inline JitInsn *
+jit_basic_block_last_insn(JitBasicBlock *block)
+{
+ return block->prev;
+}
+
+/**
+ * Get the end of instruction list of the basic block (which is always
+ * the block itself).
+ *
+ * @param block a basic block instance
+ *
+ * @return the end of instruction list of the basic block
+ */
+static inline JitInsn *
+jit_basic_block_end_insn(JitBasicBlock *block)
+{
+ return block;
+}
+
+/**
+ * Visit each instruction in the block from the first to the last. In
+ * the code block, the instruction pointer @p I must be a valid
+ * pointer to an instruction in the block. That means if the
+ * instruction may be deleted, @p I must point to the previous or next
+ * valid instruction before the next iteration.
+ *
+ * @param B (JitBasicBlock *) the block
+ * @param I (JitInsn *) instruction visited
+ */
+#define JIT_FOREACH_INSN(B, I) \
+ for (I = jit_basic_block_first_insn(B); I != jit_basic_block_end_insn(B); \
+ I = I->next)
+
+/**
+ * Visit each instruction in the block from the last to the first. In
+ * the code block, the instruction pointer @p I must be a valid
+ * pointer to an instruction in the block. That means if the
+ * instruction may be deleted, @p I must point to the previous or next
+ * valid instruction before the next iteration.
+ *
+ * @param B (JitBasicBlock *) the block
+ * @param I (JitInsn *) instruction visited
+ */
+#define JIT_FOREACH_INSN_REVERSE(B, I) \
+ for (I = jit_basic_block_last_insn(B); I != jit_basic_block_end_insn(B); \
+ I = I->prev)
+
+/**
+ * Prepend an instruction in the front of the block. The position is
+ * just after the block phi node (the block instance itself).
+ *
+ * @param block a block
+ * @param insn an instruction to be prepended
+ */
+static inline void
+jit_basic_block_prepend_insn(JitBasicBlock *block, JitInsn *insn)
+{
+ jit_insn_insert_after(block, insn);
+}
+
+/**
+ * Append an instruction to the end of the basic block.
+ *
+ * @param block a basic block
+ * @param insn an instruction to be appended
+ */
+static inline void
+jit_basic_block_append_insn(JitBasicBlock *block, JitInsn *insn)
+{
+ jit_insn_insert_before(block, insn);
+}
+
+/**
+ * Get the register vector of predecessors of a basic block.
+ *
+ * @param block a JIT IR block
+ *
+ * @return register vector of the predecessors
+ */
+JitRegVec
+jit_basic_block_preds(JitBasicBlock *block);
+
+/**
+ * Get the register vector of successors of a basic block.
+ *
+ * @param block a JIT IR basic block
+ *
+ * @return register vector of the successors
+ */
+JitRegVec
+jit_basic_block_succs(JitBasicBlock *block);
+
+/**
+ * Hard register information of one kind.
+ */
+typedef struct JitHardRegInfo {
+ struct {
+ /* Hard register number of this kind. */
+ uint32 num;
+
+ /* Whether each register is fixed. */
+ const uint8 *fixed;
+
+ /* Whether each register is caller-saved in the native ABI. */
+ const uint8 *caller_saved_native;
+
+ /* Whether each register is caller-saved in the JITed ABI. */
+ const uint8 *caller_saved_jitted;
+ } info[JIT_REG_KIND_L32];
+
+ /* The indexes of hard registers of frame pointer, exec_env and cmp. */
+ uint32 fp_hreg_index;
+ uint32 exec_env_hreg_index;
+ uint32 cmp_hreg_index;
+} JitHardRegInfo;
+
+struct JitBlock;
+struct JitCompContext;
+struct JitValueSlot;
+
+/**
+ * Value in the WASM operation stack, each stack element
+ * is a Jit register
+ */
+typedef struct JitValue {
+ struct JitValue *next;
+ struct JitValue *prev;
+ struct JitValueSlot *value;
+ /* VALUE_TYPE_I32/I64/F32/F64/VOID */
+ uint8 type;
+} JitValue;
+
+/**
+ * Value stack, represents stack elements in a WASM block
+ */
+typedef struct JitValueStack {
+ JitValue *value_list_head;
+ JitValue *value_list_end;
+} JitValueStack;
+
+/* Record information of a value slot of local variable or stack
+ during translation. */
+typedef struct JitValueSlot {
+ /* The virtual register that holds the value of the slot if the
+ value of the slot is in register. */
+ JitReg reg;
+
+ /* The dirty bit of the value slot. It's set if the value in
+ register is newer than the value in memory. */
+ uint32 dirty : 1;
+
+ /* Whether the new value in register is a reference, which is valid
+ only when the dirty bit is set. */
+ uint32 ref : 1;
+
+ /* Committed reference flag. 0: unknown, 1: not-reference, 2:
+ reference. */
+ uint32 committed_ref : 2;
+} JitValueSlot;
+
+typedef struct JitMemRegs {
+ /* The following registers should be re-loaded after
+ memory.grow, callbc and callnative */
+ JitReg memory_data;
+ JitReg memory_data_end;
+ JitReg mem_bound_check_1byte;
+ JitReg mem_bound_check_2bytes;
+ JitReg mem_bound_check_4bytes;
+ JitReg mem_bound_check_8bytes;
+ JitReg mem_bound_check_16bytes;
+} JitMemRegs;
+
+typedef struct JitTableRegs {
+ JitReg table_elems;
+ /* Should be re-loaded after table.grow,
+ callbc and callnative */
+ JitReg table_cur_size;
+} JitTableRegs;
+
+/* Frame information for translation */
+typedef struct JitFrame {
+ /* The current wasm module */
+ WASMModule *cur_wasm_module;
+ /* The current wasm function */
+ WASMFunction *cur_wasm_func;
+ /* The current wasm function index */
+ uint32 cur_wasm_func_idx;
+ /* The current compilation context */
+ struct JitCompContext *cc;
+
+ /* Max local slot number. */
+ uint32 max_locals;
+
+ /* Max operand stack slot number. */
+ uint32 max_stacks;
+
+ /* Instruction pointer */
+ uint8 *ip;
+
+ /* Stack top pointer */
+ JitValueSlot *sp;
+
+ /* Committed instruction pointer */
+ uint8 *committed_ip;
+
+ /* Committed stack top pointer */
+ JitValueSlot *committed_sp;
+
+ /* WASM module instance */
+ JitReg module_inst_reg;
+ /* WASM module */
+ JitReg module_reg;
+ /* module_inst->import_func_ptrs */
+ JitReg import_func_ptrs_reg;
+ /* module_inst->fast_jit_func_ptrs */
+ JitReg fast_jit_func_ptrs_reg;
+ /* module_inst->func_type_indexes */
+ JitReg func_type_indexes_reg;
+ /* Boundary of auxiliary stack */
+ JitReg aux_stack_bound_reg;
+ /* Bottom of auxiliary stack */
+ JitReg aux_stack_bottom_reg;
+ /* Data of memory instances */
+ JitMemRegs *memory_regs;
+ /* Data of table instances */
+ JitTableRegs *table_regs;
+
+ /* Local variables */
+ JitValueSlot lp[1];
+} JitFrame;
+
+typedef struct JitIncomingInsn {
+ struct JitIncomingInsn *next;
+ JitInsn *insn;
+ uint32 opnd_idx;
+} JitIncomingInsn, *JitIncomingInsnList;
+
+typedef struct JitBlock {
+ struct JitBlock *next;
+ struct JitBlock *prev;
+
+ /* The current Jit Block */
+ struct JitCompContext *cc;
+
+ /* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */
+ uint32 label_type;
+
+ /* code of else opcode of this block, if it is a IF block */
+ uint8 *wasm_code_else;
+ /* code of end opcode of this block */
+ uint8 *wasm_code_end;
+
+ /* JIT label points to code begin */
+ JitBasicBlock *basic_block_entry;
+ /* JIT label points to code else */
+ JitBasicBlock *basic_block_else;
+ /* JIT label points to code end */
+ JitBasicBlock *basic_block_end;
+
+ /* Incoming INSN for basic_block_else */
+ JitInsn *incoming_insn_for_else_bb;
+ /* Incoming INSNs for basic_block_end */
+ JitIncomingInsnList incoming_insns_for_end_bb;
+
+ /* WASM operation stack */
+ JitValueStack value_stack;
+
+ /* Param count/types/PHIs of this block */
+ uint32 param_count;
+ uint8 *param_types;
+
+ /* Result count/types/PHIs of this block */
+ uint32 result_count;
+ uint8 *result_types;
+
+ /* The begin frame stack pointer of this block */
+ JitValueSlot *frame_sp_begin;
+} JitBlock;
+
+/**
+ * Block stack, represents WASM block stack elements
+ */
+typedef struct JitBlockStack {
+ JitBlock *block_list_head;
+ JitBlock *block_list_end;
+} JitBlockStack;
+
+/**
+ * The JIT compilation context for one compilation process of a
+ * compilation unit.
+ */
+typedef struct JitCompContext {
+ /* Hard register information of each kind. */
+ const JitHardRegInfo *hreg_info;
+
+ /* No. of the pass to be applied. */
+ uint8 cur_pass_no;
+
+ /* The current wasm module */
+ WASMModule *cur_wasm_module;
+ /* The current wasm function */
+ WASMFunction *cur_wasm_func;
+ /* The current wasm function index */
+ uint32 cur_wasm_func_idx;
+ /* The block stack */
+ JitBlockStack block_stack;
+
+ bool mem_space_unchanged;
+
+ /* Entry and exit labels of the compilation unit, whose numbers must
+ be 0 and 1 respectively (see JIT_FOREACH_BLOCK). */
+ JitReg entry_label;
+ JitReg exit_label;
+ JitBasicBlock **exce_basic_blocks;
+ JitIncomingInsnList *incoming_insns_for_exec_bbs;
+
+ /* The current basic block to generate instructions */
+ JitBasicBlock *cur_basic_block;
+
+ /* Registers of frame pointer, exec_env and CMP result. */
+ JitReg fp_reg;
+ JitReg exec_env_reg;
+ JitReg cmp_reg;
+
+ /* WASM module instance */
+ JitReg module_inst_reg;
+ /* WASM module */
+ JitReg module_reg;
+ /* module_inst->import_func_ptrs */
+ JitReg import_func_ptrs_reg;
+ /* module_inst->fast_jit_func_ptrs */
+ JitReg fast_jit_func_ptrs_reg;
+ /* module_inst->func_type_indexes */
+ JitReg func_type_indexes_reg;
+ /* Boundary of auxiliary stack */
+ JitReg aux_stack_bound_reg;
+ /* Bottom of auxiliary stack */
+ JitReg aux_stack_bottom_reg;
+ /* Data of memory instances */
+ JitMemRegs *memory_regs;
+ /* Data of table instances */
+ JitTableRegs *table_regs;
+
+ /* Current frame information for translation */
+ JitFrame *jit_frame;
+
+ /* The total frame size of current function */
+ uint32 total_frame_size;
+
+ /* The spill cache offset to the interp frame */
+ uint32 spill_cache_offset;
+ /* The spill cache size */
+ uint32 spill_cache_size;
+
+ /* The offset of jitted_return_address in the frame, which is set by
+ the pass frontend and used by the pass codegen. */
+ uint32 jitted_return_address_offset;
+
+ /* Begin and end addresses of the jitted code produced by the pass
+ codegen and consumed by the region registration after codegen and
+ the pass dump. */
+ void *jitted_addr_begin;
+ void *jitted_addr_end;
+
+ char last_error[128];
+
+ /* Below fields are all private. Don't access them directly. */
+
+ /* Reference count of the compilation context. */
+ uint16 _reference_count;
+
+ /* Constant values. */
+ struct {
+ /* Number of constant values of each kind. */
+ uint32 _num[JIT_REG_KIND_L32];
+
+ /* Capacity of register annotations of each kind. */
+ uint32 _capacity[JIT_REG_KIND_L32];
+
+ /* Constant vallues of each kind. */
+ uint8 *_value[JIT_REG_KIND_L32];
+
+ /* Next element on the list of values with the same hash code. */
+ JitReg *_next[JIT_REG_KIND_L32];
+
+ /* Size of the hash table. */
+ uint32 _hash_table_size;
+
+ /* Map values to JIT register. */
+ JitReg *_hash_table;
+ } _const_val;
+
+ /* Annotations of labels, registers and instructions. */
+ struct {
+ /* Number of all ever created labels. */
+ uint32 _label_num;
+
+ /* Capacity of label annotations. */
+ uint32 _label_capacity;
+
+ /* Number of all ever created instructions. */
+ uint32 _insn_num;
+
+ /* Capacity of instruction annotations. */
+ uint32 _insn_capacity;
+
+ /* Number of ever created registers of each kind. */
+ uint32 _reg_num[JIT_REG_KIND_L32];
+
+ /* Capacity of register annotations of each kind. */
+ uint32 _reg_capacity[JIT_REG_KIND_L32];
+
+ /* Storage of annotations. */
+#define ANN_LABEL(TYPE, NAME) TYPE *_label_##NAME;
+#define ANN_INSN(TYPE, NAME) TYPE *_insn_##NAME;
+#define ANN_REG(TYPE, NAME) TYPE *_reg_##NAME[JIT_REG_KIND_L32];
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+ /* Flags of annotations. */
+#define ANN_LABEL(TYPE, NAME) uint32 _label_##NAME##_enabled : 1;
+#define ANN_INSN(TYPE, NAME) uint32 _insn_##NAME##_enabled : 1;
+#define ANN_REG(TYPE, NAME) uint32 _reg_##NAME##_enabled : 1;
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+ } _ann;
+
+ /* Instruction hash table. */
+ struct {
+ /* Size of the hash table. */
+ uint32 _size;
+
+ /* The hash table. */
+ JitInsn **_table;
+ } _insn_hash_table;
+
+ /* indicate if the last comparision is about floating-point numbers or not
+ */
+ bool last_cmp_on_fp;
+} JitCompContext;
+
+/*
+ * Annotation accessing functions jit_annl_NAME, jit_anni_NAME and
+ * jit_annr_NAME.
+ */
+#define ANN_LABEL(TYPE, NAME) \
+ static inline TYPE *jit_annl_##NAME(JitCompContext *cc, JitReg label) \
+ { \
+ unsigned idx = jit_reg_no(label); \
+ bh_assert(jit_reg_kind(label) == JIT_REG_KIND_L32); \
+ bh_assert(idx < cc->_ann._label_num); \
+ bh_assert(cc->_ann._label_##NAME##_enabled); \
+ return &cc->_ann._label_##NAME[idx]; \
+ }
+#define ANN_INSN(TYPE, NAME) \
+ static inline TYPE *jit_anni_##NAME(JitCompContext *cc, JitInsn *insn) \
+ { \
+ unsigned uid = insn->uid; \
+ bh_assert(uid < cc->_ann._insn_num); \
+ bh_assert(cc->_ann._insn_##NAME##_enabled); \
+ return &cc->_ann._insn_##NAME[uid]; \
+ }
+#define ANN_REG(TYPE, NAME) \
+ static inline TYPE *jit_annr_##NAME(JitCompContext *cc, JitReg reg) \
+ { \
+ unsigned kind = jit_reg_kind(reg); \
+ unsigned no = jit_reg_no(reg); \
+ bh_assert(kind < JIT_REG_KIND_L32); \
+ bh_assert(no < cc->_ann._reg_num[kind]); \
+ bh_assert(cc->_ann._reg_##NAME##_enabled); \
+ return &cc->_ann._reg_##NAME[kind][no]; \
+ }
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+/*
+ * Annotation enabling functions jit_annl_enable_NAME,
+ * jit_anni_enable_NAME and jit_annr_enable_NAME, which allocate
+ * sufficient memory for the annotations.
+ */
+#define ANN_LABEL(TYPE, NAME) bool jit_annl_enable_##NAME(JitCompContext *cc);
+#define ANN_INSN(TYPE, NAME) bool jit_anni_enable_##NAME(JitCompContext *cc);
+#define ANN_REG(TYPE, NAME) bool jit_annr_enable_##NAME(JitCompContext *cc);
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+/*
+ * Annotation disabling functions jit_annl_disable_NAME,
+ * jit_anni_disable_NAME and jit_annr_disable_NAME, which release
+ * memory of the annotations. Before calling these functions,
+ * resources owned by the annotations must be explictely released.
+ */
+#define ANN_LABEL(TYPE, NAME) void jit_annl_disable_##NAME(JitCompContext *cc);
+#define ANN_INSN(TYPE, NAME) void jit_anni_disable_##NAME(JitCompContext *cc);
+#define ANN_REG(TYPE, NAME) void jit_annr_disable_##NAME(JitCompContext *cc);
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+/*
+ * Functions jit_annl_is_enabled_NAME, jit_anni_is_enabled_NAME and
+ * jit_annr_is_enabled_NAME for checking whether an annotation is
+ * enabled.
+ */
+#define ANN_LABEL(TYPE, NAME) \
+ static inline bool jit_annl_is_enabled_##NAME(JitCompContext *cc) \
+ { \
+ return !!cc->_ann._label_##NAME##_enabled; \
+ }
+#define ANN_INSN(TYPE, NAME) \
+ static inline bool jit_anni_is_enabled_##NAME(JitCompContext *cc) \
+ { \
+ return !!cc->_ann._insn_##NAME##_enabled; \
+ }
+#define ANN_REG(TYPE, NAME) \
+ static inline bool jit_annr_is_enabled_##NAME(JitCompContext *cc) \
+ { \
+ return !!cc->_ann._reg_##NAME##_enabled; \
+ }
+#include "jit_ir.def"
+#undef ANN_LABEL
+#undef ANN_INSN
+#undef ANN_REG
+
+/**
+ * Initialize a compilation context.
+ *
+ * @param cc the compilation context
+ * @param htab_size the initial hash table size of constant pool
+ *
+ * @return cc if succeeds, NULL otherwise
+ */
+JitCompContext *
+jit_cc_init(JitCompContext *cc, unsigned htab_size);
+
+/**
+ * Release all resources of a compilation context, which doesn't
+ * include the compilation context itself.
+ *
+ * @param cc the compilation context
+ */
+void
+jit_cc_destroy(JitCompContext *cc);
+
+/**
+ * Increase the reference count of the compilation context.
+ *
+ * @param cc the compilation context
+ */
+static inline void
+jit_cc_inc_ref(JitCompContext *cc)
+{
+ cc->_reference_count++;
+}
+
+/**
+ * Decrease the reference_count and destroy and free the compilation
+ * context if the reference_count is decreased to zero.
+ *
+ * @param cc the compilation context
+ */
+void
+jit_cc_delete(JitCompContext *cc);
+
+char *
+jit_get_last_error(JitCompContext *cc);
+
+void
+jit_set_last_error(JitCompContext *cc, const char *error);
+
+void
+jit_set_last_error_v(JitCompContext *cc, const char *format, ...);
+
+/**
+ * Create a I32 constant value with relocatable into the compilation
+ * context. A constant value that has relocation info cannot be
+ * constant-folded as normal constants because its value depends on
+ * runtime context and may be different in different executions.
+ *
+ * @param cc compilation context
+ * @param val a I32 value
+ * @param rel relocation information
+ *
+ * @return a constant register containing the value
+ */
+JitReg
+jit_cc_new_const_I32_rel(JitCompContext *cc, int32 val, uint32 rel);
+
+/**
+ * Create a I32 constant value without relocation info (0) into the
+ * compilation context.
+ *
+ * @param cc compilation context
+ * @param val a I32 value
+ *
+ * @return a constant register containing the value
+ */
+static inline JitReg
+jit_cc_new_const_I32(JitCompContext *cc, int32 val)
+{
+ return jit_cc_new_const_I32_rel(cc, val, 0);
+}
+
+/**
+ * Create a I64 constant value into the compilation context.
+ *
+ * @param cc compilation context
+ * @param val a I64 value
+ *
+ * @return a constant register containing the value
+ */
+JitReg
+jit_cc_new_const_I64(JitCompContext *cc, int64 val);
+
+#if UINTPTR_MAX == UINT64_MAX
+#define jit_cc_new_const_PTR jit_cc_new_const_I64
+#else
+#define jit_cc_new_const_PTR jit_cc_new_const_I32
+#endif
+
+/**
+ * Create a F32 constant value into the compilation context.
+ *
+ * @param cc compilation context
+ * @param val a F32 value
+ *
+ * @return a constant register containing the value
+ */
+JitReg
+jit_cc_new_const_F32(JitCompContext *cc, float val);
+
+/**
+ * Create a F64 constant value into the compilation context.
+ *
+ * @param cc compilation context
+ * @param val a F64 value
+ *
+ * @return a constant register containing the value
+ */
+JitReg
+jit_cc_new_const_F64(JitCompContext *cc, double val);
+
+/**
+ * Get the relocation info of a I32 constant register.
+ *
+ * @param cc compilation context
+ * @param reg constant register
+ *
+ * @return the relocation info of the constant
+ */
+uint32
+jit_cc_get_const_I32_rel(JitCompContext *cc, JitReg reg);
+
+/**
+ * Get the constant value of a I32 constant register.
+ *
+ * @param cc compilation context
+ * @param reg constant register
+ *
+ * @return the constant value
+ */
+int32
+jit_cc_get_const_I32(JitCompContext *cc, JitReg reg);
+
+/**
+ * Get the constant value of a I64 constant register.
+ *
+ * @param cc compilation context
+ * @param reg constant register
+ *
+ * @return the constant value
+ */
+int64
+jit_cc_get_const_I64(JitCompContext *cc, JitReg reg);
+
+/**
+ * Get the constant value of a F32 constant register.
+ *
+ * @param cc compilation context
+ * @param reg constant register
+ *
+ * @return the constant value
+ */
+float
+jit_cc_get_const_F32(JitCompContext *cc, JitReg reg);
+
+/**
+ * Get the constant value of a F64 constant register.
+ *
+ * @param cc compilation context
+ * @param reg constant register
+ *
+ * @return the constant value
+ */
+double
+jit_cc_get_const_F64(JitCompContext *cc, JitReg reg);
+
+/**
+ * Get the number of total created labels.
+ *
+ * @param cc the compilation context
+ *
+ * @return the number of total created labels
+ */
+static inline unsigned
+jit_cc_label_num(JitCompContext *cc)
+{
+ return cc->_ann._label_num;
+}
+
+/**
+ * Get the number of total created instructions.
+ *
+ * @param cc the compilation context
+ *
+ * @return the number of total created instructions
+ */
+static inline unsigned
+jit_cc_insn_num(JitCompContext *cc)
+{
+ return cc->_ann._insn_num;
+}
+
+/**
+ * Get the number of total created registers.
+ *
+ * @param cc the compilation context
+ * @param kind the register kind
+ *
+ * @return the number of total created registers
+ */
+static inline unsigned
+jit_cc_reg_num(JitCompContext *cc, unsigned kind)
+{
+ bh_assert(kind < JIT_REG_KIND_L32);
+ return cc->_ann._reg_num[kind];
+}
+
+/**
+ * Create a new label in the compilation context.
+ *
+ * @param cc the compilation context
+ *
+ * @return a new label in the compilation context
+ */
+JitReg
+jit_cc_new_label(JitCompContext *cc);
+
+/**
+ * Create a new block with a new label in the compilation context.
+ *
+ * @param cc the compilation context
+ * @param n number of predecessors
+ *
+ * @return a new block with a new label in the compilation context
+ */
+JitBasicBlock *
+jit_cc_new_basic_block(JitCompContext *cc, int n);
+
+/**
+ * Resize the predecessor number of a block.
+ *
+ * @param cc the containing compilation context
+ * @param block block to be resized
+ * @param n new number of predecessors
+ *
+ * @return the new block if succeeds, NULL otherwise
+ */
+JitBasicBlock *
+jit_cc_resize_basic_block(JitCompContext *cc, JitBasicBlock *block, int n);
+
+/**
+ * Initialize the instruction hash table to the given size and enable
+ * the instruction's _hash_link annotation.
+ *
+ * @param cc the containing compilation context
+ * @param n size of the hash table
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jit_cc_enable_insn_hash(JitCompContext *cc, unsigned n);
+
+/**
+ * Destroy the instruction hash table and disable the instruction's
+ * _hash_link annotation.
+ *
+ * @param cc the containing compilation context
+ */
+void
+jit_cc_disable_insn_hash(JitCompContext *cc);
+
+/**
+ * Reset the hash table entries.
+ *
+ * @param cc the containing compilation context
+ */
+void
+jit_cc_reset_insn_hash(JitCompContext *cc);
+
+/**
+ * Allocate a new instruction ID in the compilation context and set it
+ * to the given instruction.
+ *
+ * @param cc the compilation context
+ * @param insn IR instruction
+ *
+ * @return the insn with uid being set
+ */
+JitInsn *
+jit_cc_set_insn_uid(JitCompContext *cc, JitInsn *insn);
+
+/*
+ * Similar to jit_cc_set_insn_uid except that if setting uid failed,
+ * delete the insn. Only used by jit_cc_new_insn
+ */
+JitInsn *
+_jit_cc_set_insn_uid_for_new_insn(JitCompContext *cc, JitInsn *insn);
+
+/**
+ * Create a new instruction in the compilation context.
+ *
+ * @param cc the compilationo context
+ * @param NAME instruction name
+ *
+ * @return a new instruction in the compilation context
+ */
+#define jit_cc_new_insn(cc, NAME, ...) \
+ _jit_cc_set_insn_uid_for_new_insn(cc, jit_insn_new_##NAME(__VA_ARGS__))
+
+/*
+ * Helper function for jit_cc_new_insn_norm.
+ */
+JitInsn *
+_jit_cc_new_insn_norm(JitCompContext *cc, JitReg *result, JitInsn *insn);
+
+/**
+ * Create a new instruction in the compilation context and normalize
+ * the instruction (constant folding and simplification etc.). If the
+ * instruction hashing is enabled (anni__hash_link is enabled), try to
+ * find the existing equivalent insruction first before adding a new
+ * one to the compilation contest.
+ *
+ * @param cc the compilationo context
+ * @param result returned result of the instruction. If the value is
+ * non-zero, it is the result of the constant-folding or an exsiting
+ * equivalent instruction, in which case no instruction is added into
+ * the compilation context. Otherwise, a new normalized instruction
+ * has been added into the compilation context.
+ * @param NAME instruction name
+ *
+ * @return a new or existing instruction in the compilation context
+ */
+#define jit_cc_new_insn_norm(cc, result, NAME, ...) \
+ _jit_cc_new_insn_norm(cc, result, jit_insn_new_##NAME(__VA_ARGS__))
+
+/**
+ * Helper function for GEN_INSN
+ *
+ * @param cc compilation context
+ * @param block the current block
+ * @param insn the new instruction
+ *
+ * @return the new instruction if inserted, NULL otherwise
+ */
+static inline JitInsn *
+_gen_insn(JitCompContext *cc, JitInsn *insn)
+{
+ if (insn)
+ jit_basic_block_append_insn(cc->cur_basic_block, insn);
+ else
+ jit_set_last_error(cc, "generate insn failed");
+
+ return insn;
+}
+
+/**
+ * Generate and append an instruction to the current block.
+ */
+#define GEN_INSN(...) _gen_insn(cc, jit_cc_new_insn(cc, __VA_ARGS__))
+
+/**
+ * Create a constant register without relocation info.
+ *
+ * @param Type type of the register
+ * @param val the constant value
+ *
+ * @return the constant register if succeeds, 0 otherwise
+ */
+#define NEW_CONST(Type, val) jit_cc_new_const_##Type(cc, val)
+
+/**
+ * Create a new virtual register in the compilation context.
+ *
+ * @param cc the compilation context
+ * @param kind kind of the register
+ *
+ * @return a new label in the compilation context
+ */
+JitReg
+jit_cc_new_reg(JitCompContext *cc, unsigned kind);
+
+/*
+ * Create virtual registers with specific types in the compilation
+ * context. They are more convenient than the above one.
+ */
+
+static inline JitReg
+jit_cc_new_reg_I32(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_I32);
+}
+
+static inline JitReg
+jit_cc_new_reg_I64(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_I64);
+}
+
+#if UINTPTR_MAX == UINT64_MAX
+#define jit_cc_new_reg_ptr jit_cc_new_reg_I64
+#else
+#define jit_cc_new_reg_ptr jit_cc_new_reg_I32
+#endif
+
+static inline JitReg
+jit_cc_new_reg_F32(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_F32);
+}
+
+static inline JitReg
+jit_cc_new_reg_F64(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_F64);
+}
+
+static inline JitReg
+jit_cc_new_reg_V64(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_V64);
+}
+
+static inline JitReg
+jit_cc_new_reg_V128(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_V128);
+}
+
+static inline JitReg
+jit_cc_new_reg_V256(JitCompContext *cc)
+{
+ return jit_cc_new_reg(cc, JIT_REG_KIND_V256);
+}
+
+/**
+ * Get the hard register numbe of the given kind
+ *
+ * @param cc the compilation context
+ * @param kind the register kind
+ *
+ * @return number of hard registers of the given kind
+ */
+static inline unsigned
+jit_cc_hreg_num(JitCompContext *cc, unsigned kind)
+{
+ bh_assert(kind < JIT_REG_KIND_L32);
+ return cc->hreg_info->info[kind].num;
+}
+
+/**
+ * Check whether a given register is a hard register.
+ *
+ * @param cc the compilation context
+ * @param reg the register which must be a variable
+ *
+ * @return true if the register is a hard register
+ */
+static inline bool
+jit_cc_is_hreg(JitCompContext *cc, JitReg reg)
+{
+ unsigned kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+ bh_assert(jit_reg_is_variable(reg));
+ bh_assert(kind < JIT_REG_KIND_L32);
+ return no < cc->hreg_info->info[kind].num;
+}
+
+/**
+ * Check whether the given hard register is fixed.
+ *
+ * @param cc the compilation context
+ * @param reg the hard register
+ *
+ * @return true if the hard register is fixed
+ */
+static inline bool
+jit_cc_is_hreg_fixed(JitCompContext *cc, JitReg reg)
+{
+ unsigned kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+ bh_assert(jit_cc_is_hreg(cc, reg));
+ bh_assert(kind < JIT_REG_KIND_L32);
+ return !!cc->hreg_info->info[kind].fixed[no];
+}
+
+/**
+ * Check whether the given hard register is caller-saved-native.
+ *
+ * @param cc the compilation context
+ * @param reg the hard register
+ *
+ * @return true if the hard register is caller-saved-native
+ */
+static inline bool
+jit_cc_is_hreg_caller_saved_native(JitCompContext *cc, JitReg reg)
+{
+ unsigned kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+ bh_assert(jit_cc_is_hreg(cc, reg));
+ bh_assert(kind < JIT_REG_KIND_L32);
+ return !!cc->hreg_info->info[kind].caller_saved_native[no];
+}
+
+/**
+ * Check whether the given hard register is caller-saved-jitted.
+ *
+ * @param cc the compilation context
+ * @param reg the hard register
+ *
+ * @return true if the hard register is caller-saved-jitted
+ */
+static inline bool
+jit_cc_is_hreg_caller_saved_jitted(JitCompContext *cc, JitReg reg)
+{
+ unsigned kind = jit_reg_kind(reg);
+ unsigned no = jit_reg_no(reg);
+ bh_assert(jit_cc_is_hreg(cc, reg));
+ bh_assert(kind < JIT_REG_KIND_L32);
+ return !!cc->hreg_info->info[kind].caller_saved_jitted[no];
+}
+
+/**
+ * Return the entry block of the compilation context.
+ *
+ * @param cc the compilation context
+ *
+ * @return the entry block of the compilation context
+ */
+static inline JitBasicBlock *
+jit_cc_entry_basic_block(JitCompContext *cc)
+{
+ return *(jit_annl_basic_block(cc, cc->entry_label));
+}
+
+/**
+ * Return the exit block of the compilation context.
+ *
+ * @param cc the compilation context
+ *
+ * @return the exit block of the compilation context
+ */
+static inline JitBasicBlock *
+jit_cc_exit_basic_block(JitCompContext *cc)
+{
+ return *(jit_annl_basic_block(cc, cc->exit_label));
+}
+
+void
+jit_value_stack_push(JitValueStack *stack, JitValue *value);
+
+JitValue *
+jit_value_stack_pop(JitValueStack *stack);
+
+void
+jit_value_stack_destroy(JitValueStack *stack);
+
+JitBlock *
+jit_block_stack_top(JitBlockStack *stack);
+
+void
+jit_block_stack_push(JitBlockStack *stack, JitBlock *block);
+
+JitBlock *
+jit_block_stack_pop(JitBlockStack *stack);
+
+void
+jit_block_stack_destroy(JitBlockStack *stack);
+
+bool
+jit_block_add_incoming_insn(JitBlock *block, JitInsn *insn, uint32 opnd_idx);
+
+void
+jit_block_destroy(JitBlock *block);
+
+bool
+jit_cc_push_value(JitCompContext *cc, uint8 type, JitReg value);
+
+bool
+jit_cc_pop_value(JitCompContext *cc, uint8 type, JitReg *p_value);
+
+bool
+jit_lock_reg_in_insn(JitCompContext *cc, JitInsn *the_insn, JitReg reg_to_lock);
+
+/**
+ * Update the control flow graph after successors of blocks are
+ * changed so that the predecessor vector of each block represents the
+ * updated status. The predecessors may not be required by all
+ * passes, so we don't need to keep them always being updated.
+ *
+ * @param cc the compilation context
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jit_cc_update_cfg(JitCompContext *cc);
+
+/**
+ * Visit each normal block (which is not entry nor exit block) in a
+ * compilation context. New blocks can be added in the loop body, but
+ * they won't be visited. Blocks can also be removed safely (by
+ * setting the label's block annotation to NULL) in the loop body.
+ *
+ * @param CC (JitCompContext *) the compilation context
+ * @param I (unsigned) index variable of the block (label no)
+ * @param E (unsigned) end index variable of block (last index + 1)
+ * @param B (JitBasicBlock *) block pointer variable
+ */
+#define JIT_FOREACH_BLOCK(CC, I, E, B) \
+ for ((I) = 2, (E) = (CC)->_ann._label_num; (I) < (E); (I)++) \
+ if (((B) = (CC)->_ann._label_basic_block[(I)]))
+
+/**
+ * The version that includes entry and exit block.
+ */
+#define JIT_FOREACH_BLOCK_ENTRY_EXIT(CC, I, E, B) \
+ for ((I) = 0, (E) = (CC)->_ann._label_num; (I) < (E); (I)++) \
+ if (((B) = (CC)->_ann._label_basic_block[(I)]))
+
+/**
+ * Visit each normal block (which is not entry nor exit block) in a
+ * compilation context in reverse order. New blocks can be added in
+ * the loop body, but they won't be visited. Blocks can also be
+ * removed safely (by setting the label's block annotation to NULL) in
+ * the loop body.
+ *
+ * @param CC (JitCompContext *) the compilation context
+ * @param I (unsigned) index of the block (label no)
+ * @param B (JitBasicBlock *) block pointer
+ */
+#define JIT_FOREACH_BLOCK_REVERSE(CC, I, B) \
+ for ((I) = (CC)->_ann._label_num; (I) > 2; (I)--) \
+ if (((B) = (CC)->_ann._label_basic_block[(I)-1]))
+
+/**
+ * The version that includes entry and exit block.
+ */
+#define JIT_FOREACH_BLOCK_REVERSE_ENTRY_EXIT(CC, I, B) \
+ for ((I) = (CC)->_ann._label_num; (I) > 0; (I)--) \
+ if (((B) = (CC)->_ann._label_basic_block[(I)-1]))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _JIT_IR_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_regalloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_regalloc.c
new file mode 100644
index 000000000..70ca228ac
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_regalloc.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_utils.h"
+#include "jit_compiler.h"
+
+#if BH_DEBUG != 0
+#define VREG_DEF_SANITIZER
+#endif
+
+/**
+ * A uint16 stack for storing distances of occurrences of virtual
+ * registers.
+ */
+typedef struct UintStack {
+ /* Capacity of the stack. */
+ uint32 capacity;
+
+ /* Top index of the stack. */
+ uint32 top;
+
+ /* Elements of the vector. */
+ uint32 elem[1];
+} UintStack;
+
+static bool
+uint_stack_push(UintStack **stack, unsigned val)
+{
+ unsigned capacity = *stack ? (*stack)->capacity : 0;
+ unsigned top = *stack ? (*stack)->top : 0;
+
+ bh_assert(top <= capacity);
+
+ if (top == capacity) {
+ const unsigned elem_size = sizeof((*stack)->elem[0]);
+ unsigned new_capacity = capacity ? capacity + capacity / 2 : 4;
+ UintStack *new_stack =
+ jit_malloc(offsetof(UintStack, elem) + elem_size * new_capacity);
+
+ if (!new_stack)
+ return false;
+
+ new_stack->capacity = new_capacity;
+ new_stack->top = top;
+
+ if (*stack)
+ memcpy(new_stack->elem, (*stack)->elem, elem_size * top);
+
+ jit_free(*stack);
+ *stack = new_stack;
+ }
+
+ (*stack)->elem[(*stack)->top++] = val;
+
+ return true;
+}
+
+static int
+uint_stack_top(UintStack *stack)
+{
+ return stack->elem[stack->top - 1];
+}
+
+static void
+uint_stack_delete(UintStack **stack)
+{
+ jit_free(*stack);
+ *stack = NULL;
+}
+
+static void
+uint_stack_pop(UintStack **stack)
+{
+ bh_assert((*stack)->top > 0);
+
+ /**
+ * TODO: the fact of empty distances stack means there is no instruction
+ * using current JitReg anymore. so shall we release the HardReg and clean
+ * VirtualReg information?
+ */
+ if (--(*stack)->top == 0)
+ uint_stack_delete(stack);
+}
+
+/**
+ * Information of a virtual register.
+ */
+typedef struct VirtualReg {
+ /* The hard register allocated to this virtual register. */
+ JitReg hreg;
+
+ /* The spill slot allocated to this virtual register. */
+ JitReg slot;
+
+ /* The hard register allocated to global virtual registers. It is 0
+ for local registers, whose lifetime is within one basic block. */
+ JitReg global_hreg;
+
+ /* Distances from the beginning of basic block of all occurrences of the
+ virtual register in the basic block. */
+ UintStack *distances;
+} VirtualReg;
+
+/**
+ * Information of a hard register.
+ */
+typedef struct HardReg {
+ /* The virtual register this hard register is allocated to. */
+ JitReg vreg;
+} HardReg;
+
+/**
+ * Information of a spill slot.
+ */
+typedef struct SpillSlot {
+ /* The virtual register this spill slot is allocated to. */
+ JitReg vreg;
+} SpillSlot;
+
+typedef struct RegallocContext {
+ /* The compiler context. */
+ JitCompContext *cc;
+
+ /* Information of virtual registers. The register allocation must
+ not increase the virtual register number during the allocation
+ process. */
+ VirtualReg *vregs[JIT_REG_KIND_L32];
+
+ /* Information of hard registers. */
+ HardReg *hregs[JIT_REG_KIND_L32];
+
+ /* Number of elements in the spill_slots array. */
+ uint32 spill_slot_num;
+
+ /* Information of spill slots. */
+ SpillSlot *spill_slots;
+
+ /* The last define-released hard register. */
+ JitReg last_def_released_hreg;
+} RegallocContext;
+
+/**
+ * Get the VirtualReg structure of the given virtual register.
+ *
+ * @param rc the regalloc context
+ * @param vreg the virtual register
+ *
+ * @return the VirtualReg structure of the given virtual register
+ */
+static VirtualReg *
+rc_get_vr(RegallocContext *rc, JitReg vreg)
+{
+ unsigned kind = jit_reg_kind(vreg);
+ unsigned no = jit_reg_no(vreg);
+
+ bh_assert(jit_reg_is_variable(vreg));
+ bh_assert(kind < JIT_REG_KIND_L32);
+
+ return &rc->vregs[kind][no];
+}
+
+/**
+ * Get the HardReg structure of the given hard register.
+ *
+ * @param rc the regalloc context
+ * @param hreg the hard register
+ *
+ * @return the HardReg structure of the given hard register
+ */
+static HardReg *
+rc_get_hr(RegallocContext *rc, JitReg hreg)
+{
+ unsigned kind = jit_reg_kind(hreg);
+ unsigned no = jit_reg_no(hreg);
+
+ bh_assert(jit_reg_is_variable(hreg) && jit_cc_is_hreg(rc->cc, hreg));
+ bh_assert(kind < JIT_REG_KIND_L32);
+
+ return &rc->hregs[kind][no];
+}
+
+/**
+ * Get the SpillSlot structure of the given slot.
+ *
+ * @param rc the regalloc context
+ * @param slot the constant register representing the slot index
+ *
+ * @return the SpillSlot of the given slot
+ */
+static SpillSlot *
+rc_get_spill_slot(RegallocContext *rc, JitReg slot)
+{
+ unsigned index = jit_cc_get_const_I32(rc->cc, slot);
+
+ bh_assert(index < rc->spill_slot_num);
+
+ return &rc->spill_slots[index];
+}
+
+/**
+ * Get the stride in the spill slots of the register.
+ *
+ * @param reg a virtual register
+ *
+ * @return stride in the spill slots
+ */
+static unsigned
+get_reg_stride(JitReg reg)
+{
+ static const uint8 strides[] = { 0, 1, 2, 1, 2, 2, 4, 8, 0 };
+ uint32 kind = jit_reg_kind(reg);
+ bh_assert(kind <= JIT_REG_KIND_L32);
+ return strides[kind];
+}
+
+/**
+ * Allocate a spill slot for the given virtual register.
+ *
+ * @param rc the regalloc context
+ * @param vreg the virtual register
+ *
+ * @return the spill slot encoded in a consant register
+ */
+static JitReg
+rc_alloc_spill_slot(RegallocContext *rc, JitReg vreg)
+{
+ const unsigned stride = get_reg_stride(vreg);
+ unsigned mask, new_num, i, j;
+ SpillSlot *slots;
+
+ bh_assert(stride > 0);
+
+ for (i = 0; i < rc->spill_slot_num; i += stride)
+ for (j = i;; j++) {
+ if (j == i + stride)
+ /* Found a free slot for vreg. */
+ goto found;
+
+ if (rc->spill_slots[j].vreg)
+ break;
+ }
+
+ /* No free slot, increase the slot number. */
+ mask = stride - 1;
+ /* Align the slot index. */
+ i = (rc->spill_slot_num + mask) & ~mask;
+ new_num = i == 0 ? 32 : i + i / 2;
+
+ if (!(slots = jit_calloc(sizeof(*slots) * new_num)))
+ return 0;
+
+ if (rc->spill_slots)
+ memcpy(slots, rc->spill_slots, sizeof(*slots) * rc->spill_slot_num);
+
+ jit_free(rc->spill_slots);
+ rc->spill_slots = slots;
+ rc->spill_slot_num = new_num;
+
+found:
+ /* Now, i is the first slot for vreg. */
+ if ((i + stride) * 4 > rc->cc->spill_cache_size)
+ /* No frame space for the spill area. */
+ return 0;
+
+ /* Allocate the slot(s) to vreg. */
+ for (j = i; j < i + stride; j++)
+ rc->spill_slots[j].vreg = vreg;
+
+ return jit_cc_new_const_I32(rc->cc, i);
+}
+
+/**
+ * Free a spill slot.
+ *
+ * @param rc the regalloc context
+ * @param slot_reg the constant register representing the slot index
+ */
+static void
+rc_free_spill_slot(RegallocContext *rc, JitReg slot_reg)
+{
+ if (slot_reg) {
+ SpillSlot *slot = rc_get_spill_slot(rc, slot_reg);
+ const JitReg vreg = slot->vreg;
+ const unsigned stride = get_reg_stride(vreg);
+ unsigned i;
+
+ for (i = 0; i < stride; i++)
+ slot[i].vreg = 0;
+ }
+}
+
+static void
+rc_destroy(RegallocContext *rc)
+{
+ unsigned i, j;
+
+ for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
+ const unsigned vreg_num = jit_cc_reg_num(rc->cc, i);
+
+ if (rc->vregs[i])
+ for (j = 0; j < vreg_num; j++)
+ uint_stack_delete(&rc->vregs[i][j].distances);
+
+ jit_free(rc->vregs[i]);
+ jit_free(rc->hregs[i]);
+ }
+
+ jit_free(rc->spill_slots);
+}
+
+static bool
+rc_init(RegallocContext *rc, JitCompContext *cc)
+{
+ unsigned i, j;
+
+ memset(rc, 0, sizeof(*rc));
+ rc->cc = cc;
+
+ for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
+ const unsigned vreg_num = jit_cc_reg_num(cc, i);
+ const unsigned hreg_num = jit_cc_hreg_num(cc, i);
+
+ if (vreg_num > 0
+ && !(rc->vregs[i] = jit_calloc(sizeof(VirtualReg) * vreg_num)))
+ goto fail;
+ if (hreg_num > 0
+ && !(rc->hregs[i] = jit_calloc(sizeof(HardReg) * hreg_num)))
+ goto fail;
+
+ /* Hard registers can only be allocated to themselves. */
+ for (j = 0; j < hreg_num; j++)
+ rc->vregs[i][j].global_hreg = jit_reg_new(i, j);
+ }
+
+ return true;
+
+fail:
+ rc_destroy(rc);
+
+ return false;
+}
+
+/**
+ * Check whether the given register is an allocation candidate, which
+ * must be a variable register that is not fixed hard register.
+ *
+ * @param cc the compilation context
+ * @param reg the register
+ *
+ * @return true if the register is an allocation candidate
+ */
+static bool
+is_alloc_candidate(JitCompContext *cc, JitReg reg)
+{
+ return (jit_reg_is_variable(reg)
+ && (!jit_cc_is_hreg(cc, reg) || !jit_cc_is_hreg_fixed(cc, reg)));
+}
+
+#ifdef VREG_DEF_SANITIZER
+static void
+check_vreg_definition(RegallocContext *rc, JitInsn *insn)
+{
+ JitRegVec regvec = jit_insn_opnd_regs(insn);
+ JitReg *regp, reg_defined = 0;
+ unsigned i, first_use = jit_insn_opnd_first_use(insn);
+
+ /* check if there is the definition of an vr before its references */
+ JIT_REG_VEC_FOREACH(regvec, i, regp)
+ {
+ VirtualReg *vr = NULL;
+
+ if (!is_alloc_candidate(rc->cc, *regp))
+ continue;
+
+ /* a strong assumption that there is only one defined reg */
+ if (i < first_use) {
+ reg_defined = *regp;
+ continue;
+ }
+
+ /**
+ * both definition and references are in one instruction,
+ * like MOV i3, i3
+ */
+ if (reg_defined == *regp)
+ continue;
+
+ vr = rc_get_vr(rc, *regp);
+ bh_assert(vr->distances);
+ }
+}
+#endif
+
+/**
+ * Collect distances from the beginning of basic block of all occurrences of
+ * each virtual register.
+ *
+ * @param rc the regalloc context
+ * @param basic_block the basic block
+ *
+ * @return distance of the end instruction if succeeds, -1 otherwise
+ */
+static int
+collect_distances(RegallocContext *rc, JitBasicBlock *basic_block)
+{
+ JitInsn *insn;
+ int distance = 1;
+
+ JIT_FOREACH_INSN(basic_block, insn)
+ {
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ /* fence insn doesn't have any operand, hence, no regs involved */
+ if (insn->opcode == JIT_OP_FENCE) {
+ continue;
+ }
+#endif
+
+ JitRegVec regvec = jit_insn_opnd_regs(insn);
+ unsigned i;
+ JitReg *regp;
+
+#ifdef VREG_DEF_SANITIZER
+ check_vreg_definition(rc, insn);
+#endif
+
+ /* NOTE: the distance may be pushed more than once if the
+ virtual register occurs multiple times in the
+ instruction. */
+ JIT_REG_VEC_FOREACH(regvec, i, regp)
+ if (is_alloc_candidate(rc->cc, *regp))
+ if (!uint_stack_push(&(rc_get_vr(rc, *regp))->distances, distance))
+ return -1;
+
+ /* Integer overflow check, normally it won't happen, but
+ we had better add the check here */
+ if (distance >= INT32_MAX)
+ return -1;
+
+ distance++;
+ }
+
+ return distance;
+}
+
+static JitReg
+offset_of_spill_slot(JitCompContext *cc, JitReg slot)
+{
+ return jit_cc_new_const_I32(cc, cc->spill_cache_offset
+ + jit_cc_get_const_I32(cc, slot) * 4);
+}
+
+/**
+ * Reload the virtual register from memory. Reload instruction will
+ * be inserted after the given instruction.
+ *
+ * @param rc the regalloc context
+ * @param vreg the virtual register to be reloaded
+ * @param cur_insn the current instruction after which the reload
+ * insertion will be inserted
+ *
+ * @return the reload instruction if succeeds, NULL otherwise
+ */
+static JitInsn *
+reload_vreg(RegallocContext *rc, JitReg vreg, JitInsn *cur_insn)
+{
+ VirtualReg *vr = rc_get_vr(rc, vreg);
+ HardReg *hr = rc_get_hr(rc, vr->hreg);
+ JitInsn *insn = NULL;
+
+ if (vreg == rc->cc->exec_env_reg)
+ /* Reload exec_env_reg with LDEXECENV. */
+ insn = jit_cc_new_insn(rc->cc, LDEXECENV, vr->hreg);
+ else
+ /* Allocate spill slot if not yet and reload from there. */
+ {
+ JitReg fp_reg = rc->cc->fp_reg, offset;
+
+ if (!vr->slot && !(vr->slot = rc_alloc_spill_slot(rc, vreg)))
+ /* Cannot allocte spill slot (due to OOM or frame size limit). */
+ return NULL;
+
+ offset = offset_of_spill_slot(rc->cc, vr->slot);
+
+ switch (jit_reg_kind(vreg)) {
+ case JIT_REG_KIND_I32:
+ insn = jit_cc_new_insn(rc->cc, LDI32, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_I64:
+ insn = jit_cc_new_insn(rc->cc, LDI64, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_F32:
+ insn = jit_cc_new_insn(rc->cc, LDF32, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_F64:
+ insn = jit_cc_new_insn(rc->cc, LDF64, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_V64:
+ insn = jit_cc_new_insn(rc->cc, LDV64, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_V128:
+ insn =
+ jit_cc_new_insn(rc->cc, LDV128, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_V256:
+ insn =
+ jit_cc_new_insn(rc->cc, LDV256, vr->hreg, fp_reg, offset);
+ break;
+ default:
+ bh_assert(0);
+ }
+ }
+
+ if (insn)
+ jit_insn_insert_after(cur_insn, insn);
+
+ bh_assert(hr->vreg == vreg);
+ hr->vreg = vr->hreg = 0;
+
+ return insn;
+}
+
+/**
+ * Spill the virtual register (which cannot be exec_env_reg) to memory.
+ * Spill instruction will be inserted after the given instruction.
+ *
+ * @param rc the regalloc context
+ * @param vreg the virtual register to be reloaded
+ * @param cur_insn the current instruction after which the reload
+ * insertion will be inserted
+ *
+ * @return the spill instruction if succeeds, NULL otherwise
+ */
+static JitInsn *
+spill_vreg(RegallocContext *rc, JitReg vreg, JitInsn *cur_insn)
+{
+ VirtualReg *vr = rc_get_vr(rc, vreg);
+ JitReg fp_reg = rc->cc->fp_reg, offset;
+ JitInsn *insn;
+
+ /* There is no chance to spill exec_env_reg. */
+ bh_assert(vreg != rc->cc->exec_env_reg);
+ bh_assert(vr->hreg && vr->slot);
+ offset = offset_of_spill_slot(rc->cc, vr->slot);
+
+ switch (jit_reg_kind(vreg)) {
+ case JIT_REG_KIND_I32:
+ insn = jit_cc_new_insn(rc->cc, STI32, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_I64:
+ insn = jit_cc_new_insn(rc->cc, STI64, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_F32:
+ insn = jit_cc_new_insn(rc->cc, STF32, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_F64:
+ insn = jit_cc_new_insn(rc->cc, STF64, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_V64:
+ insn = jit_cc_new_insn(rc->cc, STV64, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_V128:
+ insn = jit_cc_new_insn(rc->cc, STV128, vr->hreg, fp_reg, offset);
+ break;
+ case JIT_REG_KIND_V256:
+ insn = jit_cc_new_insn(rc->cc, STV256, vr->hreg, fp_reg, offset);
+ break;
+ default:
+ bh_assert(0);
+ return NULL;
+ }
+
+ if (insn)
+ jit_insn_insert_after(cur_insn, insn);
+
+ return insn;
+}
+
+/**
+ * Allocate a hard register for the virtual register. Necessary
+ * reloade instruction will be inserted after the given instruction.
+ *
+ * @param rc the regalloc context
+ * @param vreg the virtual register
+ * @param insn the instruction after which the reload insertion will
+ * be inserted
+ * @param distance the distance of the current instruction
+ *
+ * @return the hard register allocated if succeeds, 0 otherwise
+ */
+static JitReg
+allocate_hreg(RegallocContext *rc, JitReg vreg, JitInsn *insn, int distance)
+{
+ const int kind = jit_reg_kind(vreg);
+ const HardReg *hregs;
+ unsigned hreg_num;
+ JitReg hreg, vreg_to_reload = 0;
+ int min_distance = distance, vr_distance;
+ VirtualReg *vr = rc_get_vr(rc, vreg);
+ unsigned i;
+
+ bh_assert(kind < JIT_REG_KIND_L32);
+ hregs = rc->hregs[kind];
+ hreg_num = jit_cc_hreg_num(rc->cc, kind);
+
+ if (hreg_num == 0)
+ /* Unsupported hard register kind. */
+ {
+ jit_set_last_error(rc->cc, "unsupported hard register kind");
+ return 0;
+ }
+
+ if (vr->global_hreg)
+ /* It has globally allocated register, we can only use it. */
+ {
+ if ((vreg_to_reload = (rc_get_hr(rc, vr->global_hreg))->vreg))
+ if (!reload_vreg(rc, vreg_to_reload, insn))
+ return 0;
+
+ return vr->global_hreg;
+ }
+
+ /* Use the last define-released register if its kind is correct and
+ it's free so as to optimize for two-operand instructions. */
+ if (jit_reg_kind(rc->last_def_released_hreg) == kind
+ && (rc_get_hr(rc, rc->last_def_released_hreg))->vreg == 0)
+ return rc->last_def_released_hreg;
+
+ /* No hint given, just try to pick any free register. */
+ for (i = 0; i < hreg_num; i++) {
+ hreg = jit_reg_new(kind, i);
+
+ if (jit_cc_is_hreg_fixed(rc->cc, hreg))
+ continue;
+
+ if (hregs[i].vreg == 0)
+ /* Found a free one, return it. */
+ return hreg;
+ }
+
+ /* No free registers, need to spill and reload one. */
+ for (i = 0; i < hreg_num; i++) {
+ if (jit_cc_is_hreg_fixed(rc->cc, jit_reg_new(kind, i)))
+ continue;
+
+ vr = rc_get_vr(rc, hregs[i].vreg);
+ /* TODO: since the hregs[i] is in use, its distances should be valid */
+ vr_distance = vr->distances ? uint_stack_top(vr->distances) : 0;
+
+ if (vr_distance < min_distance) {
+ min_distance = vr_distance;
+ vreg_to_reload = hregs[i].vreg;
+ hreg = jit_reg_new(kind, i);
+ }
+ }
+
+ bh_assert(min_distance < distance);
+
+ if (!reload_vreg(rc, vreg_to_reload, insn))
+ return 0;
+
+ return hreg;
+}
+
+/**
+ * Allocate a hard register for the virtual register if not allocated
+ * yet. Necessary spill and reloade instructions will be inserted
+ * before/after and after the given instruction. This operation will
+ * convert the virtual register's state from 1 or 3 to 2.
+ *
+ * @param rc the regalloc context
+ * @param vreg the virtual register
+ * @param insn the instruction after which the spill and reload
+ * insertions will be inserted
+ * @param distance the distance of the current instruction
+ *
+ * @return the hard register allocated to the virtual register if
+ * succeeds, 0 otherwise
+ */
+static JitReg
+allocate_for_vreg(RegallocContext *rc, JitReg vreg, JitInsn *insn, int distance)
+{
+ VirtualReg *vr = rc_get_vr(rc, vreg);
+
+ if (vr->hreg)
+ /* It has had a hard register, reuse it. */
+ return vr->hreg;
+
+ /* Not allocated yet. */
+ if ((vr->hreg = allocate_hreg(rc, vreg, insn, distance)))
+ (rc_get_hr(rc, vr->hreg))->vreg = vreg;
+
+ return vr->hreg;
+}
+
+/**
+ * Clobber live registers.
+ *
+ * @param rc the regalloc context
+ * @param is_native whether it's native ABI or JITed ABI
+ * @param insn the instruction after which the reload insertion will
+ * be inserted
+ *
+ * @return true if succeeds, false otherwise
+ */
+static bool
+clobber_live_regs(RegallocContext *rc, bool is_native, JitInsn *insn)
+{
+ unsigned i, j;
+
+ for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
+ const unsigned hreg_num = jit_cc_hreg_num(rc->cc, i);
+
+ for (j = 0; j < hreg_num; j++) {
+ JitReg hreg = jit_reg_new(i, j);
+ bool caller_saved =
+ (is_native ? jit_cc_is_hreg_caller_saved_native(rc->cc, hreg)
+ : jit_cc_is_hreg_caller_saved_jitted(rc->cc, hreg));
+
+ if (caller_saved && rc->hregs[i][j].vreg)
+ if (!reload_vreg(rc, rc->hregs[i][j].vreg, insn))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Do local register allocation for the given basic block
+ *
+ * @param rc the regalloc context
+ * @param basic_block the basic block
+ * @param distance the distance of the last instruction of the basic block
+ *
+ * @return true if succeeds, false otherwise
+ */
+static bool
+allocate_for_basic_block(RegallocContext *rc, JitBasicBlock *basic_block,
+ int distance)
+{
+ JitInsn *insn;
+
+ JIT_FOREACH_INSN_REVERSE(basic_block, insn)
+ {
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ /* fence insn doesn't have any operand, hence, no regs involved */
+ if (insn->opcode == JIT_OP_FENCE) {
+ continue;
+ }
+#endif
+
+ JitRegVec regvec = jit_insn_opnd_regs(insn);
+ unsigned first_use = jit_insn_opnd_first_use(insn);
+ unsigned i;
+ JitReg *regp;
+
+ distance--;
+
+ JIT_REG_VEC_FOREACH_DEF(regvec, i, regp, first_use)
+ if (is_alloc_candidate(rc->cc, *regp)) {
+ const JitReg vreg = *regp;
+ VirtualReg *vr = rc_get_vr(rc, vreg);
+
+ if (!(*regp = allocate_for_vreg(rc, vreg, insn, distance)))
+ return false;
+
+ /* Spill the register if required. */
+ if (vr->slot && !spill_vreg(rc, vreg, insn))
+ return false;
+
+ bh_assert(uint_stack_top(vr->distances) == distance);
+ uint_stack_pop(&vr->distances);
+ /* Record the define-released hard register. */
+ rc->last_def_released_hreg = vr->hreg;
+ /* Release the hreg and spill slot. */
+ rc_free_spill_slot(rc, vr->slot);
+ (rc_get_hr(rc, vr->hreg))->vreg = 0;
+ vr->hreg = vr->slot = 0;
+ }
+
+ if (insn->opcode == JIT_OP_CALLBC) {
+ if (!clobber_live_regs(rc, false, insn))
+ return false;
+
+ /* The exec_env_reg is implicitly used by the callee. */
+ if (!allocate_for_vreg(rc, rc->cc->exec_env_reg, insn, distance))
+ return false;
+ }
+ else if (insn->opcode == JIT_OP_CALLNATIVE) {
+ if (!clobber_live_regs(rc, true, insn))
+ return false;
+ }
+
+ JIT_REG_VEC_FOREACH_USE(regvec, i, regp, first_use)
+ if (is_alloc_candidate(rc->cc, *regp)) {
+ if (!allocate_for_vreg(rc, *regp, insn, distance))
+ return false;
+ }
+
+ JIT_REG_VEC_FOREACH_USE(regvec, i, regp, first_use)
+ if (is_alloc_candidate(rc->cc, *regp)) {
+ VirtualReg *vr = rc_get_vr(rc, *regp);
+ bh_assert(uint_stack_top(vr->distances) == distance);
+ uint_stack_pop(&vr->distances);
+ /* be sure that the hreg exists and hasn't been spilled out */
+ bh_assert(vr->hreg != 0);
+ *regp = vr->hreg;
+ }
+ }
+
+ return true;
+}
+
+bool
+jit_pass_regalloc(JitCompContext *cc)
+{
+ RegallocContext rc = { 0 };
+ unsigned label_index, end_label_index;
+ JitBasicBlock *basic_block;
+ VirtualReg *self_vr;
+ bool retval = false;
+
+ if (!rc_init(&rc, cc))
+ return false;
+
+ /* NOTE: don't allocate new virtual registers during allocation
+ because the rc->vregs array is fixed size. */
+
+ /* TODO: allocate hard registers for global virtual registers here.
+ Currently, exec_env_reg is the only global virtual register. */
+ self_vr = rc_get_vr(&rc, cc->exec_env_reg);
+
+ JIT_FOREACH_BLOCK_ENTRY_EXIT(cc, label_index, end_label_index, basic_block)
+ {
+ int distance;
+
+ /* TODO: initialize hreg for live-out registers. */
+ self_vr->hreg = self_vr->global_hreg;
+ (rc_get_hr(&rc, cc->exec_env_reg))->vreg = cc->exec_env_reg;
+
+ /**
+ * TODO: the allocation of a basic block keeps using vregs[]
+ * and hregs[] from previous basic block
+ */
+ if ((distance = collect_distances(&rc, basic_block)) < 0)
+ goto cleanup_and_return;
+
+ if (!allocate_for_basic_block(&rc, basic_block, distance))
+ goto cleanup_and_return;
+
+ /* TODO: generate necessary spills for live-in registers. */
+ }
+
+ retval = true;
+
+cleanup_and_return:
+ rc_destroy(&rc);
+
+ return retval;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.c
new file mode 100644
index 000000000..57a3e8f67
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "jit_utils.h"
+
+JitBitmap *
+jit_bitmap_new(uintptr_t begin_index, unsigned bitnum)
+{
+ JitBitmap *bitmap;
+
+ if ((bitmap = jit_calloc(offsetof(JitBitmap, map) + (bitnum + 7) / 8))) {
+ bitmap->begin_index = begin_index;
+ bitmap->end_index = begin_index + bitnum;
+ }
+
+ return bitmap;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.h
new file mode 100644
index 000000000..c165b7a3c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/fast-jit/jit_utils.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _JIT_UTILS_H_
+#define _JIT_UTILS_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A simple fixed size bitmap.
+ */
+typedef struct JitBitmap {
+ /* The first valid bit index. */
+ uintptr_t begin_index;
+
+ /* The last valid bit index plus one. */
+ uintptr_t end_index;
+
+ /* The bitmap. */
+ uint8 map[1];
+} JitBitmap;
+
+static inline void *
+jit_malloc(unsigned int size)
+{
+ return wasm_runtime_malloc(size);
+}
+
+static inline void *
+jit_calloc(unsigned int size)
+{
+ void *ret = wasm_runtime_malloc(size);
+ if (ret) {
+ memset(ret, 0, size);
+ }
+ return ret;
+}
+
+static inline void
+jit_free(void *ptr)
+{
+ if (ptr)
+ wasm_runtime_free(ptr);
+}
+
+/**
+ * Create a new bitmap.
+ *
+ * @param begin_index the first valid bit index
+ * @param bitnum maximal bit number of the bitmap.
+ *
+ * @return the new bitmap if succeeds, NULL otherwise.
+ */
+JitBitmap *
+jit_bitmap_new(uintptr_t begin_index, unsigned bitnum);
+
+/**
+ * Delete a bitmap.
+ *
+ * @param bitmap the bitmap to be deleted
+ */
+static inline void
+jit_bitmap_delete(JitBitmap *bitmap)
+{
+ jit_free(bitmap);
+}
+
+/**
+ * Check whether the given index is in the range of the bitmap.
+ *
+ * @param bitmap the bitmap
+ * @param n the bit index
+ *
+ * @return true if the index is in range, false otherwise
+ */
+static inline bool
+jit_bitmap_is_in_range(JitBitmap *bitmap, unsigned n)
+{
+ return n >= bitmap->begin_index && n < bitmap->end_index;
+}
+
+/**
+ * Get a bit in the bitmap
+ *
+ * @param bitmap the bitmap
+ * @param n the n-th bit to be get
+ *
+ * @return value of the bit
+ */
+static inline int
+jit_bitmap_get_bit(JitBitmap *bitmap, unsigned n)
+{
+ unsigned idx = n - bitmap->begin_index;
+ bh_assert(n >= bitmap->begin_index && n < bitmap->end_index);
+ return (bitmap->map[idx / 8] >> (idx % 8)) & 1;
+}
+
+/**
+ * Set a bit in the bitmap.
+ *
+ * @param bitmap the bitmap
+ * @param n the n-th bit to be set
+ */
+static inline void
+jit_bitmap_set_bit(JitBitmap *bitmap, unsigned n)
+{
+ unsigned idx = n - bitmap->begin_index;
+ bh_assert(n >= bitmap->begin_index && n < bitmap->end_index);
+ bitmap->map[idx / 8] |= 1 << (idx % 8);
+}
+
+/**
+ * Clear a bit in the bitmap.
+ *
+ * @param bitmap the bitmap
+ * @param n the n-th bit to be cleared
+ */
+static inline void
+jit_bitmap_clear_bit(JitBitmap *bitmap, unsigned n)
+{
+ unsigned idx = n - bitmap->begin_index;
+ bh_assert(n >= bitmap->begin_index && n < bitmap->end_index);
+ bitmap->map[idx / 8] &= ~(1 << (idx % 8));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/aot_export.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/aot_export.h
new file mode 100644
index 000000000..e58873bfd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/aot_export.h
@@ -0,0 +1,107 @@
+/*
+ * 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 <stdint.h>
+#include <stdbool.h>
+
+#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);
+
+#if WASM_ENABLE_DEBUG_AOT != 0
+typedef void *dwar_extractor_handle_t;
+dwar_extractor_handle_t
+create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
+#endif
+
+enum {
+ AOT_FORMAT_FILE,
+ AOT_OBJECT_FILE,
+ AOT_LLVMIR_UNOPT_FILE,
+ AOT_LLVMIR_OPT_FILE,
+};
+
+typedef struct AOTCompOption {
+ bool is_jit_mode;
+ bool is_indirect_mode;
+ char *target_arch;
+ char *target_abi;
+ char *target_cpu;
+ char *cpu_features;
+ bool is_sgx_platform;
+ bool enable_bulk_memory;
+ bool enable_thread_mgr;
+ bool enable_tail_call;
+ bool enable_simd;
+ bool enable_ref_types;
+ bool enable_aux_stack_check;
+ bool enable_aux_stack_frame;
+ bool disable_llvm_intrinsics;
+ bool disable_llvm_lto;
+ bool enable_stack_estimation;
+ uint32_t opt_level;
+ uint32_t size_level;
+ uint32_t output_format;
+ uint32_t bounds_checks;
+ uint32_t stack_bounds_checks;
+ char **custom_sections;
+ uint32_t custom_sections_count;
+ const char *stack_usage_file;
+} AOTCompOption, *aot_comp_option_t;
+
+bool
+aot_compiler_init(void);
+
+void
+aot_compiler_destroy(void);
+
+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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/lib_export.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/lib_export.h
new file mode 100644
index 000000000..e4829e4fe
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/lib_export.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _LIB_EXPORT_H_
+#define _LIB_EXPORT_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct NativeSymbol {
+ const char *symbol;
+ void *func_ptr;
+ const char *signature;
+ /* attachment which can be retrieved in native API by
+ calling wasm_runtime_get_function_attachment(exec_env) */
+ void *attachment;
+} NativeSymbol;
+
+/* clang-format off */
+#define EXPORT_WASM_API(symbol) \
+ { #symbol, (void *)symbol, NULL, NULL }
+#define EXPORT_WASM_API2(symbol) \
+ { #symbol, (void *)symbol##_wrapper, NULL, NULL }
+
+#define EXPORT_WASM_API_WITH_SIG(symbol, signature) \
+ { #symbol, (void *)symbol, signature, NULL }
+#define EXPORT_WASM_API_WITH_SIG2(symbol, signature) \
+ { #symbol, (void *)symbol##_wrapper, signature, NULL }
+
+#define EXPORT_WASM_API_WITH_ATT(symbol, signature, attachment) \
+ { #symbol, (void *)symbol, signature, attachment }
+#define EXPORT_WASM_API_WITH_ATT2(symbol, signature, attachment) \
+ { #symbol, (void *)symbol##_wrapper, signature, attachment }
+/* clang-format on */
+
+/**
+ * Get the exported APIs of base lib
+ *
+ * @param p_base_lib_apis return the exported API array of base lib
+ *
+ * @return the number of the exported API
+ */
+uint32_t
+get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _LIB_EXPORT_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_c_api.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_c_api.h
new file mode 100644
index 000000000..324a43bd5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_c_api.h
@@ -0,0 +1,814 @@
+// WebAssembly C API
+
+#ifndef _WASM_C_API_H_
+#define _WASM_C_API_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef WASM_API_EXTERN
+#if defined(_MSC_BUILD)
+#if defined(COMPILING_WASM_RUNTIME_API)
+#define WASM_API_EXTERN __declspec(dllexport)
+#else
+#define WASM_API_EXTERN __declspec(dllimport)
+#endif
+#else
+#define WASM_API_EXTERN
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* clang-format off */
+
+///////////////////////////////////////////////////////////////////////////////
+// Auxiliaries
+
+// Machine types
+#if (__STDC_VERSION__) > 199901L
+inline void assertions(void) {
+ static_assert(sizeof(float) == sizeof(uint32_t), "incompatible float type");
+ static_assert(sizeof(double) == sizeof(uint64_t), "incompatible double type");
+ static_assert(sizeof(intptr_t) == sizeof(uint32_t) ||
+ sizeof(intptr_t) == sizeof(uint64_t),
+ "incompatible pointer type");
+}
+#endif
+
+typedef char byte_t;
+typedef float float32_t;
+typedef double float64_t;
+
+
+// Ownership
+
+#define own
+
+// The qualifier `own` is used to indicate ownership of data in this API.
+// It is intended to be interpreted similar to a `const` qualifier:
+//
+// - `own wasm_xxx_t*` owns the pointed-to data
+// - `own wasm_xxx_t` distributes to all fields of a struct or union `xxx`
+// - `own wasm_xxx_vec_t` owns the vector as well as its elements(!)
+// - an `own` function parameter passes ownership from caller to callee
+// - an `own` function result passes ownership from callee to caller
+// - an exception are `own` pointer parameters named `out`, which are copy-back
+// output parameters passing back ownership from callee to caller
+//
+// Own data is created by `wasm_xxx_new` functions and some others.
+// It must be released with the corresponding `wasm_xxx_delete` function.
+//
+// Deleting a reference does not necessarily delete the underlying object,
+// it merely indicates that this owner no longer uses it.
+//
+// For vectors, `const wasm_xxx_vec_t` is used informally to indicate that
+// neither the vector nor its elements should be modified.
+// TODO: introduce proper `wasm_xxx_const_vec_t`?
+
+
+#define WASM_DECLARE_OWN(name) \
+ typedef struct wasm_##name##_t wasm_##name##_t; \
+ \
+ WASM_API_EXTERN void wasm_##name##_delete(own wasm_##name##_t*);
+
+
+// Vectors
+// size: capacity
+// num_elems: current number of elements
+// size_of_elem: size of one elemen
+#define WASM_DECLARE_VEC(name, ptr_or_none) \
+ typedef struct wasm_##name##_vec_t { \
+ size_t size; \
+ wasm_##name##_t ptr_or_none* data; \
+ size_t num_elems; \
+ size_t size_of_elem; \
+ void *lock; \
+ } wasm_##name##_vec_t; \
+ \
+ WASM_API_EXTERN void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t* out); \
+ WASM_API_EXTERN void wasm_##name##_vec_new_uninitialized( \
+ own wasm_##name##_vec_t* out, size_t); \
+ WASM_API_EXTERN void wasm_##name##_vec_new( \
+ own wasm_##name##_vec_t* out, \
+ size_t, own wasm_##name##_t ptr_or_none const[]); \
+ WASM_API_EXTERN void wasm_##name##_vec_copy( \
+ own wasm_##name##_vec_t* out, const wasm_##name##_vec_t*); \
+ WASM_API_EXTERN void wasm_##name##_vec_delete(own wasm_##name##_vec_t*);
+
+
+// Byte vectors
+
+typedef byte_t wasm_byte_t;
+WASM_DECLARE_VEC(byte, )
+
+typedef wasm_byte_vec_t wasm_name_t;
+
+#define wasm_name wasm_byte_vec
+#define wasm_name_new wasm_byte_vec_new
+#define wasm_name_new_empty wasm_byte_vec_new_empty
+#define wasm_name_new_new_uninitialized wasm_byte_vec_new_uninitialized
+#define wasm_name_copy wasm_byte_vec_copy
+#define wasm_name_delete wasm_byte_vec_delete
+
+static inline void wasm_name_new_from_string(
+ own wasm_name_t* out, const char* s
+) {
+ wasm_name_new(out, strlen(s), s);
+}
+
+static inline void wasm_name_new_from_string_nt(
+ own wasm_name_t* out, const char* s
+) {
+ wasm_name_new(out, strlen(s) + 1, s);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Runtime Environment
+
+// Configuration
+
+WASM_DECLARE_OWN(config)
+
+WASM_API_EXTERN own wasm_config_t* wasm_config_new(void);
+
+// Embedders may provide custom functions for manipulating configs.
+
+
+// Engine
+
+WASM_DECLARE_OWN(engine)
+
+/**
+ * Create a new engine
+ *
+ * Note: for the engine new/delete operations, including this,
+ * wasm_engine_new_with_config, wasm_engine_new_with_args, and
+ * wasm_engine_delete, if the platform has mutex initializer,
+ * then they are thread-safe: we use a global lock to lock the
+ * operations of the engine. Otherwise they are not thread-safe:
+ * when there are engine new/delete operations happening
+ * simultaneously in multiple threads, developer must create
+ * the lock by himself, and add the lock when calling these
+ * functions.
+ */
+WASM_API_EXTERN own wasm_engine_t* wasm_engine_new(void);
+WASM_API_EXTERN own wasm_engine_t* wasm_engine_new_with_config(own wasm_config_t*);
+
+#ifndef MEM_ALLOC_OPTION_DEFINED
+#define MEM_ALLOC_OPTION_DEFINED
+/* same definition from wasm_export.h */
+/* Memory allocator type */
+typedef enum {
+ /* pool mode, allocate memory from user defined heap buffer */
+ Alloc_With_Pool = 0,
+ /* user allocator mode, allocate memory from user defined
+ malloc function */
+ Alloc_With_Allocator,
+ /* system allocator mode, allocate memory from system allocator,
+ or, platform's os_malloc function */
+ Alloc_With_System_Allocator,
+} mem_alloc_type_t;
+
+/* Memory allocator option */
+typedef union MemAllocOption {
+ struct {
+ void *heap_buf;
+ uint32_t heap_size;
+ } pool;
+ struct {
+ void *malloc_func;
+ void *realloc_func;
+ void *free_func;
+ /* allocator user data, only used when
+ WASM_MEM_ALLOC_WITH_USER_DATA is defined */
+ void *user_data;
+ } allocator;
+} MemAllocOption;
+#endif
+
+WASM_API_EXTERN own wasm_engine_t *
+wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts);
+
+// Store
+
+WASM_DECLARE_OWN(store)
+
+WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Type Representations
+
+// Type attributes
+
+typedef uint8_t wasm_mutability_t;
+enum wasm_mutability_enum {
+ WASM_CONST,
+ WASM_VAR,
+};
+
+typedef struct wasm_limits_t {
+ uint32_t min;
+ uint32_t max;
+} wasm_limits_t;
+
+static const uint32_t wasm_limits_max_default = 0xffffffff;
+
+
+// Generic
+
+#define WASM_DECLARE_TYPE(name) \
+ WASM_DECLARE_OWN(name) \
+ WASM_DECLARE_VEC(name, *) \
+ \
+ WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t*);
+
+
+// Value Types
+
+WASM_DECLARE_TYPE(valtype)
+
+#ifndef WASM_VALKIND_T_DEFINED
+#define WASM_VALKIND_T_DEFINED
+typedef uint8_t wasm_valkind_t;
+enum wasm_valkind_enum {
+ WASM_I32,
+ WASM_I64,
+ WASM_F32,
+ WASM_F64,
+ WASM_ANYREF = 128,
+ WASM_FUNCREF,
+};
+#endif
+
+WASM_API_EXTERN own wasm_valtype_t* wasm_valtype_new(wasm_valkind_t);
+
+WASM_API_EXTERN wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*);
+
+static inline bool wasm_valkind_is_num(wasm_valkind_t k) {
+ return k < WASM_ANYREF;
+}
+static inline bool wasm_valkind_is_ref(wasm_valkind_t k) {
+ return k >= WASM_ANYREF;
+}
+
+static inline bool wasm_valtype_is_num(const wasm_valtype_t* t) {
+ return wasm_valkind_is_num(wasm_valtype_kind(t));
+}
+static inline bool wasm_valtype_is_ref(const wasm_valtype_t* t) {
+ return wasm_valkind_is_ref(wasm_valtype_kind(t));
+}
+
+
+// Function Types
+
+WASM_DECLARE_TYPE(functype)
+
+WASM_API_EXTERN own wasm_functype_t* wasm_functype_new(
+ own wasm_valtype_vec_t* params, own wasm_valtype_vec_t* results);
+
+WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t*);
+WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t*);
+
+
+// Global Types
+
+WASM_DECLARE_TYPE(globaltype)
+
+WASM_API_EXTERN own wasm_globaltype_t* wasm_globaltype_new(
+ own wasm_valtype_t*, wasm_mutability_t);
+
+WASM_API_EXTERN const wasm_valtype_t* wasm_globaltype_content(const wasm_globaltype_t*);
+WASM_API_EXTERN wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t*);
+
+
+// Table Types
+
+WASM_DECLARE_TYPE(tabletype)
+
+WASM_API_EXTERN own wasm_tabletype_t* wasm_tabletype_new(
+ own wasm_valtype_t*, const wasm_limits_t*);
+
+WASM_API_EXTERN const wasm_valtype_t* wasm_tabletype_element(const wasm_tabletype_t*);
+WASM_API_EXTERN const wasm_limits_t* wasm_tabletype_limits(const wasm_tabletype_t*);
+
+
+// Memory Types
+
+WASM_DECLARE_TYPE(memorytype)
+
+WASM_API_EXTERN own wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t*);
+
+WASM_API_EXTERN const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t*);
+
+
+// Extern Types
+
+WASM_DECLARE_TYPE(externtype)
+
+typedef uint8_t wasm_externkind_t;
+enum wasm_externkind_enum {
+ WASM_EXTERN_FUNC,
+ WASM_EXTERN_GLOBAL,
+ WASM_EXTERN_TABLE,
+ WASM_EXTERN_MEMORY,
+};
+
+WASM_API_EXTERN wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t*);
+
+WASM_API_EXTERN wasm_externtype_t* wasm_functype_as_externtype(wasm_functype_t*);
+WASM_API_EXTERN wasm_externtype_t* wasm_globaltype_as_externtype(wasm_globaltype_t*);
+WASM_API_EXTERN wasm_externtype_t* wasm_tabletype_as_externtype(wasm_tabletype_t*);
+WASM_API_EXTERN wasm_externtype_t* wasm_memorytype_as_externtype(wasm_memorytype_t*);
+
+WASM_API_EXTERN wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t*);
+WASM_API_EXTERN wasm_globaltype_t* wasm_externtype_as_globaltype(wasm_externtype_t*);
+WASM_API_EXTERN wasm_tabletype_t* wasm_externtype_as_tabletype(wasm_externtype_t*);
+WASM_API_EXTERN wasm_memorytype_t* wasm_externtype_as_memorytype(wasm_externtype_t*);
+
+WASM_API_EXTERN const wasm_externtype_t* wasm_functype_as_externtype_const(const wasm_functype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_globaltype_as_externtype_const(const wasm_globaltype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_tabletype_as_externtype_const(const wasm_tabletype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_memorytype_as_externtype_const(const wasm_memorytype_t*);
+
+WASM_API_EXTERN const wasm_functype_t* wasm_externtype_as_functype_const(const wasm_externtype_t*);
+WASM_API_EXTERN const wasm_globaltype_t* wasm_externtype_as_globaltype_const(const wasm_externtype_t*);
+WASM_API_EXTERN const wasm_tabletype_t* wasm_externtype_as_tabletype_const(const wasm_externtype_t*);
+WASM_API_EXTERN const wasm_memorytype_t* wasm_externtype_as_memorytype_const(const wasm_externtype_t*);
+
+
+// Import Types
+
+WASM_DECLARE_TYPE(importtype)
+
+WASM_API_EXTERN own wasm_importtype_t* wasm_importtype_new(
+ own wasm_name_t* module, own wasm_name_t* name, own wasm_externtype_t*);
+
+WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
+WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
+WASM_API_EXTERN bool wasm_importtype_is_linked(const wasm_importtype_t*);
+
+
+// Export Types
+
+WASM_DECLARE_TYPE(exporttype)
+
+WASM_API_EXTERN own wasm_exporttype_t* wasm_exporttype_new(
+ own wasm_name_t*, own wasm_externtype_t*);
+
+WASM_API_EXTERN const wasm_name_t* wasm_exporttype_name(const wasm_exporttype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_exporttype_type(const wasm_exporttype_t*);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Runtime Objects
+
+// Values
+
+#ifndef WASM_VAL_T_DEFINED
+#define WASM_VAL_T_DEFINED
+struct wasm_ref_t;
+
+typedef struct wasm_val_t {
+ wasm_valkind_t kind;
+ union {
+ int32_t i32;
+ int64_t i64;
+ float32_t f32;
+ float64_t f64;
+ struct wasm_ref_t* ref;
+ } of;
+} wasm_val_t;
+#endif
+
+WASM_API_EXTERN void wasm_val_delete(own wasm_val_t* v);
+WASM_API_EXTERN void wasm_val_copy(own wasm_val_t* out, const wasm_val_t*);
+
+WASM_DECLARE_VEC(val, )
+
+
+// References
+
+#define WASM_DECLARE_REF_BASE(name) \
+ WASM_DECLARE_OWN(name) \
+ \
+ WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t*); \
+ WASM_API_EXTERN bool wasm_##name##_same(const wasm_##name##_t*, const wasm_##name##_t*); \
+ \
+ WASM_API_EXTERN void* wasm_##name##_get_host_info(const wasm_##name##_t*); \
+ WASM_API_EXTERN void wasm_##name##_set_host_info(wasm_##name##_t*, void*); \
+ WASM_API_EXTERN void wasm_##name##_set_host_info_with_finalizer( \
+ wasm_##name##_t*, void*, void (*)(void*));
+
+#define WASM_DECLARE_REF(name) \
+ WASM_DECLARE_REF_BASE(name) \
+ \
+ WASM_API_EXTERN wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \
+ WASM_API_EXTERN wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \
+ WASM_API_EXTERN const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t*); \
+ WASM_API_EXTERN const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t*);
+
+#define WASM_DECLARE_SHARABLE_REF(name) \
+ WASM_DECLARE_REF(name) \
+ WASM_DECLARE_OWN(shared_##name) \
+ \
+ WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); \
+ WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*);
+
+
+WASM_DECLARE_REF_BASE(ref)
+
+
+// Frames
+
+WASM_DECLARE_OWN(frame)
+WASM_DECLARE_VEC(frame, *)
+WASM_API_EXTERN own wasm_frame_t* wasm_frame_copy(const wasm_frame_t*);
+
+WASM_API_EXTERN struct wasm_instance_t* wasm_frame_instance(const wasm_frame_t*);
+WASM_API_EXTERN uint32_t wasm_frame_func_index(const wasm_frame_t*);
+WASM_API_EXTERN size_t wasm_frame_func_offset(const wasm_frame_t*);
+WASM_API_EXTERN size_t wasm_frame_module_offset(const wasm_frame_t*);
+
+
+// Traps
+
+typedef wasm_name_t wasm_message_t; // null terminated
+
+WASM_DECLARE_REF(trap)
+
+WASM_API_EXTERN own wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t*);
+
+WASM_API_EXTERN void wasm_trap_message(const wasm_trap_t*, own wasm_message_t* out);
+WASM_API_EXTERN own wasm_frame_t* wasm_trap_origin(const wasm_trap_t*);
+WASM_API_EXTERN void wasm_trap_trace(const wasm_trap_t*, own wasm_frame_vec_t* out);
+
+
+// Foreign Objects
+
+WASM_DECLARE_REF(foreign)
+
+WASM_API_EXTERN own wasm_foreign_t* wasm_foreign_new(wasm_store_t*);
+
+
+// Modules
+// WASM_DECLARE_SHARABLE_REF(module)
+
+#ifndef WASM_MODULE_T_DEFINED
+#define WASM_MODULE_T_DEFINED
+struct WASMModuleCommon;
+typedef struct WASMModuleCommon *wasm_module_t;
+#endif
+
+
+WASM_API_EXTERN own wasm_module_t* wasm_module_new(
+ wasm_store_t*, const wasm_byte_vec_t* binary);
+
+WASM_API_EXTERN void wasm_module_delete(own wasm_module_t*);
+
+WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);
+
+WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
+WASM_API_EXTERN void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out);
+
+WASM_API_EXTERN void wasm_module_serialize(wasm_module_t*, own wasm_byte_vec_t* out);
+WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
+
+typedef wasm_module_t wasm_shared_module_t;
+WASM_API_EXTERN own wasm_shared_module_t* wasm_module_share(wasm_module_t*);
+WASM_API_EXTERN own wasm_module_t* wasm_module_obtain(wasm_store_t*, wasm_shared_module_t*);
+WASM_API_EXTERN void wasm_shared_module_delete(own wasm_shared_module_t*);
+
+
+// Function Instances
+
+WASM_DECLARE_REF(func)
+
+typedef own wasm_trap_t* (*wasm_func_callback_t)(
+ const wasm_val_vec_t* args, own wasm_val_vec_t *results);
+typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)(
+ void* env, const wasm_val_vec_t *args, wasm_val_vec_t *results);
+
+WASM_API_EXTERN own wasm_func_t* wasm_func_new(
+ wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t);
+WASM_API_EXTERN own wasm_func_t* wasm_func_new_with_env(
+ wasm_store_t*, const wasm_functype_t* type, wasm_func_callback_with_env_t,
+ void* env, void (*finalizer)(void*));
+
+WASM_API_EXTERN own wasm_functype_t* wasm_func_type(const wasm_func_t*);
+WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*);
+WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*);
+
+WASM_API_EXTERN own wasm_trap_t* wasm_func_call(
+ const wasm_func_t*, const wasm_val_vec_t* args, wasm_val_vec_t* results);
+
+
+// Global Instances
+
+WASM_DECLARE_REF(global)
+
+WASM_API_EXTERN own wasm_global_t* wasm_global_new(
+ wasm_store_t*, const wasm_globaltype_t*, const wasm_val_t*);
+
+WASM_API_EXTERN own wasm_globaltype_t* wasm_global_type(const wasm_global_t*);
+
+WASM_API_EXTERN void wasm_global_get(const wasm_global_t*, own wasm_val_t* out);
+WASM_API_EXTERN void wasm_global_set(wasm_global_t*, const wasm_val_t*);
+
+
+// Table Instances
+
+WASM_DECLARE_REF(table)
+
+typedef uint32_t wasm_table_size_t;
+
+WASM_API_EXTERN own wasm_table_t* wasm_table_new(
+ wasm_store_t*, const wasm_tabletype_t*, wasm_ref_t* init);
+
+WASM_API_EXTERN own wasm_tabletype_t* wasm_table_type(const wasm_table_t*);
+
+WASM_API_EXTERN own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index);
+WASM_API_EXTERN bool wasm_table_set(wasm_table_t*, wasm_table_size_t index, wasm_ref_t*);
+
+WASM_API_EXTERN wasm_table_size_t wasm_table_size(const wasm_table_t*);
+WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init);
+
+
+// Memory Instances
+
+WASM_DECLARE_REF(memory)
+
+typedef uint32_t wasm_memory_pages_t;
+
+static const size_t MEMORY_PAGE_SIZE = 0x10000;
+
+WASM_API_EXTERN own wasm_memory_t* wasm_memory_new(wasm_store_t*, const wasm_memorytype_t*);
+
+WASM_API_EXTERN own wasm_memorytype_t* wasm_memory_type(const wasm_memory_t*);
+
+WASM_API_EXTERN byte_t* wasm_memory_data(wasm_memory_t*);
+WASM_API_EXTERN size_t wasm_memory_data_size(const wasm_memory_t*);
+
+WASM_API_EXTERN wasm_memory_pages_t wasm_memory_size(const wasm_memory_t*);
+WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
+
+
+// Externals
+
+WASM_DECLARE_REF(extern)
+WASM_DECLARE_VEC(extern, *)
+
+WASM_API_EXTERN wasm_externkind_t wasm_extern_kind(const wasm_extern_t*);
+WASM_API_EXTERN own wasm_externtype_t* wasm_extern_type(const wasm_extern_t*);
+
+WASM_API_EXTERN wasm_extern_t* wasm_func_as_extern(wasm_func_t*);
+WASM_API_EXTERN wasm_extern_t* wasm_global_as_extern(wasm_global_t*);
+WASM_API_EXTERN wasm_extern_t* wasm_table_as_extern(wasm_table_t*);
+WASM_API_EXTERN wasm_extern_t* wasm_memory_as_extern(wasm_memory_t*);
+
+WASM_API_EXTERN wasm_func_t* wasm_extern_as_func(wasm_extern_t*);
+WASM_API_EXTERN wasm_global_t* wasm_extern_as_global(wasm_extern_t*);
+WASM_API_EXTERN wasm_table_t* wasm_extern_as_table(wasm_extern_t*);
+WASM_API_EXTERN wasm_memory_t* wasm_extern_as_memory(wasm_extern_t*);
+
+WASM_API_EXTERN const wasm_extern_t* wasm_func_as_extern_const(const wasm_func_t*);
+WASM_API_EXTERN const wasm_extern_t* wasm_global_as_extern_const(const wasm_global_t*);
+WASM_API_EXTERN const wasm_extern_t* wasm_table_as_extern_const(const wasm_table_t*);
+WASM_API_EXTERN const wasm_extern_t* wasm_memory_as_extern_const(const wasm_memory_t*);
+
+WASM_API_EXTERN const wasm_func_t* wasm_extern_as_func_const(const wasm_extern_t*);
+WASM_API_EXTERN const wasm_global_t* wasm_extern_as_global_const(const wasm_extern_t*);
+WASM_API_EXTERN const wasm_table_t* wasm_extern_as_table_const(const wasm_extern_t*);
+WASM_API_EXTERN const wasm_memory_t* wasm_extern_as_memory_const(const wasm_extern_t*);
+
+
+// Module Instances
+
+WASM_DECLARE_REF(instance)
+
+WASM_API_EXTERN own wasm_instance_t* wasm_instance_new(
+ wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t *imports,
+ own wasm_trap_t** trap
+);
+
+// please refer to wasm_runtime_instantiate(...) in core/iwasm/include/wasm_export.h
+WASM_API_EXTERN own wasm_instance_t* wasm_instance_new_with_args(
+ wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t *imports,
+ own wasm_trap_t** trap, const uint32_t stack_size, const uint32_t heap_size
+);
+
+WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Convenience
+
+// Vectors
+
+#define WASM_EMPTY_VEC {0, NULL, 0, 0, NULL}
+#define WASM_ARRAY_VEC(array) {sizeof(array)/sizeof(*(array)), array, sizeof(array)/sizeof(*(array)), sizeof(*(array)), NULL}
+
+
+// Value Type construction short-hands
+
+static inline own wasm_valtype_t* wasm_valtype_new_i32(void) {
+ return wasm_valtype_new(WASM_I32);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_i64(void) {
+ return wasm_valtype_new(WASM_I64);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_f32(void) {
+ return wasm_valtype_new(WASM_F32);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_f64(void) {
+ return wasm_valtype_new(WASM_F64);
+}
+
+static inline own wasm_valtype_t* wasm_valtype_new_anyref(void) {
+ return wasm_valtype_new(WASM_ANYREF);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_funcref(void) {
+ return wasm_valtype_new(WASM_FUNCREF);
+}
+
+
+// Function Types construction short-hands
+
+static inline own wasm_functype_t* wasm_functype_new_0_0(void) {
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new_empty(&params);
+ wasm_valtype_vec_new_empty(&results);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_1_0(
+ own wasm_valtype_t* p
+) {
+ wasm_valtype_t* ps[1] = {p};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 1, ps);
+ wasm_valtype_vec_new_empty(&results);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_2_0(
+ own wasm_valtype_t* p1, own wasm_valtype_t* p2
+) {
+ wasm_valtype_t* ps[2] = {p1, p2};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 2, ps);
+ wasm_valtype_vec_new_empty(&results);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_3_0(
+ own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3
+) {
+ wasm_valtype_t* ps[3] = {p1, p2, p3};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 3, ps);
+ wasm_valtype_vec_new_empty(&results);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_0_1(
+ own wasm_valtype_t* r
+) {
+ wasm_valtype_t* rs[1] = {r};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new_empty(&params);
+ wasm_valtype_vec_new(&results, 1, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_1_1(
+ own wasm_valtype_t* p, own wasm_valtype_t* r
+) {
+ wasm_valtype_t* ps[1] = {p};
+ wasm_valtype_t* rs[1] = {r};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 1, ps);
+ wasm_valtype_vec_new(&results, 1, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_2_1(
+ own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* r
+) {
+ wasm_valtype_t* ps[2] = {p1, p2};
+ wasm_valtype_t* rs[1] = {r};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 2, ps);
+ wasm_valtype_vec_new(&results, 1, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_3_1(
+ own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
+ own wasm_valtype_t* r
+) {
+ wasm_valtype_t* ps[3] = {p1, p2, p3};
+ wasm_valtype_t* rs[1] = {r};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 3, ps);
+ wasm_valtype_vec_new(&results, 1, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_0_2(
+ own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+ wasm_valtype_t* rs[2] = {r1, r2};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new_empty(&params);
+ wasm_valtype_vec_new(&results, 2, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_1_2(
+ own wasm_valtype_t* p, own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+ wasm_valtype_t* ps[1] = {p};
+ wasm_valtype_t* rs[2] = {r1, r2};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 1, ps);
+ wasm_valtype_vec_new(&results, 2, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_2_2(
+ own wasm_valtype_t* p1, own wasm_valtype_t* p2,
+ own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+ wasm_valtype_t* ps[2] = {p1, p2};
+ wasm_valtype_t* rs[2] = {r1, r2};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 2, ps);
+ wasm_valtype_vec_new(&results, 2, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_3_2(
+ own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
+ own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+ wasm_valtype_t* ps[3] = {p1, p2, p3};
+ wasm_valtype_t* rs[2] = {r1, r2};
+ wasm_valtype_vec_t params, results;
+ wasm_valtype_vec_new(&params, 3, ps);
+ wasm_valtype_vec_new(&results, 2, rs);
+ return wasm_functype_new(&params, &results);
+}
+
+
+// Value construction short-hands
+
+static inline void wasm_val_init_ptr(own wasm_val_t* out, void* p) {
+#if UINTPTR_MAX == UINT32_MAX
+ out->kind = WASM_I32;
+ out->of.i32 = (intptr_t)p;
+#elif UINTPTR_MAX == UINT64_MAX
+ out->kind = WASM_I64;
+ out->of.i64 = (intptr_t)p;
+#endif
+}
+
+static inline void* wasm_val_ptr(const wasm_val_t* val) {
+#if UINTPTR_MAX == UINT32_MAX
+ return (void*)(intptr_t)val->of.i32;
+#elif UINTPTR_MAX == UINT64_MAX
+ return (void*)(intptr_t)val->of.i64;
+#endif
+}
+
+#define WASM_I32_VAL(i) {.kind = WASM_I32, .of = {.i32 = i}}
+#define WASM_I64_VAL(i) {.kind = WASM_I64, .of = {.i64 = i}}
+#define WASM_F32_VAL(z) {.kind = WASM_F32, .of = {.f32 = z}}
+#define WASM_F64_VAL(z) {.kind = WASM_F64, .of = {.f64 = z}}
+#define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .of = {.ref = r}}
+#define WASM_INIT_VAL {.kind = WASM_ANYREF, .of = {.ref = NULL}}
+
+#define KILOBYTE(n) ((n) * 1024)
+
+// Create placeholders filled in `wasm_externvec_t* imports` for `wasm_instance_new()`
+WASM_API_EXTERN wasm_extern_t *wasm_extern_new_empty(wasm_store_t *, wasm_externkind_t);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#undef own
+
+/* clang-format on */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // #ifdef _WASM_C_API_H_
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_export.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_export.h
new file mode 100644
index 000000000..f6c0107b9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/include/wasm_export.h
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_EXPORT_H
+#define _WASM_EXPORT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "lib_export.h"
+
+#ifndef WASM_RUNTIME_API_EXTERN
+#if defined(_MSC_BUILD)
+#if defined(COMPILING_WASM_RUNTIME_API)
+#define WASM_RUNTIME_API_EXTERN __declspec(dllexport)
+#else
+#define WASM_RUNTIME_API_EXTERN __declspec(dllimport)
+#endif
+#else
+#define WASM_RUNTIME_API_EXTERN
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* clang-format off */
+
+#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)
+
+#define validate_app_str_addr(offset) \
+ wasm_runtime_validate_app_str_addr(module_inst, offset)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+
+#define module_malloc(size, p_native_addr) \
+ wasm_runtime_module_malloc(module_inst, size, p_native_addr)
+
+#define module_free(offset) \
+ wasm_runtime_module_free(module_inst, offset)
+
+#define native_raw_return_type(type, args) type *raw_ret = (type *)(args)
+
+#define native_raw_get_arg(type, name, args) type name = *((type *)(args++))
+
+#define native_raw_set_return(val) *raw_ret = (val)
+
+#ifndef WASM_MODULE_T_DEFINED
+#define WASM_MODULE_T_DEFINED
+/* Uninstantiated WASM module loaded from WASM binary file
+ or AoT binary file*/
+struct WASMModuleCommon;
+typedef struct WASMModuleCommon *wasm_module_t;
+#endif
+
+/* Instantiated WASM module */
+struct WASMModuleInstanceCommon;
+typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
+
+/* Function instance */
+typedef void WASMFunctionInstanceCommon;
+typedef WASMFunctionInstanceCommon *wasm_function_inst_t;
+
+/* WASM section */
+typedef struct wasm_section_t {
+ struct wasm_section_t *next;
+ /* section type */
+ int section_type;
+ /* section body, not include type and size */
+ uint8_t *section_body;
+ /* section body size */
+ uint32_t section_body_size;
+} wasm_section_t, aot_section_t, *wasm_section_list_t, *aot_section_list_t;
+
+/* Execution environment, e.g. stack info */
+struct WASMExecEnv;
+typedef struct WASMExecEnv *wasm_exec_env_t;
+
+/* Package Type */
+typedef enum {
+ Wasm_Module_Bytecode = 0,
+ Wasm_Module_AoT,
+ Package_Type_Unknown = 0xFFFF
+} package_type_t;
+
+#ifndef MEM_ALLOC_OPTION_DEFINED
+#define MEM_ALLOC_OPTION_DEFINED
+/* Memory allocator type */
+typedef enum {
+ /* pool mode, allocate memory from user defined heap buffer */
+ Alloc_With_Pool = 0,
+ /* user allocator mode, allocate memory from user defined
+ malloc function */
+ Alloc_With_Allocator,
+ /* system allocator mode, allocate memory from system allocator,
+ or, platform's os_malloc function */
+ Alloc_With_System_Allocator,
+} mem_alloc_type_t;
+
+/* Memory allocator option */
+typedef union MemAllocOption {
+ struct {
+ void *heap_buf;
+ uint32_t heap_size;
+ } pool;
+ struct {
+ void *malloc_func;
+ void *realloc_func;
+ void *free_func;
+ /* allocator user data, only used when
+ WASM_MEM_ALLOC_WITH_USER_DATA is defined */
+ void *user_data;
+ } allocator;
+} MemAllocOption;
+#endif
+
+/* Memory pool info */
+typedef struct mem_alloc_info_t {
+ uint32_t total_size;
+ uint32_t total_free_size;
+ uint32_t highmark_size;
+} mem_alloc_info_t;
+
+/* Running mode of runtime and module instance*/
+typedef enum RunningMode {
+ Mode_Interp = 1,
+ Mode_Fast_JIT,
+ Mode_LLVM_JIT,
+ Mode_Multi_Tier_JIT,
+} RunningMode;
+
+/* WASM runtime initialize arguments */
+typedef struct RuntimeInitArgs {
+ mem_alloc_type_t mem_alloc_type;
+ MemAllocOption mem_alloc_option;
+
+ const char *native_module_name;
+ NativeSymbol *native_symbols;
+ uint32_t n_native_symbols;
+
+ /* maximum thread number, only used when
+ WASM_ENABLE_THREAD_MGR is defined */
+ uint32_t max_thread_num;
+
+ /* Debug settings, only used when
+ WASM_ENABLE_DEBUG_INTERP != 0 */
+ char ip_addr[128];
+ int unused; /* was platform_port */
+ int instance_port;
+
+ /* Fast JIT code cache size */
+ uint32_t fast_jit_code_cache_size;
+
+ /* Default running mode of the runtime */
+ RunningMode running_mode;
+
+ /* LLVM JIT opt and size level */
+ uint32_t llvm_jit_opt_level;
+ uint32_t llvm_jit_size_level;
+} RuntimeInitArgs;
+
+#ifndef WASM_VALKIND_T_DEFINED
+#define WASM_VALKIND_T_DEFINED
+typedef uint8_t wasm_valkind_t;
+enum wasm_valkind_enum {
+ WASM_I32,
+ WASM_I64,
+ WASM_F32,
+ WASM_F64,
+ WASM_ANYREF = 128,
+ WASM_FUNCREF,
+};
+#endif
+
+#ifndef WASM_VAL_T_DEFINED
+#define WASM_VAL_T_DEFINED
+
+typedef struct wasm_val_t {
+ wasm_valkind_t kind;
+ union {
+ /* also represent a function index */
+ int32_t i32;
+ int64_t i64;
+ float f32;
+ double f64;
+ /* represent a foreign object, aka externref in .wat */
+ uintptr_t foreign;
+ } of;
+} wasm_val_t;
+#endif
+
+/**
+ * Initialize the WASM runtime environment, and also initialize
+ * the memory allocator with system allocator, which calls os_malloc
+ * to allocate memory
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_init(void);
+
+/**
+ * Initialize the WASM runtime environment, WASM running mode,
+ * and also initialize the memory allocator and register native symbols,
+ * which are specified with init arguments
+ *
+ * @param init_args specifies the init arguments
+ *
+ * @return return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_full_init(RuntimeInitArgs *init_args);
+
+/**
+ * Query whether a certain running mode is supported for the runtime
+ *
+ * @param running_mode the running mode to query
+ *
+ * @return true if this running mode is supported, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_running_mode_supported(RunningMode running_mode);
+
+/**
+ * Set the default running mode for the runtime. It is inherited
+ * to set the running mode of a module instance when it is instantiated,
+ * and can be changed by calling wasm_runtime_set_running_mode
+ *
+ * @param running_mode the running mode to set
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_default_running_mode(RunningMode running_mode);
+
+/**
+ * Destroy the WASM runtime environment.
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy(void);
+
+/**
+ * Allocate memory from runtime memory environment.
+ *
+ * @param size bytes need to allocate
+ *
+ * @return the pointer to memory allocated
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_malloc(unsigned int size);
+
+/**
+ * Reallocate memory from runtime memory environment
+ *
+ * @param ptr the original memory
+ * @param size bytes need to reallocate
+ *
+ * @return the pointer to memory reallocated
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_realloc(void *ptr, unsigned int size);
+
+/*
+ * Free memory to runtime memory environment.
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_free(void *ptr);
+
+/*
+ * Get memory info, only pool mode is supported now.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info);
+
+/**
+ * Get the package type of a buffer.
+ *
+ * @param buf the package buffer
+ * @param size the package buffer size
+ *
+ * @return the package type, return Package_Type_Unknown if the type is unknown
+ */
+WASM_RUNTIME_API_EXTERN package_type_t
+get_package_type(const uint8_t *buf, uint32_t size);
+
+/**
+ * Check whether a file is an AOT XIP (Execution In Place) file
+ *
+ * @param buf the package buffer
+ * @param size the package buffer size
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_xip_file(const uint8_t *buf, uint32_t size);
+
+/**
+ * Callback to load a module file into a buffer in multi-module feature
+ */
+typedef bool (*module_reader)(const char *module_name,
+ uint8_t **p_buffer, uint32_t *p_size);
+
+/**
+ * Callback to release the buffer loaded by module_reader callback
+ */
+typedef void (*module_destroyer)(uint8_t *buffer, uint32_t size);
+
+/**
+ * Setup callbacks for reading and releasing a buffer about a module file
+ *
+ * @param reader a callback to read a module file into a buffer
+ * @param destroyer a callback to release above buffer
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_module_reader(const module_reader reader,
+ const module_destroyer destroyer);
+/**
+ * Give the "module" a name "module_name".
+ * Can not assign a new name to a module if it already has a name
+ *
+ * @param module_name indicate a name
+ * @param module the target module
+ * @param error_buf output of the exception info
+ * @param error_buf_size the size of the exception string
+ *
+ * @return true means success, false means failed
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_register_module(const char *module_name, wasm_module_t module,
+ char *error_buf, uint32_t error_buf_size);
+
+/**
+ * Check if there is already a loaded module named module_name in the
+ * runtime. Repeately loading a module with the same name is not allowed.
+ *
+ * @param module_name indicate a name
+ *
+ * @return return WASM module loaded, NULL if failed
+ */
+WASM_RUNTIME_API_EXTERN wasm_module_t
+wasm_runtime_find_module_registered(const char *module_name);
+
+/**
+ * Load a WASM module from a specified byte buffer. The byte buffer can be
+ * WASM binary data when interpreter or JIT is enabled, or AOT binary data
+ * when AOT is enabled. If it is AOT binary data, it must be 4-byte aligned.
+ *
+ * Note: In case of AOT XIP modules, the runtime doesn't make modifications
+ * to the buffer. (Except the "Known issues" mentioned in doc/xip.md.)
+ * Otherwise, the runtime can make modifications to the buffer for its
+ * internal purposes. Thus, in general, it isn't safe to create multiple
+ * modules from a single buffer.
+ *
+ * @param buf the byte buffer which contains the WASM/AOT binary data,
+ * note that the byte buffer must be writable since runtime may
+ * change its content for footprint and performance purpose, and
+ * it must be referencable until wasm_runtime_unload is called
+ * @param size the size of the buffer
+ * @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_RUNTIME_API_EXTERN wasm_module_t
+wasm_runtime_load(uint8_t *buf, uint32_t size,
+ char *error_buf, uint32_t error_buf_size);
+
+/**
+ * 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_RUNTIME_API_EXTERN wasm_module_t
+wasm_runtime_load_from_sections(wasm_section_list_t section_list, bool is_aot,
+ char *error_buf, uint32_t error_buf_size);
+
+/**
+ * Unload a WASM module.
+ *
+ * @param module the module to be unloaded
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_unload(wasm_module_t module);
+
+/**
+ * Get the module hash of a WASM module, currently only available on
+ * linux-sgx platform when the remote attestation feature is enabled
+ *
+ * @param module the WASM module to retrieve
+ *
+ * @return the module hash of the WASM module
+ */
+char *
+wasm_runtime_get_module_hash(wasm_module_t module);
+
+/**
+ * Set WASI parameters.
+ *
+ * While this API operates on a module, these parameters will be used
+ * only when the module is instantiated. That is, you can consider these
+ * as extra parameters for wasm_runtime_instantiate().
+ *
+ * @param module The module to set WASI parameters.
+ * @param dir_list The list of directories to preopen. (real path)
+ * @param dir_count The number of elements in dir_list.
+ * @param map_dir_list The list of directories to preopen. (mapped path)
+ * @param map_dir_count The number of elements in map_dir_list.
+ * If map_dir_count is smaller than dir_count,
+ * mapped path is assumed to be same as the
+ * corresponding real path for the rest of entries.
+ * @param env The list of environment variables.
+ * @param env_count The number of elements in env.
+ * @param argv The list of command line arguments.
+ * @param argc The number of elements in argv.
+ * @param stdinfd The host file descriptor to back WASI STDIN_FILENO.
+ * If -1 is specified, STDIN_FILENO is used.
+ * @param stdoutfd The host file descriptor to back WASI STDOUT_FILENO.
+ * If -1 is specified, STDOUT_FILENO is used.
+ * @param stderrfd The host file descriptor to back WASI STDERR_FILENO.
+ * If -1 is specified, STDERR_FILENO is used.
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_args_ex(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,
+ int stdinfd, int stdoutfd, int stderrfd);
+
+/**
+ * Set WASI parameters.
+ *
+ * Same as wasm_runtime_set_wasi_args_ex with stdinfd = -1, stdoutfd = -1,
+ * stderrfd = -1.
+ */
+WASM_RUNTIME_API_EXTERN 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);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_addr_pool(wasm_module_t module, const char *addr_pool[],
+ uint32_t addr_pool_size);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_ns_lookup_pool(wasm_module_t module, const char *ns_lookup_pool[],
+ uint32_t ns_lookup_pool_size);
+
+/**
+ * Instantiate a WASM module.
+ *
+ * @param module the WASM module to instantiate
+ * @param default_stack_size the default stack size of the module instance when the
+ * exec env's operation stack isn't created by user, e.g. API
+ * wasm_application_execute_main() and wasm_application_execute_func()
+ * create the operation stack internally with the stack size specified
+ * here. And API wasm_runtime_create_exec_env() creates the operation
+ * stack with stack size specified by its parameter, the stack size
+ * specified here is ignored.
+ * @param host_managed_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.
+ * @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 WASM module instance, NULL if failed
+ */
+WASM_RUNTIME_API_EXTERN wasm_module_inst_t
+wasm_runtime_instantiate(const wasm_module_t module,
+ uint32_t default_stack_size, uint32_t host_managed_heap_size,
+ char *error_buf, uint32_t error_buf_size);
+
+/**
+ * Set the running mode of a WASM module instance, override the
+ * default running mode of the runtime. Note that it only makes sense when
+ * the input is a wasm bytecode file: for the AOT file, runtime always runs
+ * it with AOT engine, and this function always returns true.
+ *
+ * @param module_inst the WASM module instance to set running mode
+ * @param running_mode the running mode to set
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
+ RunningMode running_mode);
+
+/**
+ * Get the running mode of a WASM module instance, if no running mode
+ * is explicitly set the default running mode of runtime will
+ * be used and returned. Note that it only makes sense when the input is a
+ * wasm bytecode file: for the AOT file, this function always returns 0.
+ *
+ * @param module_inst the WASM module instance to query for running mode
+ *
+ * @return the running mode this module instance currently use
+ */
+WASM_RUNTIME_API_EXTERN RunningMode
+wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
+
+/**
+ * Deinstantiate a WASM module instance, destroy the resources.
+ *
+ * @param module_inst the WASM module instance to destroy
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_deinstantiate(wasm_module_inst_t module_inst);
+
+/**
+ * Get WASM module from WASM module instance
+ *
+ * @param module_inst the WASM module instance to retrieve
+ *
+ * @return the WASM module
+ */
+WASM_RUNTIME_API_EXTERN wasm_module_t
+wasm_runtime_get_module(wasm_module_inst_t module_inst);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_wasi_mode(wasm_module_inst_t module_inst);
+
+WASM_RUNTIME_API_EXTERN wasm_function_inst_t
+wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst);
+
+/**
+ * Get WASI exit code.
+ *
+ * After a WASI command completed its execution, an embedder can
+ * call this function to get its exit code. (that is, the value given
+ * to proc_exit.)
+ *
+ * @param module_inst the module instance
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_get_wasi_exit_code(wasm_module_inst_t module_inst);
+
+/**
+ * Lookup an exported function in the WASM module instance.
+ *
+ * @param module_inst the module instance
+ * @param name the name of the function
+ * @param signature the signature of the function, ignored currently
+ *
+ * @return the function instance found, NULL if not found
+ */
+WASM_RUNTIME_API_EXTERN wasm_function_inst_t
+wasm_runtime_lookup_function(wasm_module_inst_t const module_inst,
+ const char *name, const char *signature);
+
+/**
+ * Get parameter count of the function instance
+ *
+ * @param func_inst the function instance
+ * @param module_inst the module instance the function instance belongs to
+ *
+ * @return the parameter count of the function instance
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_func_get_param_count(wasm_function_inst_t const func_inst,
+ wasm_module_inst_t const module_inst);
+
+/**
+ * Get result count of the function instance
+ *
+ * @param func_inst the function instance
+ * @param module_inst the module instance the function instance belongs to
+ *
+ * @return the result count of the function instance
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_func_get_result_count(wasm_function_inst_t const func_inst,
+ wasm_module_inst_t const module_inst);
+
+/**
+ * Get parameter types of the function instance
+ *
+ * @param func_inst the function instance
+ * @param module_inst the module instance the function instance belongs to
+ * @param param_types the parameter types returned
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_func_get_param_types(wasm_function_inst_t const func_inst,
+ wasm_module_inst_t const module_inst,
+ wasm_valkind_t *param_types);
+
+/**
+ * Get result types of the function instance
+ *
+ * @param func_inst the function instance
+ * @param module_inst the module instance the function instance belongs to
+ * @param result_types the result types returned
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_func_get_result_types(wasm_function_inst_t const func_inst,
+ wasm_module_inst_t const module_inst,
+ wasm_valkind_t *result_types);
+
+/**
+ * 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, NULL if failed, e.g. invalid
+ * stack size is passed
+ */
+WASM_RUNTIME_API_EXTERN wasm_exec_env_t
+wasm_runtime_create_exec_env(wasm_module_inst_t module_inst,
+ uint32_t stack_size);
+
+/**
+ * Destroy the execution environment.
+ *
+ * @param exec_env the execution environment to destroy
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
+
+/**
+ * Get the singleton execution environment for the instance.
+ *
+ * Note: The singleton execution environment is the execution
+ * environment used internally by the runtime for the API functions
+ * like wasm_application_execute_main, which don't take explicit
+ * execution environment. It's associated to the corresponding
+ * module instance and managed by the runtime. The API user should
+ * not destroy it with wasm_runtime_destroy_exec_env.
+ *
+ * @param module_inst the module instance
+ *
+ * @return exec_env the execution environment to destroy
+ */
+WASM_RUNTIME_API_EXTERN wasm_exec_env_t
+wasm_runtime_get_exec_env_singleton(wasm_module_inst_t module_inst);
+
+/**
+ * Start debug instance based on given execution environment.
+ * Note:
+ * The debug instance will be destroyed during destroying the
+ * execution environment, developers don't need to destroy it
+ * manually.
+ * If the cluster of this execution environment has already
+ * been bound to a debug instance, this function will return true
+ * directly.
+ * If developer spawns some exec_env by wasm_runtime_spawn_exec_env,
+ * don't need to call this function for every spawned exec_env as
+ * they are sharing the same cluster with the main exec_env.
+ *
+ * @param exec_env the execution environment to start debug instance
+ * @param port the port for the debug server to listen on.
+ * 0 means automatic assignment.
+ * -1 means to use the global setting in RuntimeInitArgs.
+ *
+ * @return debug port if success, 0 otherwise.
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_start_debug_instance_with_port(wasm_exec_env_t exec_env, int32_t port);
+
+/**
+ * Same as wasm_runtime_start_debug_instance_with_port(env, -1).
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_start_debug_instance(wasm_exec_env_t exec_env);
+
+/**
+ * Initialize the thread environment.
+ * Note:
+ * If developer creates a child thread by himself to call the
+ * the wasm function in that thread, he should call this API
+ * firstly before calling the wasm function and then call
+ * wasm_runtime_destroy_thread_env() after calling the wasm
+ * function. If the thread is created from the runtime API,
+ * it is unnecessary to call these two APIs.
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_init_thread_env(void);
+
+/**
+ * Destroy the thread environment
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_thread_env(void);
+
+/**
+ * Whether the thread environment is initialized
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_thread_env_inited(void);
+
+/**
+ * Get WASM module instance from execution environment
+ *
+ * @param exec_env the execution environment to retrieve
+ *
+ * @return the WASM module instance
+ */
+WASM_RUNTIME_API_EXTERN wasm_module_inst_t
+wasm_runtime_get_module_inst(wasm_exec_env_t exec_env);
+
+/**
+ * Set WASM module instance of execution environment
+ * Caution:
+ * normally the module instance is bound with the execution
+ * environment one by one, if multiple module instances want
+ * to share to the same execution environment, developer should
+ * be responsible for the backup and restore of module instance
+ *
+ * @param exec_env the execution environment
+ * @param module_inst the WASM module instance to set
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_module_inst(wasm_exec_env_t exec_env,
+ const wasm_module_inst_t module_inst);
+
+/**
+ * Call the given WASM function of a WASM module instance with
+ * arguments (bytecode and AoT).
+ *
+ * @param exec_env the execution environment to call the function,
+ * which must be created from wasm_create_exec_env()
+ * @param function the function to call
+ * @param argc total cell number that the function parameters occupy,
+ * a cell is a slot of the uint32 array argv[], e.g. i32/f32 argument
+ * occupies one cell, i64/f64 argument occupies two cells, note that
+ * it might be different from the parameter number of the function
+ * @param argv the arguments. If the function 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 the exception
+ * info.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm(wasm_exec_env_t exec_env,
+ wasm_function_inst_t function,
+ uint32_t argc, uint32_t argv[]);
+
+/**
+ * Call the given WASM function of a WASM module instance with
+ * provided results space and arguments (bytecode and AoT).
+ *
+ * @param exec_env the execution environment to call the function,
+ * which must be created from wasm_create_exec_env()
+ * @param function the function to call
+ * @param num_results the number of results
+ * @param results the pre-alloced pointer to get the results
+ * @param num_args the number of arguments
+ * @param args the arguments
+ *
+ * @return true if success, false otherwise and exception will be thrown,
+ * the caller can call wasm_runtime_get_exception to get the exception
+ * info.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm_a(wasm_exec_env_t exec_env,
+ wasm_function_inst_t function,
+ uint32_t num_results, wasm_val_t results[],
+ uint32_t num_args, wasm_val_t *args);
+
+/**
+ * Call the given WASM function of a WASM module instance with
+ * provided results space and variant arguments (bytecode and AoT).
+ *
+ * @param exec_env the execution environment to call the function,
+ * which must be created from wasm_create_exec_env()
+ * @param function the function to call
+ * @param num_results the number of results
+ * @param results the pre-alloced pointer to get the results
+ * @param num_args the number of arguments
+ * @param ... the variant arguments
+ *
+ * @return true if success, false otherwise and exception will be thrown,
+ * the caller can call wasm_runtime_get_exception to get the exception
+ * info.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm_v(wasm_exec_env_t exec_env,
+ wasm_function_inst_t function,
+ uint32_t num_results, wasm_val_t results[],
+ uint32_t num_args, ...);
+
+/**
+ * Call a function reference of a given WASM runtime instance with
+ * arguments.
+ *
+ * Note: this can be used to call a function which is not exported
+ * by the module explicitly. You might consider it as an abstraction
+ * violation.
+ *
+ * @param exec_env the execution environment to call the function
+ * which must be created from wasm_create_exec_env()
+ * @param element_index the function reference index, usually
+ * prvovided by the caller of a registed native function
+ * @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.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_indirect(wasm_exec_env_t exec_env, uint32_t element_index,
+ 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, if the main function has return value,
+ * *(int*)argv stores the return value of the called main function after
+ * this function returns.
+ *
+ * @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
+ * the exception info.
+ */
+WASM_RUNTIME_API_EXTERN 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.
+ * to indicate the module name via: $module_name$function_name
+ * or just a function name: function_name
+ * @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 the exception info.
+ */
+WASM_RUNTIME_API_EXTERN 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.
+ *
+ * @param module_inst the WASM module instance
+ *
+ * @return the exception string
+ */
+WASM_RUNTIME_API_EXTERN const char *
+wasm_runtime_get_exception(wasm_module_inst_t module_inst);
+
+/**
+ * Set exception info of the WASM module instance.
+ *
+ * @param module_inst the WASM module instance
+ *
+ * @param exception the exception string
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_exception(wasm_module_inst_t module_inst,
+ const char *exception);
+
+/**
+ * Clear exception info of the WASM module instance.
+ *
+ * @param module_inst the WASM module instance
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_clear_exception(wasm_module_inst_t module_inst);
+
+/**
+ * Set custom data to WASM module instance.
+ * Note:
+ * If WAMR_BUILD_LIB_PTHREAD is enabled, this API
+ * will spread the custom data to all threads
+ *
+ * @param module_inst the WASM module instance
+ * @param custom_data the custom data to be set
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_custom_data(wasm_module_inst_t module_inst,
+ void *custom_data);
+/**
+ * Get the custom data within a WASM module instance.
+ *
+ * @param module_inst the WASM module instance
+ *
+ * @return the custom data (NULL if not set yet)
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
+
+/**
+ * Allocate memory from the heap of WASM module instance
+ *
+ * Note: wasm_runtime_module_malloc can call heap functions inside
+ * the module instance and thus cause a memory growth.
+ * This API needs to be used very carefully when you have a native
+ * pointers to the module instance memory obtained with
+ * wasm_runtime_addr_app_to_native or similar APIs.
+ *
+ * @param module_inst the WASM module instance which contains heap
+ * @param size the size bytes to allocate
+ * @param p_native_addr return native address of the allocated memory
+ * if it is not NULL, and return NULL if memory malloc failed
+ *
+ * @return the allocated memory address, which is a relative offset to the
+ * base address of the module instance's memory space. Note that
+ * it is not an absolute address.
+ * Return non-zero if success, zero if failed.
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size,
+ void **p_native_addr);
+
+/**
+ * Free memory to the heap of WASM module instance
+ *
+ * @param module_inst the WASM module instance which contains heap
+ * @param ptr the pointer to free
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_module_free(wasm_module_inst_t module_inst, uint32_t ptr);
+
+/**
+ * Allocate memory from the heap of WASM module instance and initialize
+ * the memory with src
+ *
+ * @param module_inst the WASM module instance which contains heap
+ * @param src the source data to copy
+ * @param size the size of the source data
+ *
+ * @return the allocated memory address, which is a relative offset to the
+ * base address of the module instance's memory space. Note that
+ * it is not an absolute address.
+ * Return non-zero if success, zero if failed.
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_module_dup_data(wasm_module_inst_t module_inst,
+ const char *src, uint32_t size);
+
+/**
+ * Validate the app address, check whether it belongs to WASM module
+ * instance's address space, or in its heap space or memory space.
+ *
+ * @param module_inst the WASM module instance
+ * @param app_offset the app address to validate, which is a relative address
+ * @param size the size bytes of the app address
+ *
+ * @return true if success, false otherwise. If failed, an exception will
+ * be thrown.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_validate_app_addr(wasm_module_inst_t module_inst,
+ uint32_t app_offset, uint32_t size);
+
+/**
+ * Similar to wasm_runtime_validate_app_addr(), except that the size parameter
+ * is not provided. This function validates the app string address, check
+ * whether it belongs to WASM module instance's address space, or in its heap
+ * space or memory space. Moreover, it checks whether it is the offset of a
+ * string that is end with '\0'.
+ *
+ * Note: The validation result, especially the NUL termination check,
+ * is not reliable for a module instance with multiple threads because
+ * other threads can modify the heap behind us.
+ *
+ * @param module_inst the WASM module instance
+ * @param app_str_offset the app address of the string to validate, which is a
+ * relative address
+ *
+ * @return true if success, false otherwise. If failed, an exception will
+ * be thrown.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_validate_app_str_addr(wasm_module_inst_t module_inst,
+ uint32_t app_str_offset);
+
+/**
+ * Validate the native address, check whether it belongs to WASM module
+ * instance's address space, or in its heap space or memory space.
+ *
+ * @param module_inst the WASM module instance
+ * @param native_ptr the native address to validate, which is an absolute
+ * address
+ * @param size the size bytes of the app address
+ *
+ * @return true if success, false otherwise. If failed, an exception will
+ * be thrown.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_validate_native_addr(wasm_module_inst_t module_inst,
+ void *native_ptr, uint32_t size);
+
+/**
+ * Convert app address(relative address) to native address(absolute address)
+ *
+ * Note that native addresses to module instance memory can be invalidated
+ * on a memory growth. (Except shared memory, whose native addresses are
+ * stable.)
+ *
+ * @param module_inst the WASM module instance
+ * @param app_offset the app adress
+ *
+ * @return the native address converted
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_addr_app_to_native(wasm_module_inst_t module_inst,
+ uint32_t app_offset);
+
+/**
+ * Convert native address(absolute address) to app address(relative address)
+ *
+ * @param module_inst the WASM module instance
+ * @param native_ptr the native address
+ *
+ * @return the app address converted
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_addr_native_to_app(wasm_module_inst_t module_inst,
+ void *native_ptr);
+
+/**
+ * Get the app address range (relative address) that a app address belongs to
+ *
+ * @param module_inst the WASM module instance
+ * @param app_offset the app address to retrieve
+ * @param p_app_start_offset buffer to output the app start offset if not NULL
+ * @param p_app_end_offset buffer to output the app end offset if not NULL
+ *
+ * @return true if success, false otherwise.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_get_app_addr_range(wasm_module_inst_t module_inst,
+ uint32_t app_offset,
+ uint32_t *p_app_start_offset,
+ uint32_t *p_app_end_offset);
+
+/**
+ * Get the native address range (absolute address) that a native address
+ * belongs to
+ *
+ * @param module_inst the WASM module instance
+ * @param native_ptr the native address to retrieve
+ * @param p_native_start_addr buffer to output the native start address
+ * if not NULL
+ * @param p_native_end_addr buffer to output the native end address
+ * if not NULL
+ *
+ * @return true if success, false otherwise.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
+ uint8_t *native_ptr,
+ uint8_t **p_native_start_addr,
+ uint8_t **p_native_end_addr);
+
+/**
+ * Register native functions with same module name
+ *
+ * Note: The array `native_symbols` should not be read-only because the
+ * library can modify it in-place.
+ *
+ * Note: After successful call of this function, the array `native_symbols`
+ * is owned by the library.
+ *
+ * @param module_name the module name of the native functions
+ * @param native_symbols specifies an array of NativeSymbol structures which
+ * contain the names, function pointers and signatures
+ * Note: WASM runtime will not allocate memory to clone the data, so
+ * user must ensure the array can be used forever
+ * Meanings of letters in function signature:
+ * 'i': the parameter is i32 type
+ * 'I': the parameter is i64 type
+ * 'f': the parameter is f32 type
+ * 'F': the parameter is f64 type
+ * 'r': the parameter is externref type, it should be a uintptr_t in host
+ * '*': the parameter is a pointer (i32 in WASM), and runtime will
+ * auto check its boundary before calling the native function.
+ * If it is followed by '~', the checked length of the pointer
+ * is gotten from the following parameter, if not, the checked
+ * length of the pointer is 1.
+ * '~': the parameter is the pointer's length with i32 type, and must
+ * follow after '*'
+ * '$': the parameter is a string (i32 in WASM), and runtime will
+ * auto check its boundary before calling the native function
+ * @param n_native_symbols specifies the number of native symbols in the array
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_register_natives(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32_t n_native_symbols);
+
+/**
+ * Register native functions with same module name, similar to
+ * wasm_runtime_register_natives, the difference is that runtime passes raw
+ * arguments to native API, which means that the native API should be defined as
+ * void foo(wasm_exec_env_t exec_env, uint64 *args);
+ * and native API should extract arguments one by one from args array with macro
+ * native_raw_get_arg
+ * and write the return value back to args[0] with macro
+ * native_raw_return_type and native_raw_set_return
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_register_natives_raw(const char *module_name,
+ NativeSymbol *native_symbols,
+ uint32_t n_native_symbols);
+
+
+/**
+ * Undo wasm_runtime_register_natives or wasm_runtime_register_natives_raw
+ *
+ * @param module_name Should be the same as the corresponding
+ * wasm_runtime_register_natives.
+ * (Same in term of strcmp.)
+ *
+ * @param native_symbols Should be the same as the corresponding
+ * wasm_runtime_register_natives.
+ * (Same in term of pointer comparison.)
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_unregister_natives(const char *module_name,
+ NativeSymbol *native_symbols);
+
+/**
+ * Get attachment of native function from execution environment
+ *
+ * @param exec_env the execution environment to retrieve
+ *
+ * @return the attachment of native function
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
+
+/**
+ * Set user data to execution environment.
+ *
+ * @param exec_env the execution environment
+ * @param user_data the user data to be set
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
+
+/**
+ * Get the user data within execution environment.
+ *
+ * @param exec_env the execution environment
+ *
+ * @return the user data (NULL if not set yet)
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
+
+/**
+ * Dump runtime memory consumption, including:
+ * Exec env memory consumption
+ * WASM module memory consumption
+ * WASM module instance memory consumption
+ * stack and app heap used info
+ *
+ * @param exec_env the execution environment
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_dump_mem_consumption(wasm_exec_env_t exec_env);
+
+/**
+ * Dump runtime performance profiler data of each function
+ *
+ * @param module_inst the WASM module instance to profile
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst);
+
+/* wasm thread callback function type */
+typedef void *(*wasm_thread_callback_t)(wasm_exec_env_t, void *);
+/* wasm thread type */
+typedef uintptr_t wasm_thread_t;
+
+/**
+ * Set the max thread num per cluster.
+ *
+ * @param num maximum thread num
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_max_thread_num(uint32_t num);
+
+/**
+ * Spawn a new exec_env, the spawned exec_env
+ * can be used in other threads
+ *
+ * @param num the original exec_env
+ *
+ * @return the spawned exec_env if success, NULL otherwise
+ */
+WASM_RUNTIME_API_EXTERN wasm_exec_env_t
+wasm_runtime_spawn_exec_env(wasm_exec_env_t exec_env);
+
+/**
+ * Destroy the spawned exec_env
+ *
+ * @param exec_env the spawned exec_env
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_spawned_exec_env(wasm_exec_env_t exec_env);
+
+/**
+ * Spawn a thread from the given exec_env
+ *
+ * @param exec_env the original exec_env
+ * @param tid thread id to be returned to the caller
+ * @param callback the callback function provided by the user
+ * @param arg the arguments passed to the callback
+ *
+ * @return 0 if success, -1 otherwise
+ */
+WASM_RUNTIME_API_EXTERN int32_t
+wasm_runtime_spawn_thread(wasm_exec_env_t exec_env, wasm_thread_t *tid,
+ wasm_thread_callback_t callback, void *arg);
+
+/**
+ * Wait a spawned thread to terminate
+ *
+ * @param tid thread id
+ * @param retval if not NULL, output the return value of the thread
+ *
+ * @return 0 if success, error number otherwise
+ */
+WASM_RUNTIME_API_EXTERN int32_t
+wasm_runtime_join_thread(wasm_thread_t tid, void **retval);
+
+/**
+ * Map external object to an internal externref index: if the index
+ * has been created, return it, otherwise create the index.
+ *
+ * @param module_inst the WASM module instance that the extern object
+ * belongs to
+ * @param extern_obj the external object to be mapped
+ * @param p_externref_idx return externref index of the external object
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_obj2ref(wasm_module_inst_t module_inst,
+ void *extern_obj, uint32_t *p_externref_idx);
+
+/**
+ * Retrieve the external object from an internal externref index
+ *
+ * @param externref_idx the externref index to retrieve
+ * @param p_extern_obj return the mapped external object of
+ * the externref index
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_ref2obj(uint32_t externref_idx, void **p_extern_obj);
+
+/**
+ * Retain an extern object which is mapped to the internal externref
+ * so that the object won't be cleaned during extern object reclaim
+ * if it isn't used.
+ *
+ * @param externref_idx the externref index of an external object
+ * to retain
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_retain(uint32_t externref_idx);
+
+/**
+ * Dump the call stack to stdout
+ *
+ * @param exec_env the execution environment
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env);
+
+/**
+ * Get the size required to store the call stack contents, including
+ * the space for terminating null byte ('\0')
+ *
+ * @param exec_env the execution environment
+ *
+ * @return size required to store the contents, 0 means error
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_get_call_stack_buf_size(wasm_exec_env_t exec_env);
+
+/**
+ * Dump the call stack to buffer.
+ *
+ * @note this function is not thread-safe, please only use this API
+ * when the exec_env is not executing
+ *
+ * @param exec_env the execution environment
+ * @param buf buffer to store the dumped content
+ * @param len length of the buffer
+ *
+ * @return bytes dumped to the buffer, including the terminating null
+ * byte ('\0'), 0 means error and data in buf may be invalid
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_dump_call_stack_to_buf(wasm_exec_env_t exec_env, char *buf,
+ uint32_t len);
+
+/**
+ * Get a custom section by name
+ *
+ * @param module_comm the module to find
+ * @param name name of the custom section
+ * @param len return the length of the content if found
+ *
+ * @return Custom section content (not including the name length
+ * and name string) if found, NULL otherwise
+ */
+WASM_RUNTIME_API_EXTERN const uint8_t *
+wasm_runtime_get_custom_section(wasm_module_t const module_comm,
+ const char *name, uint32_t *len);
+
+
+/**
+ * Get WAMR semantic version
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
+
+/**
+ * Check whether an import func `(import <module_name> <func_name> (func ...))` is linked or not
+ * with runtime registered natvie functions
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_func_linked(const char *module_name,
+ const char *func_name);
+
+/**
+ * Check whether an import global `(import <module_name> <global_name> (global ...))` is linked or not
+ * with runtime registered natvie globals
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_global_linked(const char *module_name,
+ const char *global_name);
+/* clang-format on */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_EXPORT_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/SConscript
new file mode 100644
index 000000000..7c0605ee9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/SConscript
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+wasm_runtime.c
+''')
+
+if GetDepend(['WAMR_BUILD_FAST_INTERP']):
+ src += ["wasm_interp_fast.c"]
+else:
+ src += ["wasm_interp_classic.c"]
+
+if GetDepend(['WAMR_BUILD_MINI_LOADER']):
+ src += ["wasm_mini_loader.c"]
+else:
+ src += ["wasm_loader.c"]
+
+
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_interpreter', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/iwasm_interp.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/iwasm_interp.cmake
new file mode 100644
index 000000000..e6e52e42c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/iwasm_interp.cmake
@@ -0,0 +1,29 @@
+# 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})
+
+if (WAMR_BUILD_FAST_INTERP EQUAL 1)
+ set (INTERPRETER "wasm_interp_fast.c")
+else ()
+ set (INTERPRETER "wasm_interp_classic.c")
+endif ()
+
+if (WAMR_BUILD_MINI_LOADER EQUAL 1)
+ set (LOADER "wasm_mini_loader.c")
+else ()
+ set (LOADER "wasm_loader.c")
+endif ()
+
+file (GLOB_RECURSE source_all
+ ${IWASM_INTERP_DIR}/${LOADER}
+ ${IWASM_INTERP_DIR}/wasm_runtime.c
+ ${IWASM_INTERP_DIR}/${INTERPRETER}
+)
+
+set (IWASM_INTERP_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm.h
new file mode 100644
index 000000000..0797a018b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm.h
@@ -0,0 +1,797 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_H_
+#define _WASM_H_
+
+#include "bh_platform.h"
+#include "bh_hashmap.h"
+#include "bh_assert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Value Type */
+#define VALUE_TYPE_I32 0x7F
+#define VALUE_TYPE_I64 0X7E
+#define VALUE_TYPE_F32 0x7D
+#define VALUE_TYPE_F64 0x7C
+#define VALUE_TYPE_V128 0x7B
+#define VALUE_TYPE_FUNCREF 0x70
+#define VALUE_TYPE_EXTERNREF 0x6F
+#define VALUE_TYPE_VOID 0x40
+/* Used by AOT */
+#define VALUE_TYPE_I1 0x41
+/* Used by loader to represent any type of i32/i64/f32/f64 */
+#define VALUE_TYPE_ANY 0x42
+
+#define DEFAULT_NUM_BYTES_PER_PAGE 65536
+#define DEFAULT_MAX_PAGES 65536
+
+#define NULL_REF (0xFFFFFFFF)
+
+#define TABLE_MAX_SIZE (1024)
+
+#define INIT_EXPR_TYPE_I32_CONST 0x41
+#define INIT_EXPR_TYPE_I64_CONST 0x42
+#define INIT_EXPR_TYPE_F32_CONST 0x43
+#define INIT_EXPR_TYPE_F64_CONST 0x44
+#define INIT_EXPR_TYPE_V128_CONST 0xFD
+/* = WASM_OP_REF_FUNC */
+#define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
+/* = WASM_OP_REF_NULL */
+#define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
+#define INIT_EXPR_TYPE_GET_GLOBAL 0x23
+#define INIT_EXPR_TYPE_ERROR 0xff
+
+#define WASM_MAGIC_NUMBER 0x6d736100
+#define WASM_CURRENT_VERSION 1
+
+#define SECTION_TYPE_USER 0
+#define SECTION_TYPE_TYPE 1
+#define SECTION_TYPE_IMPORT 2
+#define SECTION_TYPE_FUNC 3
+#define SECTION_TYPE_TABLE 4
+#define SECTION_TYPE_MEMORY 5
+#define SECTION_TYPE_GLOBAL 6
+#define SECTION_TYPE_EXPORT 7
+#define SECTION_TYPE_START 8
+#define SECTION_TYPE_ELEM 9
+#define SECTION_TYPE_CODE 10
+#define SECTION_TYPE_DATA 11
+#if WASM_ENABLE_BULK_MEMORY != 0
+#define SECTION_TYPE_DATACOUNT 12
+#endif
+
+#define SUB_SECTION_TYPE_MODULE 0
+#define SUB_SECTION_TYPE_FUNC 1
+#define SUB_SECTION_TYPE_LOCAL 2
+
+#define IMPORT_KIND_FUNC 0
+#define IMPORT_KIND_TABLE 1
+#define IMPORT_KIND_MEMORY 2
+#define IMPORT_KIND_GLOBAL 3
+
+#define EXPORT_KIND_FUNC 0
+#define EXPORT_KIND_TABLE 1
+#define EXPORT_KIND_MEMORY 2
+#define EXPORT_KIND_GLOBAL 3
+
+#define LABEL_TYPE_BLOCK 0
+#define LABEL_TYPE_LOOP 1
+#define LABEL_TYPE_IF 2
+#define LABEL_TYPE_FUNCTION 3
+
+typedef struct WASMModule WASMModule;
+typedef struct WASMFunction WASMFunction;
+typedef struct WASMGlobal WASMGlobal;
+
+typedef union V128 {
+ int8 i8x16[16];
+ int16 i16x8[8];
+ int32 i32x8[4];
+ int64 i64x2[2];
+ float32 f32x4[4];
+ float64 f64x2[2];
+} V128;
+
+typedef union WASMValue {
+ int32 i32;
+ uint32 u32;
+ uint32 global_index;
+ uint32 ref_index;
+ int64 i64;
+ uint64 u64;
+ float32 f32;
+ float64 f64;
+ uintptr_t addr;
+ V128 v128;
+} WASMValue;
+
+typedef struct InitializerExpression {
+ /* type of INIT_EXPR_TYPE_XXX */
+ /* it actually is instr, in some places, requires constant only */
+ uint8 init_expr_type;
+ WASMValue u;
+} InitializerExpression;
+
+typedef struct WASMType {
+ uint16 param_count;
+ uint16 result_count;
+ uint16 param_cell_num;
+ uint16 ret_cell_num;
+ uint16 ref_count;
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ /* Code block to call llvm jit functions of this
+ kind of function type from fast jit jitted code */
+ void *call_to_llvm_jit_from_fast_jit;
+#endif
+ /* types of params and results */
+ uint8 types[1];
+} WASMType;
+
+typedef struct WASMTable {
+ uint8 elem_type;
+ uint32 flags;
+ uint32 init_size;
+ /* specified if (flags & 1), else it is 0x10000 */
+ uint32 max_size;
+ bool possible_grow;
+} WASMTable;
+
+typedef struct WASMMemory {
+ uint32 flags;
+ uint32 num_bytes_per_page;
+ uint32 init_page_count;
+ uint32 max_page_count;
+} WASMMemory;
+
+typedef struct WASMTableImport {
+ char *module_name;
+ char *field_name;
+ uint8 elem_type;
+ uint32 flags;
+ uint32 init_size;
+ /* specified if (flags & 1), else it is 0x10000 */
+ uint32 max_size;
+ bool possible_grow;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *import_module;
+ WASMTable *import_table_linked;
+#endif
+} WASMTableImport;
+
+typedef struct WASMMemoryImport {
+ char *module_name;
+ char *field_name;
+ uint32 flags;
+ uint32 num_bytes_per_page;
+ uint32 init_page_count;
+ uint32 max_page_count;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *import_module;
+ WASMMemory *import_memory_linked;
+#endif
+} WASMMemoryImport;
+
+typedef struct WASMFunctionImport {
+ char *module_name;
+ char *field_name;
+ /* function type */
+ WASMType *func_type;
+ /* native function pointer after linked */
+ void *func_ptr_linked;
+ /* signature from registered native symbols */
+ const char *signature;
+ /* attachment */
+ void *attachment;
+ bool call_conv_raw;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *import_module;
+ WASMFunction *import_func_linked;
+#endif
+ bool call_conv_wasm_c_api;
+} WASMFunctionImport;
+
+typedef struct WASMGlobalImport {
+ char *module_name;
+ char *field_name;
+ uint8 type;
+ bool is_mutable;
+ /* global data after linked */
+ WASMValue global_data_linked;
+ bool is_linked;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /* imported function pointer after linked */
+ /* TODO: remove if not needed */
+ WASMModule *import_module;
+ WASMGlobal *import_global_linked;
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+ /* The data offset of current global in global data */
+ uint32 data_offset;
+#endif
+} WASMGlobalImport;
+
+typedef struct WASMImport {
+ uint8 kind;
+ union {
+ WASMFunctionImport function;
+ WASMTableImport table;
+ WASMMemoryImport memory;
+ WASMGlobalImport global;
+ struct {
+ char *module_name;
+ char *field_name;
+ } names;
+ } u;
+} WASMImport;
+
+struct WASMFunction {
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ char *field_name;
+#endif
+ /* the type of function */
+ WASMType *func_type;
+ uint32 local_count;
+ uint8 *local_types;
+
+ /* cell num of parameters */
+ uint16 param_cell_num;
+ /* cell num of return type */
+ uint16 ret_cell_num;
+ /* cell num of local variables */
+ uint16 local_cell_num;
+ /* offset of each local, including function parameters
+ and local variables */
+ uint16 *local_offsets;
+
+ uint32 max_stack_cell_num;
+ uint32 max_block_num;
+ uint32 code_size;
+ uint8 *code;
+#if WASM_ENABLE_FAST_INTERP != 0
+ uint32 code_compiled_size;
+ uint8 *code_compiled;
+ uint8 *consts;
+ uint32 const_cell_num;
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ /* Whether function has opcode memory.grow */
+ bool has_op_memory_grow;
+ /* Whether function has opcode call or call_indirect */
+ bool has_op_func_call;
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ /* Whether function has memory operation opcodes */
+ bool has_memory_operations;
+ /* Whether function has opcode call_indirect */
+ bool has_op_call_indirect;
+ /* Whether function has opcode set_global_aux_stack */
+ bool has_op_set_global_aux_stack;
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /* The compiled fast jit jitted code block of this function */
+ void *fast_jit_jitted_code;
+#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ /* The compiled llvm jit func ptr of this function */
+ void *llvm_jit_func_ptr;
+ /* Code block to call fast jit jitted code of this function
+ from the llvm jit jitted code */
+ void *call_to_fast_jit_from_llvm_jit;
+#endif
+#endif
+};
+
+struct WASMGlobal {
+ uint8 type;
+ bool is_mutable;
+ InitializerExpression init_expr;
+#if WASM_ENABLE_FAST_JIT != 0
+ /* The data offset of current global in global data */
+ uint32 data_offset;
+#endif
+};
+
+typedef struct WASMExport {
+ char *name;
+ uint8 kind;
+ uint32 index;
+} WASMExport;
+
+typedef struct WASMTableSeg {
+ /* 0 to 7 */
+ uint32 mode;
+ /* funcref or externref, elemkind will be considered as funcref */
+ uint32 elem_type;
+ bool is_dropped;
+ /* optional, only for active */
+ uint32 table_index;
+ InitializerExpression base_offset;
+ uint32 function_count;
+ uint32 *func_indexes;
+} WASMTableSeg;
+
+typedef struct WASMDataSeg {
+ uint32 memory_index;
+ InitializerExpression base_offset;
+ uint32 data_length;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ bool is_passive;
+#endif
+ uint8 *data;
+} WASMDataSeg;
+
+typedef struct BlockAddr {
+ const uint8 *start_addr;
+ uint8 *else_addr;
+ uint8 *end_addr;
+} BlockAddr;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+typedef struct WASIArguments {
+ const char **dir_list;
+ uint32 dir_count;
+ const char **map_dir_list;
+ uint32 map_dir_count;
+ const char **env;
+ uint32 env_count;
+ /* in CIDR noation */
+ const char **addr_pool;
+ uint32 addr_count;
+ const char **ns_lookup_pool;
+ uint32 ns_lookup_count;
+ char **argv;
+ uint32 argc;
+ int stdio[3];
+} WASIArguments;
+#endif
+
+typedef struct StringNode {
+ struct StringNode *next;
+ char *str;
+} StringNode, *StringList;
+
+typedef struct BrTableCache {
+ struct BrTableCache *next;
+ /* Address of br_table opcode */
+ uint8 *br_table_op_addr;
+ uint32 br_count;
+ uint32 br_depths[1];
+} BrTableCache;
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+typedef struct WASMFastOPCodeNode {
+ struct WASMFastOPCodeNode *next;
+ uint64 offset;
+ uint8 orig_op;
+} WASMFastOPCodeNode;
+#endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+typedef struct WASMCustomSection {
+ struct WASMCustomSection *next;
+ /* Start address of the section name */
+ char *name_addr;
+ /* Length of the section name decoded from leb */
+ uint32 name_len;
+ /* Start address of the content (name len and name skipped) */
+ uint8 *content_addr;
+ uint32 content_len;
+} WASMCustomSection;
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+struct AOTCompData;
+struct AOTCompContext;
+
+/* Orc JIT thread arguments */
+typedef struct OrcJitThreadArg {
+#if WASM_ENABLE_JIT != 0
+ struct AOTCompContext *comp_ctx;
+#endif
+ struct WASMModule *module;
+ uint32 group_idx;
+} OrcJitThreadArg;
+#endif
+
+struct WASMModuleInstance;
+
+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;
+ uint32 table_count;
+ uint32 memory_count;
+ uint32 global_count;
+ uint32 export_count;
+ uint32 table_seg_count;
+ /* data seg count read from data segment section */
+ uint32 data_seg_count;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ /* data count read from datacount section */
+ uint32 data_seg_count1;
+#endif
+
+ uint32 import_function_count;
+ uint32 import_table_count;
+ uint32 import_memory_count;
+ uint32 import_global_count;
+
+ WASMImport *import_functions;
+ WASMImport *import_tables;
+ WASMImport *import_memories;
+ WASMImport *import_globals;
+
+ WASMType **types;
+ WASMImport *imports;
+ WASMFunction **functions;
+ WASMTable *tables;
+ WASMMemory *memories;
+ WASMGlobal *globals;
+ WASMExport *exports;
+ WASMTableSeg *table_segments;
+ WASMDataSeg **data_segments;
+ uint32 start_function;
+
+ /* total global variable size */
+ uint32 global_data_size;
+
+ /* the index of auxiliary __data_end global,
+ -1 means unexported */
+ uint32 aux_data_end_global_index;
+ /* auxiliary __data_end exported by wasm app */
+ uint32 aux_data_end;
+
+ /* the index of auxiliary __heap_base global,
+ -1 means unexported */
+ uint32 aux_heap_base_global_index;
+ /* auxiliary __heap_base exported by wasm app */
+ uint32 aux_heap_base;
+
+ /* the index of auxiliary stack top global,
+ -1 means unexported */
+ uint32 aux_stack_top_global_index;
+ /* auxiliary stack bottom resolved */
+ uint32 aux_stack_bottom;
+ /* auxiliary stack size resolved */
+ uint32 aux_stack_size;
+
+ /* the index of malloc/free function,
+ -1 means unexported */
+ uint32 malloc_function;
+ uint32 free_function;
+
+ /* the index of __retain function,
+ -1 means unexported */
+ uint32 retain_function;
+
+ /* Whether there is possible memory grow, e.g. memory.grow opcode */
+ bool possible_memory_grow;
+
+ StringList const_str_list;
+#if WASM_ENABLE_FAST_INTERP == 0
+ bh_list br_table_cache_list_head;
+ bh_list *br_table_cache_list;
+#endif
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIArguments wasi_args;
+ bool import_wasi_api;
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /* TODO: add mutex for mutli-thread? */
+ bh_list import_module_list_head;
+ bh_list *import_module_list;
+#endif
+#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0
+ bh_list fast_opcode_list;
+ uint8 *buf_code;
+ uint64 buf_code_size;
+#endif
+#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0 \
+ || WASM_ENABLE_FAST_JIT != 0
+ uint8 *load_addr;
+ uint64 load_size;
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0 \
+ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0)
+ /**
+ * List of instances referred to this module. When source debugging
+ * feature is enabled, the debugger may modify the code section of
+ * the module, so we need to report a warning if user create several
+ * instances based on the same module.
+ *
+ * Also add the instance to the list for Fast JIT to LLVM JIT
+ * tier-up, since we need to lazily update the LLVM func pointers
+ * in the instance.
+ */
+ struct WASMModuleInstance *instance_list;
+ korp_mutex instance_list_lock;
+#endif
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ const uint8 *name_section_buf;
+ const uint8 *name_section_buf_end;
+#endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ WASMCustomSection *custom_section_list;
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /**
+ * func pointers of Fast JITed (un-imported) functions
+ * for non Multi-Tier JIT mode:
+ * (1) when lazy jit is disabled, each pointer is set to the compiled
+ * fast jit jitted code
+ * (2) when lazy jit is enabled, each pointer is firstly inited as
+ * jit_global->compile_fast_jit_and_then_call, and then set to the
+ * compiled fast jit jitted code when it is called (the stub will
+ * compile the jit function and then update itself)
+ * for Multi-Tier JIT mode:
+ * each pointer is firstly inited as compile_fast_jit_and_then_call,
+ * and then set to the compiled fast jit jitted code when it is called,
+ * and when the llvm jit func ptr of the same function is compiled, it
+ * will be set to call_to_llvm_jit_from_fast_jit of this function type
+ * (tier-up from fast-jit to llvm-jit)
+ */
+ void **fast_jit_func_ptrs;
+ /* locks for Fast JIT lazy compilation */
+ korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
+ bool fast_jit_thread_locks_inited[WASM_ORC_JIT_BACKEND_THREAD_NUM];
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ struct AOTCompData *comp_data;
+ struct AOTCompContext *comp_ctx;
+ /**
+ * func pointers of LLVM JITed (un-imported) functions
+ * for non Multi-Tier JIT mode:
+ * each pointer is set to the lookuped llvm jit func ptr, note that it
+ * is a stub and will trigger the actual compilation when it is called
+ * for Multi-Tier JIT mode:
+ * each pointer is inited as call_to_fast_jit code block, when the llvm
+ * jit func ptr is actually compiled, it is set to the compiled llvm jit
+ * func ptr
+ */
+ void **func_ptrs;
+ /* whether the func pointers are compiled */
+ bool *func_ptrs_compiled;
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ /* backend compilation threads */
+ korp_tid orcjit_threads[WASM_ORC_JIT_BACKEND_THREAD_NUM];
+ /* backend thread arguments */
+ OrcJitThreadArg orcjit_thread_args[WASM_ORC_JIT_BACKEND_THREAD_NUM];
+ /* whether to stop the compilation of backend threads */
+ bool orcjit_stop_compiling;
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ /* wait lock/cond for the synchronization of
+ the llvm jit initialization */
+ korp_mutex tierup_wait_lock;
+ korp_cond tierup_wait_cond;
+ bool tierup_wait_lock_inited;
+ korp_tid llvm_jit_init_thread;
+ /* whether the llvm jit is initialized */
+ bool llvm_jit_inited;
+ /* Whether to enable llvm jit compilation:
+ it is set to true only when there is a module instance starts to
+ run with running mode Mode_LLVM_JIT or Mode_Multi_Tier_JIT,
+ since no need to enable llvm jit compilation for Mode_Interp and
+ Mode_Fast_JIT, so as to improve performance for them */
+ bool enable_llvm_jit_compilation;
+ /* The count of groups which finish compiling the fast jit
+ functions in that group */
+ uint32 fast_jit_ready_groups;
+#endif
+};
+
+typedef struct BlockType {
+ /* Block type may be expressed in one of two forms:
+ * either by the type of the single return value or
+ * by a type index of module.
+ */
+ union {
+ uint8 value_type;
+ WASMType *type;
+ } u;
+ bool is_value_type;
+} BlockType;
+
+typedef struct WASMBranchBlock {
+ uint8 *begin_addr;
+ uint8 *target_addr;
+ uint32 *frame_sp;
+ uint32 cell_num;
+} WASMBranchBlock;
+
+/* Execution environment, e.g. stack info */
+/**
+ * Align an unsigned value on a alignment boundary.
+ *
+ * @param v the value to be aligned
+ * @param b the alignment boundary (2, 4, 8, ...)
+ *
+ * @return the aligned value
+ */
+inline static unsigned
+align_uint(unsigned v, unsigned b)
+{
+ unsigned m = b - 1;
+ return (v + m) & ~m;
+}
+
+/**
+ * Return the hash value of c string.
+ */
+inline static uint32
+wasm_string_hash(const char *str)
+{
+ unsigned h = (unsigned)strlen(str);
+ const uint8 *p = (uint8 *)str;
+ const uint8 *end = p + h;
+
+ while (p != end)
+ h = ((h << 5) - h) + *p++;
+ return h;
+}
+
+/**
+ * Whether two c strings are equal.
+ */
+inline static bool
+wasm_string_equal(const char *s1, const char *s2)
+{
+ return strcmp(s1, s2) == 0 ? true : false;
+}
+
+/**
+ * Return the byte size of value type.
+ *
+ */
+inline static uint32
+wasm_value_type_size(uint8 value_type)
+{
+ switch (value_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ return sizeof(int32);
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ return sizeof(int64);
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ return sizeof(int64) * 2;
+#endif
+ case VALUE_TYPE_VOID:
+ return 0;
+ default:
+ bh_assert(0);
+ }
+ return 0;
+}
+
+inline static uint16
+wasm_value_type_cell_num(uint8 value_type)
+{
+ return wasm_value_type_size(value_type) / 4;
+}
+
+inline static uint32
+wasm_get_cell_num(const uint8 *types, uint32 type_count)
+{
+ uint32 cell_num = 0;
+ uint32 i;
+ for (i = 0; i < type_count; i++)
+ cell_num += wasm_value_type_cell_num(types[i]);
+ return cell_num;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+inline static uint16
+wasm_value_type_cell_num_outside(uint8 value_type)
+{
+ if (VALUE_TYPE_EXTERNREF == value_type) {
+ return sizeof(uintptr_t) / sizeof(uint32);
+ }
+ else {
+ return wasm_value_type_cell_num(value_type);
+ }
+}
+#endif
+
+inline static bool
+wasm_type_equal(const WASMType *type1, const WASMType *type2)
+{
+ if (type1 == type2) {
+ return true;
+ }
+ return (type1->param_count == type2->param_count
+ && type1->result_count == type2->result_count
+ && memcmp(type1->types, type2->types,
+ (uint32)(type1->param_count + type1->result_count))
+ == 0)
+ ? true
+ : false;
+}
+
+inline static uint32
+wasm_get_smallest_type_idx(WASMType **types, uint32 type_count,
+ uint32 cur_type_idx)
+{
+ uint32 i;
+
+ for (i = 0; i < cur_type_idx; i++) {
+ if (wasm_type_equal(types[cur_type_idx], types[i]))
+ return i;
+ }
+ (void)type_count;
+ return cur_type_idx;
+}
+
+static inline uint32
+block_type_get_param_types(BlockType *block_type, uint8 **p_param_types)
+{
+ uint32 param_count = 0;
+ if (!block_type->is_value_type) {
+ WASMType *wasm_type = block_type->u.type;
+ *p_param_types = wasm_type->types;
+ param_count = wasm_type->param_count;
+ }
+ else {
+ *p_param_types = NULL;
+ param_count = 0;
+ }
+
+ return param_count;
+}
+
+static inline uint32
+block_type_get_result_types(BlockType *block_type, uint8 **p_result_types)
+{
+ uint32 result_count = 0;
+ if (block_type->is_value_type) {
+ if (block_type->u.value_type != VALUE_TYPE_VOID) {
+ *p_result_types = &block_type->u.value_type;
+ result_count = 1;
+ }
+ }
+ else {
+ WASMType *wasm_type = block_type->u.type;
+ *p_result_types = wasm_type->types + wasm_type->param_count;
+ result_count = wasm_type->result_count;
+ }
+ return result_count;
+}
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* end of _WASM_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp.h
new file mode 100644
index 000000000..d3692ff21
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_INTERP_H
+#define _WASM_INTERP_H
+
+#include "wasm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct WASMModuleInstance;
+struct WASMFunctionInstance;
+struct WASMExecEnv;
+
+typedef struct WASMInterpFrame {
+ /* The frame of the caller that are calling the current function. */
+ struct WASMInterpFrame *prev_frame;
+
+ /* The current WASM function. */
+ struct WASMFunctionInstance *function;
+
+ /* Instruction pointer of the bytecode array. */
+ uint8 *ip;
+
+#if WASM_ENABLE_FAST_JIT != 0
+ uint8 *jitted_return_addr;
+#endif
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ uint64 time_started;
+#endif
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Return offset of the first return value of current frame,
+ the callee will put return values here continuously */
+ uint32 ret_offset;
+ uint32 *lp;
+ uint32 operand[1];
+#else
+ /* Operand stack top pointer of the current frame. The bottom of
+ the stack is the next cell after the last local variable. */
+ uint32 *sp_bottom;
+ uint32 *sp_boundary;
+ uint32 *sp;
+
+ WASMBranchBlock *csp_bottom;
+ WASMBranchBlock *csp_boundary;
+ WASMBranchBlock *csp;
+
+ /**
+ * Frame data, the layout is:
+ * lp: parameters and local variables
+ * sp_bottom to sp_boundary: wasm operand stack
+ * csp_bottom to csp_boundary: wasm label stack
+ * jit spill cache: only available for fast jit
+ */
+ uint32 lp[1];
+#endif
+} WASMInterpFrame;
+
+/**
+ * Calculate the size of interpreter area of frame of a function.
+ *
+ * @param all_cell_num number of all cells including local variables
+ * and the working stack slots
+ *
+ * @return the size of interpreter area of the frame
+ */
+static inline unsigned
+wasm_interp_interp_frame_size(unsigned all_cell_num)
+{
+ unsigned frame_size;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ frame_size = (uint32)offsetof(WASMInterpFrame, lp) + all_cell_num * 4;
+#else
+ frame_size = (uint32)offsetof(WASMInterpFrame, operand) + all_cell_num * 4;
+#endif
+ return align_uint(frame_size, 4);
+}
+
+void
+wasm_interp_call_wasm(struct WASMModuleInstance *module_inst,
+ struct WASMExecEnv *exec_env,
+ struct WASMFunctionInstance *function, uint32 argc,
+ uint32 argv[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_INTERP_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_classic.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_classic.c
new file mode 100644
index 000000000..4cc470143
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_classic.c
@@ -0,0 +1,4315 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_interp.h"
+#include "bh_log.h"
+#include "wasm_runtime.h"
+#include "wasm_opcode.h"
+#include "wasm_loader.h"
+#include "wasm_memory.h"
+#include "../common/wasm_exec_env.h"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "../common/wasm_shared_memory.h"
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#include "../libraries/debug-engine/debug_engine.h"
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+#include "../fast-jit/jit_compiler.h"
+#endif
+
+typedef int32 CellType_I32;
+typedef int64 CellType_I64;
+typedef float32 CellType_F32;
+typedef float64 CellType_F64;
+
+#define BR_TABLE_TMP_BUF_LEN 32
+
+#if WASM_ENABLE_THREAD_MGR == 0
+#define get_linear_mem_size() linear_mem_size
+#else
+/**
+ * Load memory data size in each time boundary check in
+ * multi-threading mode since it may be changed by other
+ * threads in memory.grow
+ */
+#define get_linear_mem_size() memory->memory_data_size
+#endif
+
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+#define CHECK_MEMORY_OVERFLOW(bytes) \
+ do { \
+ uint64 offset1 = (uint64)offset + (uint64)addr; \
+ if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
+ /* If offset1 is in valid range, maddr must also \
+ be in valid range, no need to check it again. */ \
+ maddr = memory->memory_data + offset1; \
+ else \
+ goto out_of_bounds; \
+ } while (0)
+
+#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
+ do { \
+ uint64 offset1 = (uint32)(start); \
+ if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
+ /* App heap space is not valid space for \
+ bulk memory operation */ \
+ maddr = memory->memory_data + offset1; \
+ else \
+ goto out_of_bounds; \
+ } while (0)
+#else
+#define CHECK_MEMORY_OVERFLOW(bytes) \
+ do { \
+ uint64 offset1 = (uint64)offset + (uint64)addr; \
+ maddr = memory->memory_data + offset1; \
+ } while (0)
+
+#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
+ do { \
+ maddr = memory->memory_data + (uint32)(start); \
+ } while (0)
+#endif /* !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
+
+#define CHECK_ATOMIC_MEMORY_ACCESS() \
+ do { \
+ if (((uintptr_t)maddr & (((uintptr_t)1 << align) - 1)) != 0) \
+ goto unaligned_atomic; \
+ } while (0)
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#define TRIGGER_WATCHPOINT_SIGTRAP() \
+ do { \
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); \
+ CHECK_SUSPEND_FLAGS(); \
+ } while (0)
+
+#define CHECK_WATCHPOINT(list, current_addr) \
+ do { \
+ WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list); \
+ while (watchpoint) { \
+ WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint); \
+ if (watchpoint->addr <= current_addr \
+ && watchpoint->addr + watchpoint->length > current_addr) { \
+ TRIGGER_WATCHPOINT_SIGTRAP(); \
+ } \
+ watchpoint = next; \
+ } \
+ } while (0)
+
+#define CHECK_READ_WATCHPOINT(addr, offset) \
+ CHECK_WATCHPOINT(watch_point_list_read, WASM_ADDR_OFFSET(addr + offset))
+#define CHECK_WRITE_WATCHPOINT(addr, offset) \
+ CHECK_WATCHPOINT(watch_point_list_write, WASM_ADDR_OFFSET(addr + offset))
+#else
+#define CHECK_READ_WATCHPOINT(addr, offset) (void)0
+#define CHECK_WRITE_WATCHPOINT(addr, offset) (void)0
+#endif
+
+static inline uint32
+rotl32(uint32 n, uint32 c)
+{
+ const uint32 mask = (31);
+ c = c % 32;
+ c &= mask;
+ return (n << c) | (n >> ((0 - c) & mask));
+}
+
+static inline uint32
+rotr32(uint32 n, uint32 c)
+{
+ const uint32 mask = (31);
+ c = c % 32;
+ c &= mask;
+ return (n >> c) | (n << ((0 - c) & mask));
+}
+
+static inline uint64
+rotl64(uint64 n, uint64 c)
+{
+ const uint64 mask = (63);
+ c = c % 64;
+ c &= mask;
+ return (n << c) | (n >> ((0 - c) & mask));
+}
+
+static inline uint64
+rotr64(uint64 n, uint64 c)
+{
+ const uint64 mask = (63);
+ c = c % 64;
+ c &= mask;
+ return (n >> c) | (n << ((0 - c) & mask));
+}
+
+static inline float32
+f32_min(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+static inline float32
+f32_max(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+static inline float64
+f64_min(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+static inline float64
+f64_max(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+static inline uint32
+clz32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 0x80000000)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+static inline uint32
+clz64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 0x8000000000000000LL)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+static inline uint32
+ctz32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+static inline uint32
+ctz64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+static inline uint32
+popcount32(uint32 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+static inline uint32
+popcount64(uint64 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+static float
+local_copysignf(float x, float y)
+{
+ union {
+ float f;
+ uint32 i;
+ } ux = { x }, uy = { y };
+ ux.i &= 0x7fffffff;
+ ux.i |= uy.i & 0x80000000;
+ return ux.f;
+}
+
+static double
+local_copysign(double x, double y)
+{
+ union {
+ double f;
+ uint64 i;
+ } ux = { x }, uy = { y };
+ ux.i &= UINT64_MAX / 2;
+ ux.i |= uy.i & 1ULL << 63;
+ return ux.f;
+}
+
+static uint64
+read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
+{
+ uint64 result = 0, byte;
+ uint32 offset = *p_offset;
+ uint32 shift = 0;
+
+ while (true) {
+ byte = buf[offset++];
+ result |= ((byte & 0x7f) << shift);
+ shift += 7;
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ }
+ if (sign && (shift < maxbits) && (byte & 0x40)) {
+ /* Sign extend */
+ result |= (~((uint64)0)) << shift;
+ }
+ *p_offset = offset;
+ return result;
+}
+
+#define skip_leb(p) while (*p++ & 0x80)
+
+#define PUSH_I32(value) \
+ do { \
+ *(int32 *)frame_sp++ = (int32)(value); \
+ } while (0)
+
+#define PUSH_F32(value) \
+ do { \
+ *(float32 *)frame_sp++ = (float32)(value); \
+ } while (0)
+
+#define PUSH_I64(value) \
+ do { \
+ PUT_I64_TO_ADDR(frame_sp, value); \
+ frame_sp += 2; \
+ } while (0)
+
+#define PUSH_F64(value) \
+ do { \
+ PUT_F64_TO_ADDR(frame_sp, value); \
+ frame_sp += 2; \
+ } while (0)
+
+#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
+ do { \
+ bh_assert(frame_csp < frame->csp_boundary); \
+ /* frame_csp->label_type = _label_type; */ \
+ frame_csp->cell_num = cell_num; \
+ frame_csp->begin_addr = frame_ip; \
+ frame_csp->target_addr = _target_addr; \
+ frame_csp->frame_sp = frame_sp - param_cell_num; \
+ frame_csp++; \
+ } while (0)
+
+#define POP_I32() (--frame_sp, *(int32 *)frame_sp)
+
+#define POP_F32() (--frame_sp, *(float32 *)frame_sp)
+
+#define POP_I64() (frame_sp -= 2, GET_I64_FROM_ADDR(frame_sp))
+
+#define POP_F64() (frame_sp -= 2, GET_F64_FROM_ADDR(frame_sp))
+
+#define POP_CSP_CHECK_OVERFLOW(n) \
+ do { \
+ bh_assert(frame_csp - n >= frame->csp_bottom); \
+ } while (0)
+
+#define POP_CSP() \
+ do { \
+ POP_CSP_CHECK_OVERFLOW(1); \
+ --frame_csp; \
+ } while (0)
+
+#define POP_CSP_N(n) \
+ do { \
+ uint32 *frame_sp_old = frame_sp; \
+ uint32 cell_num_to_copy; \
+ POP_CSP_CHECK_OVERFLOW(n + 1); \
+ frame_csp -= n; \
+ frame_ip = (frame_csp - 1)->target_addr; \
+ /* copy arity values of block */ \
+ frame_sp = (frame_csp - 1)->frame_sp; \
+ cell_num_to_copy = (frame_csp - 1)->cell_num; \
+ if (cell_num_to_copy > 0) { \
+ word_copy(frame_sp, frame_sp_old - cell_num_to_copy, \
+ cell_num_to_copy); \
+ } \
+ frame_sp += cell_num_to_copy; \
+ } while (0)
+
+/* Pop the given number of elements from the given frame's stack. */
+#define POP(N) \
+ do { \
+ int n = (N); \
+ frame_sp -= n; \
+ } while (0)
+
+#define SYNC_ALL_TO_FRAME() \
+ do { \
+ frame->sp = frame_sp; \
+ frame->ip = frame_ip; \
+ frame->csp = frame_csp; \
+ } while (0)
+
+#define UPDATE_ALL_FROM_FRAME() \
+ do { \
+ frame_sp = frame->sp; \
+ frame_ip = frame->ip; \
+ frame_csp = frame->csp; \
+ } while (0)
+
+#define read_leb_int64(p, p_end, res) \
+ do { \
+ uint8 _val = *p; \
+ if (!(_val & 0x80)) { \
+ res = (int64)_val; \
+ if (_val & 0x40) \
+ /* sign extend */ \
+ res |= 0xFFFFFFFFFFFFFF80LL; \
+ p++; \
+ break; \
+ } \
+ uint32 _off = 0; \
+ res = (int64)read_leb(p, &_off, 64, true); \
+ p += _off; \
+ } while (0)
+
+#define read_leb_uint32(p, p_end, res) \
+ do { \
+ uint8 _val = *p; \
+ if (!(_val & 0x80)) { \
+ res = _val; \
+ p++; \
+ break; \
+ } \
+ uint32 _off = 0; \
+ res = (uint32)read_leb(p, &_off, 32, false); \
+ p += _off; \
+ } while (0)
+
+#define read_leb_int32(p, p_end, res) \
+ do { \
+ uint8 _val = *p; \
+ if (!(_val & 0x80)) { \
+ res = (int32)_val; \
+ if (_val & 0x40) \
+ /* sign extend */ \
+ res |= 0xFFFFFF80; \
+ p++; \
+ break; \
+ } \
+ uint32 _off = 0; \
+ res = (int32)read_leb(p, &_off, 32, true); \
+ p += _off; \
+ } while (0)
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+#define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func)
+#else
+#define RECOVER_FRAME_IP_END() (void)0
+#endif
+
+#define RECOVER_CONTEXT(new_frame) \
+ do { \
+ frame = (new_frame); \
+ cur_func = frame->function; \
+ prev_frame = frame->prev_frame; \
+ frame_ip = frame->ip; \
+ RECOVER_FRAME_IP_END(); \
+ frame_lp = frame->lp; \
+ frame_sp = frame->sp; \
+ frame_csp = frame->csp; \
+ } while (0)
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#define GET_OPCODE() opcode = *(frame_ip - 1);
+#else
+#define GET_OPCODE() (void)0
+#endif
+
+#define DEF_OP_I_CONST(ctype, src_op_type) \
+ do { \
+ ctype cval; \
+ read_leb_##ctype(frame_ip, frame_ip_end, cval); \
+ PUSH_##src_op_type(cval); \
+ } while (0)
+
+#define DEF_OP_EQZ(src_op_type) \
+ do { \
+ int32 pop_val; \
+ pop_val = POP_##src_op_type() == 0; \
+ PUSH_I32(pop_val); \
+ } while (0)
+
+#define DEF_OP_CMP(src_type, src_op_type, cond) \
+ do { \
+ uint32 res; \
+ src_type val1, val2; \
+ val2 = (src_type)POP_##src_op_type(); \
+ val1 = (src_type)POP_##src_op_type(); \
+ res = val1 cond val2; \
+ PUSH_I32(res); \
+ } while (0)
+
+#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) \
+ do { \
+ src_type val1, val2; \
+ val1 = (src_type)POP_##src_op_type(); \
+ val2 = (src_type)operation(val1); \
+ PUSH_##src_op_type(val2); \
+ } while (0)
+
+#define DEF_OP_NUMERIC(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); \
+ } while (0)
+
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define DEF_OP_NUMERIC_64 DEF_OP_NUMERIC
+#else
+#define DEF_OP_NUMERIC_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; \
+ PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \
+ } 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 src_val; \
+ src_val = POP_##src_op_type(); \
+ PUSH_##src_op_type(method(src_val)); \
+ } while (0)
+
+#define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type) \
+ static dst_type func_name(src_type src_value, src_type src_min, \
+ src_type src_max, dst_type dst_min, \
+ dst_type dst_max, bool is_sign) \
+ { \
+ dst_type dst_value = 0; \
+ if (!isnan(src_value)) { \
+ if (src_value <= src_min) \
+ dst_value = dst_min; \
+ else if (src_value >= src_max) \
+ dst_value = dst_max; \
+ else { \
+ if (is_sign) \
+ dst_value = (dst_type)(signed_type)src_value; \
+ else \
+ dst_value = (dst_type)src_value; \
+ } \
+ } \
+ return dst_value; \
+ }
+
+TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32)
+TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64)
+TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32)
+TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64)
+
+static bool
+trunc_f32_to_int(WASMModuleInstance *module, uint32 *frame_sp, float32 src_min,
+ float32 src_max, bool saturating, bool is_i32, bool is_sign)
+{
+ float32 src_value = POP_F32();
+ uint64 dst_value_i64;
+ uint32 dst_value_i32;
+
+ if (!saturating) {
+ if (isnan(src_value)) {
+ wasm_set_exception(module, "invalid conversion to integer");
+ return false;
+ }
+ else if (src_value <= src_min || src_value >= src_max) {
+ wasm_set_exception(module, "integer overflow");
+ return false;
+ }
+ }
+
+ if (is_i32) {
+ uint32 dst_min = is_sign ? INT32_MIN : 0;
+ uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+ dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ PUSH_I32(dst_value_i32);
+ }
+ else {
+ uint64 dst_min = is_sign ? INT64_MIN : 0;
+ uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+ dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ PUSH_I64(dst_value_i64);
+ }
+ return true;
+}
+
+static bool
+trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
+ float64 src_max, bool saturating, bool is_i32, bool is_sign)
+{
+ float64 src_value = POP_F64();
+ uint64 dst_value_i64;
+ uint32 dst_value_i32;
+
+ if (!saturating) {
+ if (isnan(src_value)) {
+ wasm_set_exception(module, "invalid conversion to integer");
+ return false;
+ }
+ else if (src_value <= src_min || src_value >= src_max) {
+ wasm_set_exception(module, "integer overflow");
+ return false;
+ }
+ }
+
+ if (is_i32) {
+ uint32 dst_min = is_sign ? INT32_MIN : 0;
+ uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+ dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ PUSH_I32(dst_value_i32);
+ }
+ else {
+ uint64 dst_min = is_sign ? INT64_MIN : 0;
+ uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+ dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ PUSH_I64(dst_value_i64);
+ }
+ return true;
+}
+
+#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) \
+ do { \
+ if (!trunc_f32_to_int(module, frame_sp, min, max, false, is_i32, \
+ is_sign)) \
+ goto got_exception; \
+ } while (0)
+
+#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) \
+ do { \
+ if (!trunc_f64_to_int(module, frame_sp, min, max, false, is_i32, \
+ is_sign)) \
+ goto got_exception; \
+ } while (0)
+
+#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) \
+ do { \
+ (void)trunc_f32_to_int(module, frame_sp, min, max, true, is_i32, \
+ is_sign); \
+ } while (0)
+
+#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) \
+ do { \
+ (void)trunc_f64_to_int(module, frame_sp, min, max, true, is_i32, \
+ is_sign); \
+ } while (0)
+
+#define DEF_OP_CONVERT(dst_type, dst_op_type, src_type, src_op_type) \
+ do { \
+ dst_type value = (dst_type)(src_type)POP_##src_op_type(); \
+ PUSH_##dst_op_type(value); \
+ } while (0)
+
+#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \
+ do { \
+ uint32 param_count = cur_func->param_count; \
+ read_leb_uint32(frame_ip, frame_ip_end, local_idx); \
+ bh_assert(local_idx < param_count + cur_func->local_count); \
+ local_offset = cur_func->local_offsets[local_idx]; \
+ if (local_idx < param_count) \
+ local_type = cur_func->param_types[local_idx]; \
+ else \
+ local_type = cur_func->local_types[local_idx - param_count]; \
+ } while (0)
+
+#define DEF_ATOMIC_RMW_OPCODE(OP_NAME, op) \
+ case WASM_OP_ATOMIC_RMW_I32_##OP_NAME: \
+ case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U: \
+ case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U: \
+ { \
+ uint32 readv, sval; \
+ \
+ sval = POP_I32(); \
+ addr = POP_I32(); \
+ \
+ if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint32)(*(uint8 *)maddr); \
+ *(uint8 *)maddr = (uint8)(readv op sval); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint32)LOAD_U16(maddr); \
+ STORE_U16(maddr, (uint16)(readv op sval)); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = LOAD_I32(maddr); \
+ STORE_U32(maddr, readv op sval); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ PUSH_I32(readv); \
+ break; \
+ } \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME: \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U: \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U: \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U: \
+ { \
+ uint64 readv, sval; \
+ \
+ sval = (uint64)POP_I64(); \
+ addr = POP_I32(); \
+ \
+ if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)(*(uint8 *)maddr); \
+ *(uint8 *)maddr = (uint8)(readv op sval); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)LOAD_U16(maddr); \
+ STORE_U16(maddr, (uint16)(readv op sval)); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)LOAD_U32(maddr); \
+ STORE_U32(maddr, (uint32)(readv op sval)); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else { \
+ uint64 op_result; \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)LOAD_I64(maddr); \
+ op_result = readv op sval; \
+ STORE_I64(maddr, op_result); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ PUSH_I64(readv); \
+ break; \
+ }
+
+static inline int32
+sign_ext_8_32(int8 val)
+{
+ if (val & 0x80)
+ return (int32)val | (int32)0xffffff00;
+ return val;
+}
+
+static inline int32
+sign_ext_16_32(int16 val)
+{
+ if (val & 0x8000)
+ return (int32)val | (int32)0xffff0000;
+ return val;
+}
+
+static inline int64
+sign_ext_8_64(int8 val)
+{
+ if (val & 0x80)
+ return (int64)val | (int64)0xffffffffffffff00LL;
+ return val;
+}
+
+static inline int64
+sign_ext_16_64(int16 val)
+{
+ if (val & 0x8000)
+ return (int64)val | (int64)0xffffffffffff0000LL;
+ return val;
+}
+
+static inline int64
+sign_ext_32_64(int32 val)
+{
+ if (val & (int32)0x80000000)
+ return (int64)val | (int64)0xffffffff00000000LL;
+ return val;
+}
+
+static inline void
+word_copy(uint32 *dest, uint32 *src, unsigned num)
+{
+ bh_assert(dest != NULL);
+ bh_assert(src != NULL);
+ bh_assert(num > 0);
+ if (dest != src) {
+ /* No overlap buffer */
+ bh_assert(!((src < dest) && (dest < src + num)));
+ for (; num > 0; num--)
+ *dest++ = *src++;
+ }
+}
+
+static inline WASMInterpFrame *
+ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame)
+{
+ WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size);
+
+ if (frame) {
+ frame->prev_frame = prev_frame;
+#if WASM_ENABLE_PERF_PROFILING != 0
+ frame->time_started = os_time_get_boot_microsecond();
+#endif
+ }
+ else {
+ wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
+ "wasm operand stack overflow");
+ }
+
+ return frame;
+}
+
+static inline void
+FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame)
+{
+#if WASM_ENABLE_PERF_PROFILING != 0
+ if (frame->function) {
+ frame->function->total_exec_time +=
+ os_time_get_boot_microsecond() - frame->time_started;
+ frame->function->total_exec_cnt++;
+ }
+#endif
+ wasm_exec_env_free_wasm_frame(exec_env, frame);
+}
+
+static void
+wasm_interp_call_func_native(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame)
+{
+ WASMFunctionImport *func_import = cur_func->u.func_import;
+ CApiFuncImport *c_api_func_import = NULL;
+ unsigned local_cell_num = 2;
+ WASMInterpFrame *frame;
+ uint32 argv_ret[2], cur_func_index;
+ void *native_func_pointer = NULL;
+ char buf[128];
+ bool ret;
+
+ 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_exec_env_set_cur_frame(exec_env, frame);
+
+ cur_func_index = (uint32)(cur_func - module_inst->e->functions);
+ bh_assert(cur_func_index < module_inst->module->import_function_count);
+ if (!func_import->call_conv_wasm_c_api) {
+ native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
+ }
+ else if (module_inst->e->c_api_func_imports) {
+ c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index;
+ native_func_pointer = c_api_func_import->func_ptr_linked;
+ }
+
+ if (!native_func_pointer) {
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ func_import->module_name, func_import->field_name);
+ wasm_set_exception(module_inst, buf);
+ return;
+ }
+
+ if (func_import->call_conv_wasm_c_api) {
+ ret = wasm_runtime_invoke_c_api_native(
+ (WASMModuleInstanceCommon *)module_inst, native_func_pointer,
+ func_import->func_type, cur_func->param_cell_num, frame->lp,
+ c_api_func_import->with_env_arg, c_api_func_import->env_arg);
+ if (ret) {
+ argv_ret[0] = frame->lp[0];
+ argv_ret[1] = frame->lp[1];
+ }
+ }
+ else if (!func_import->call_conv_raw) {
+ ret = wasm_runtime_invoke_native(
+ exec_env, native_func_pointer, func_import->func_type,
+ func_import->signature, func_import->attachment, frame->lp,
+ cur_func->param_cell_num, argv_ret);
+ }
+ else {
+ ret = wasm_runtime_invoke_native_raw(
+ exec_env, native_func_pointer, func_import->func_type,
+ func_import->signature, func_import->attachment, frame->lp,
+ cur_func->param_cell_num, argv_ret);
+ }
+
+ if (!ret)
+ return;
+
+ if (cur_func->ret_cell_num == 1) {
+ prev_frame->sp[0] = argv_ret[0];
+ prev_frame->sp++;
+ }
+ else if (cur_func->ret_cell_num == 2) {
+ prev_frame->sp[0] = argv_ret[0];
+ prev_frame->sp[1] = argv_ret[1];
+ prev_frame->sp += 2;
+ }
+
+ FREE_FRAME(exec_env, frame);
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+}
+
+#if WASM_ENABLE_FAST_JIT != 0
+bool
+fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
+ WASMInterpFrame *prev_frame)
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ WASMFunctionInstance *cur_func = module_inst->e->functions + func_idx;
+
+ wasm_interp_call_func_native(module_inst, exec_env, cur_func, prev_frame);
+ return wasm_copy_exception(module_inst, NULL) ? false : true;
+}
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static void
+wasm_interp_call_func_bytecode(WASMModuleInstance *module,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame);
+
+static void
+wasm_interp_call_func_import(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame)
+{
+ WASMModuleInstance *sub_module_inst = cur_func->import_module_inst;
+ WASMFunctionInstance *sub_func_inst = cur_func->import_func_inst;
+ WASMFunctionImport *func_import = cur_func->u.func_import;
+ uint8 *ip = prev_frame->ip;
+ char buf[128];
+ WASMExecEnv *sub_module_exec_env = NULL;
+ uint32 aux_stack_origin_boundary = 0;
+ uint32 aux_stack_origin_bottom = 0;
+
+ if (!sub_func_inst) {
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ func_import->module_name, func_import->field_name);
+ wasm_set_exception(module_inst, buf);
+ return;
+ }
+
+ /* Switch exec_env but keep using the same one by replacing necessary
+ * variables */
+ sub_module_exec_env = wasm_runtime_get_exec_env_singleton(
+ (WASMModuleInstanceCommon *)sub_module_inst);
+ if (!sub_module_exec_env) {
+ wasm_set_exception(module_inst, "create singleton exec_env failed");
+ return;
+ }
+
+ /* - module_inst */
+ exec_env->module_inst = (WASMModuleInstanceCommon *)sub_module_inst;
+ /* - aux_stack_boundary */
+ aux_stack_origin_boundary = exec_env->aux_stack_boundary.boundary;
+ exec_env->aux_stack_boundary.boundary =
+ sub_module_exec_env->aux_stack_boundary.boundary;
+ /* - aux_stack_bottom */
+ aux_stack_origin_bottom = exec_env->aux_stack_bottom.bottom;
+ exec_env->aux_stack_bottom.bottom =
+ sub_module_exec_env->aux_stack_bottom.bottom;
+
+ /* set ip NULL to make call_func_bytecode return after executing
+ this function */
+ prev_frame->ip = NULL;
+
+ /* call function of sub-module*/
+ wasm_interp_call_func_bytecode(sub_module_inst, exec_env, sub_func_inst,
+ prev_frame);
+
+ /* restore ip and other replaced */
+ prev_frame->ip = ip;
+ exec_env->aux_stack_boundary.boundary = aux_stack_origin_boundary;
+ exec_env->aux_stack_bottom.bottom = aux_stack_origin_bottom;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+
+ /* transfer exception if it is thrown */
+ if (wasm_copy_exception(sub_module_inst, NULL)) {
+ bh_memcpy_s(module_inst->cur_exception,
+ sizeof(module_inst->cur_exception),
+ sub_module_inst->cur_exception,
+ sizeof(sub_module_inst->cur_exception));
+ }
+}
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#define CHECK_SUSPEND_FLAGS() \
+ do { \
+ os_mutex_lock(&exec_env->wait_lock); \
+ if (IS_WAMR_TERM_SIG(exec_env->current_status->signal_flag)) { \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ return; \
+ } \
+ if (IS_WAMR_STOP_SIG(exec_env->current_status->signal_flag)) { \
+ SYNC_ALL_TO_FRAME(); \
+ wasm_cluster_thread_waiting_run(exec_env); \
+ } \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ } while (0)
+#else
+#define CHECK_SUSPEND_FLAGS() \
+ do { \
+ os_mutex_lock(&exec_env->wait_lock); \
+ if (exec_env->suspend_flags.flags != 0) { \
+ if (exec_env->suspend_flags.flags & 0x01) { \
+ /* terminate current thread */ \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ return; \
+ } \
+ while (exec_env->suspend_flags.flags & 0x02) { \
+ /* suspend current thread */ \
+ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
+ } \
+ } \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ } while (0)
+#endif /* WASM_ENABLE_DEBUG_INTERP */
+#endif /* WASM_ENABLE_THREAD_MGR */
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+
+#define HANDLE_OP(opcode) HANDLE_##opcode:
+#define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++]
+
+#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
+#define HANDLE_OP_END() \
+ do { \
+ /* Record the current frame_ip, so when exception occurs, \
+ debugger can know the exact opcode who caused the exception */ \
+ frame_ip_orig = frame_ip; \
+ os_mutex_lock(&exec_env->wait_lock); \
+ while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
+ && exec_env->current_status->step_count++ == 1) { \
+ exec_env->current_status->step_count = 0; \
+ SYNC_ALL_TO_FRAME(); \
+ wasm_cluster_thread_waiting_run(exec_env); \
+ } \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ goto *handle_table[*frame_ip++]; \
+ } while (0)
+#else
+#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH()
+#endif
+
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#define HANDLE_OP(opcode) case opcode:
+#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
+#define HANDLE_OP_END() \
+ os_mutex_lock(&exec_env->wait_lock); \
+ if (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
+ && exec_env->current_status->step_count++ == 2) { \
+ exec_env->current_status->step_count = 0; \
+ SYNC_ALL_TO_FRAME(); \
+ wasm_cluster_thread_waiting_run(exec_env); \
+ } \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ continue
+#else
+#define HANDLE_OP_END() continue
+#endif
+
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+
+static inline uint8 *
+get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
+{
+#if WASM_ENABLE_MULTI_MODULE == 0
+ return global_data + global->data_offset;
+#else
+ return global->import_global_inst
+ ? global->import_module_inst->global_data
+ + global->import_global_inst->data_offset
+ : global_data + global->data_offset;
+#endif
+}
+
+static void
+wasm_interp_call_func_bytecode(WASMModuleInstance *module,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame)
+{
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *node =
+ wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
+#endif
+ WASMMemoryInstance *memory = wasm_get_default_memory(module);
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ uint32 linear_mem_size = memory ? memory->memory_data_size : 0;
+#endif
+ WASMType **wasm_types = module->module->types;
+ WASMGlobalInstance *globals = module->e->globals, *global;
+ uint8 *global_data = module->global_data;
+ uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
+ WASMInterpFrame *frame = NULL;
+ /* Points to this special opcode so as to jump to the
+ * call_method_from_entry. */
+ register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */
+ register uint32 *frame_lp = NULL; /* cache of frame->lp */
+ register uint32 *frame_sp = NULL; /* cache of frame->sp */
+ WASMBranchBlock *frame_csp = NULL;
+ BlockAddr *cache_items;
+ uint8 *frame_ip_end = frame_ip + 1;
+ uint8 opcode;
+ uint32 i, depth, cond, count, fidx, tidx, lidx, frame_size = 0;
+ uint32 all_cell_num = 0;
+ int32 val;
+ uint8 *else_addr, *end_addr, *maddr = NULL;
+ uint32 local_idx, local_offset, global_idx;
+ uint8 local_type, *global_addr;
+ uint32 cache_index, type_index, param_cell_num, cell_num;
+ uint8 value_type;
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ uint8 *frame_ip_orig = NULL;
+ WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env);
+ bh_list *watch_point_list_read =
+ debug_instance ? &debug_instance->watch_point_list_read : NULL;
+ bh_list *watch_point_list_write =
+ debug_instance ? &debug_instance->watch_point_list_write : NULL;
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#define HANDLE_OPCODE(op) &&HANDLE_##op
+ DEFINE_GOTO_TABLE(const void *, handle_table);
+#undef HANDLE_OPCODE
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ while (frame_ip < frame_ip_end) {
+ opcode = *frame_ip++;
+ switch (opcode) {
+#else
+ FETCH_OPCODE_AND_DISPATCH();
+#endif
+ /* control instructions */
+ HANDLE_OP(WASM_OP_UNREACHABLE)
+ {
+ wasm_set_exception(module, "unreachable");
+ goto got_exception;
+ }
+
+ HANDLE_OP(WASM_OP_NOP) { HANDLE_OP_END(); }
+
+ HANDLE_OP(EXT_OP_BLOCK)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, type_index);
+ param_cell_num = wasm_types[type_index]->param_cell_num;
+ cell_num = wasm_types[type_index]->ret_cell_num;
+ goto handle_op_block;
+ }
+
+ HANDLE_OP(WASM_OP_BLOCK)
+ {
+ value_type = *frame_ip++;
+ param_cell_num = 0;
+ cell_num = wasm_value_type_cell_num(value_type);
+ handle_op_block:
+ cache_index = ((uintptr_t)frame_ip)
+ & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
+ cache_items = exec_env->block_addr_cache[cache_index];
+ if (cache_items[0].start_addr == frame_ip) {
+ end_addr = cache_items[0].end_addr;
+ }
+ else if (cache_items[1].start_addr == frame_ip) {
+ end_addr = cache_items[1].end_addr;
+ }
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ else if (!wasm_loader_find_block_addr(
+ exec_env, (BlockAddr *)exec_env->block_addr_cache,
+ frame_ip, (uint8 *)-1, LABEL_TYPE_BLOCK,
+ &else_addr, &end_addr)) {
+ wasm_set_exception(module, "find block address failed");
+ goto got_exception;
+ }
+#endif
+ else {
+ end_addr = NULL;
+ }
+ PUSH_CSP(LABEL_TYPE_BLOCK, param_cell_num, cell_num, end_addr);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_LOOP)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, type_index);
+ param_cell_num = wasm_types[type_index]->param_cell_num;
+ cell_num = wasm_types[type_index]->param_cell_num;
+ goto handle_op_loop;
+ }
+
+ HANDLE_OP(WASM_OP_LOOP)
+ {
+ value_type = *frame_ip++;
+ param_cell_num = 0;
+ cell_num = 0;
+ handle_op_loop:
+ PUSH_CSP(LABEL_TYPE_LOOP, param_cell_num, cell_num, frame_ip);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_IF)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, type_index);
+ param_cell_num = wasm_types[type_index]->param_cell_num;
+ cell_num = wasm_types[type_index]->ret_cell_num;
+ goto handle_op_if;
+ }
+
+ HANDLE_OP(WASM_OP_IF)
+ {
+ value_type = *frame_ip++;
+ param_cell_num = 0;
+ cell_num = wasm_value_type_cell_num(value_type);
+ handle_op_if:
+ cache_index = ((uintptr_t)frame_ip)
+ & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
+ cache_items = exec_env->block_addr_cache[cache_index];
+ if (cache_items[0].start_addr == frame_ip) {
+ else_addr = cache_items[0].else_addr;
+ end_addr = cache_items[0].end_addr;
+ }
+ else if (cache_items[1].start_addr == frame_ip) {
+ else_addr = cache_items[1].else_addr;
+ end_addr = cache_items[1].end_addr;
+ }
+ else if (!wasm_loader_find_block_addr(
+ exec_env, (BlockAddr *)exec_env->block_addr_cache,
+ frame_ip, (uint8 *)-1, LABEL_TYPE_IF, &else_addr,
+ &end_addr)) {
+ wasm_set_exception(module, "find block address failed");
+ goto got_exception;
+ }
+
+ cond = (uint32)POP_I32();
+
+ if (cond) { /* if branch is met */
+ PUSH_CSP(LABEL_TYPE_IF, param_cell_num, cell_num, end_addr);
+ }
+ else { /* if branch is not met */
+ /* if there is no else branch, go to the end addr */
+ if (else_addr == NULL) {
+ frame_ip = end_addr + 1;
+ }
+ /* if there is an else branch, go to the else addr */
+ else {
+ PUSH_CSP(LABEL_TYPE_IF, param_cell_num, cell_num,
+ end_addr);
+ frame_ip = else_addr + 1;
+ }
+ }
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_ELSE)
+ {
+ /* comes from the if branch in WASM_OP_IF */
+ frame_ip = (frame_csp - 1)->target_addr;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_END)
+ {
+ if (frame_csp > frame->csp_bottom + 1) {
+ POP_CSP();
+ }
+ else { /* end of function, treat as WASM_OP_RETURN */
+ frame_sp -= cur_func->ret_cell_num;
+ for (i = 0; i < cur_func->ret_cell_num; i++) {
+ *prev_frame->sp++ = frame_sp[i];
+ }
+ goto return_func;
+ }
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_BR)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ read_leb_uint32(frame_ip, frame_ip_end, depth);
+ label_pop_csp_n:
+ POP_CSP_N(depth);
+ if (!frame_ip) { /* must be label pushed by WASM_OP_BLOCK */
+ if (!wasm_loader_find_block_addr(
+ exec_env, (BlockAddr *)exec_env->block_addr_cache,
+ (frame_csp - 1)->begin_addr, (uint8 *)-1,
+ LABEL_TYPE_BLOCK, &else_addr, &end_addr)) {
+ wasm_set_exception(module, "find block address failed");
+ goto got_exception;
+ }
+ frame_ip = end_addr;
+ }
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_BR_IF)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ read_leb_uint32(frame_ip, frame_ip_end, depth);
+ cond = (uint32)POP_I32();
+ if (cond)
+ goto label_pop_csp_n;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_BR_TABLE)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ read_leb_uint32(frame_ip, frame_ip_end, count);
+ lidx = POP_I32();
+ if (lidx > count)
+ lidx = count;
+ depth = frame_ip[lidx];
+ goto label_pop_csp_n;
+ }
+
+ HANDLE_OP(EXT_OP_BR_TABLE_CACHE)
+ {
+ BrTableCache *node_cache =
+ bh_list_first_elem(module->module->br_table_cache_list);
+ BrTableCache *node_next;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ lidx = POP_I32();
+
+ while (node_cache) {
+ node_next = bh_list_elem_next(node_cache);
+ if (node_cache->br_table_op_addr == frame_ip - 1) {
+ depth = node_cache->br_depths[lidx];
+ goto label_pop_csp_n;
+ }
+ node_cache = node_next;
+ }
+ bh_assert(0);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_RETURN)
+ {
+ frame_sp -= cur_func->ret_cell_num;
+ for (i = 0; i < cur_func->ret_cell_num; i++) {
+ *prev_frame->sp++ = frame_sp[i];
+ }
+ goto return_func;
+ }
+
+ HANDLE_OP(WASM_OP_CALL)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ read_leb_uint32(frame_ip, frame_ip_end, fidx);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (fidx >= module->e->function_count) {
+ wasm_set_exception(module, "unknown function");
+ goto got_exception;
+ }
+#endif
+
+ cur_func = module->e->functions + fidx;
+ goto call_func_from_interp;
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ HANDLE_OP(WASM_OP_RETURN_CALL)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ read_leb_uint32(frame_ip, frame_ip_end, fidx);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (fidx >= module->e->function_count) {
+ wasm_set_exception(module, "unknown function");
+ goto got_exception;
+ }
+#endif
+ cur_func = module->e->functions + fidx;
+
+ goto call_func_from_return_call;
+ }
+#endif /* WASM_ENABLE_TAIL_CALL */
+
+ HANDLE_OP(WASM_OP_CALL_INDIRECT)
+#if WASM_ENABLE_TAIL_CALL != 0
+ HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT)
+#endif
+ {
+ WASMType *cur_type, *cur_func_type;
+ WASMTableInstance *tbl_inst;
+ uint32 tbl_idx;
+#if WASM_ENABLE_TAIL_CALL != 0
+ opcode = *(frame_ip - 1);
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+
+ /**
+ * type check. compiler will make sure all like
+ * (call_indirect (type $x) (i32.const 1))
+ * the function type has to be defined in the module also
+ * no matter it is used or not
+ */
+ read_leb_uint32(frame_ip, frame_ip_end, tidx);
+ bh_assert(tidx < module->module->type_count);
+ cur_type = wasm_types[tidx];
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ val = POP_I32();
+ if ((uint32)val >= tbl_inst->cur_size) {
+ wasm_set_exception(module, "undefined element");
+ goto got_exception;
+ }
+
+ fidx = tbl_inst->elems[val];
+ if (fidx == NULL_REF) {
+ wasm_set_exception(module, "uninitialized element");
+ goto got_exception;
+ }
+
+ /*
+ * we might be using a table injected by host or
+ * another module. In that case, we don't validate
+ * the elem value while loading
+ */
+ if (fidx >= module->e->function_count) {
+ wasm_set_exception(module, "unknown function");
+ goto got_exception;
+ }
+
+ /* always call module own functions */
+ cur_func = module->e->functions + fidx;
+
+ if (cur_func->is_import_func)
+ cur_func_type = cur_func->u.func_import->func_type;
+ else
+ cur_func_type = cur_func->u.func->func_type;
+
+ if (cur_type != cur_func_type) {
+ wasm_set_exception(module, "indirect call type mismatch");
+ goto got_exception;
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
+ goto call_func_from_return_call;
+#endif
+ goto call_func_from_interp;
+ }
+
+ /* parametric instructions */
+ HANDLE_OP(WASM_OP_DROP)
+ {
+ frame_sp--;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_DROP_64)
+ {
+ frame_sp -= 2;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SELECT)
+ {
+ cond = (uint32)POP_I32();
+ frame_sp--;
+ if (!cond)
+ *(frame_sp - 1) = *frame_sp;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SELECT_64)
+ {
+ cond = (uint32)POP_I32();
+ frame_sp -= 2;
+ if (!cond) {
+ *(frame_sp - 2) = *frame_sp;
+ *(frame_sp - 1) = *(frame_sp + 1);
+ }
+ HANDLE_OP_END();
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ HANDLE_OP(WASM_OP_SELECT_T)
+ {
+ uint32 vec_len;
+ uint8 type;
+
+ read_leb_uint32(frame_ip, frame_ip_end, vec_len);
+ type = *frame_ip++;
+
+ cond = (uint32)POP_I32();
+ if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) {
+ frame_sp -= 2;
+ if (!cond) {
+ *(frame_sp - 2) = *frame_sp;
+ *(frame_sp - 1) = *(frame_sp + 1);
+ }
+ }
+ else {
+ frame_sp--;
+ if (!cond)
+ *(frame_sp - 1) = *frame_sp;
+ }
+
+ (void)vec_len;
+ HANDLE_OP_END();
+ }
+ HANDLE_OP(WASM_OP_TABLE_GET)
+ {
+ uint32 tbl_idx, elem_idx;
+ WASMTableInstance *tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ elem_idx = POP_I32();
+ if (elem_idx >= tbl_inst->cur_size) {
+ wasm_set_exception(module, "out of bounds table access");
+ goto got_exception;
+ }
+
+ PUSH_I32(tbl_inst->elems[elem_idx]);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_TABLE_SET)
+ {
+ uint32 tbl_idx, elem_idx, elem_val;
+ WASMTableInstance *tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ elem_val = POP_I32();
+ elem_idx = POP_I32();
+ if (elem_idx >= tbl_inst->cur_size) {
+ wasm_set_exception(module, "out of bounds table access");
+ goto got_exception;
+ }
+
+ tbl_inst->elems[elem_idx] = elem_val;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_REF_NULL)
+ {
+ uint32 ref_type;
+ read_leb_uint32(frame_ip, frame_ip_end, ref_type);
+ PUSH_I32(NULL_REF);
+ (void)ref_type;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_REF_IS_NULL)
+ {
+ uint32 ref_val;
+ ref_val = POP_I32();
+ PUSH_I32(ref_val == NULL_REF ? 1 : 0);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_REF_FUNC)
+ {
+ uint32 func_idx;
+ read_leb_uint32(frame_ip, frame_ip_end, func_idx);
+ PUSH_I32(func_idx);
+ HANDLE_OP_END();
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+
+ /* variable instructions */
+ HANDLE_OP(WASM_OP_GET_LOCAL)
+ {
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ PUSH_I32(*(int32 *)(frame_lp + local_offset));
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ PUSH_I64(GET_I64_FROM_ADDR(frame_lp + local_offset));
+ break;
+ default:
+ wasm_set_exception(module, "invalid local type");
+ goto got_exception;
+ }
+
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_GET_LOCAL_FAST)
+ {
+ local_offset = *frame_ip++;
+ if (local_offset & 0x80)
+ PUSH_I64(
+ GET_I64_FROM_ADDR(frame_lp + (local_offset & 0x7F)));
+ else
+ PUSH_I32(*(int32 *)(frame_lp + local_offset));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_LOCAL)
+ {
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ *(int32 *)(frame_lp + local_offset) = POP_I32();
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset),
+ POP_I64());
+ break;
+ default:
+ wasm_set_exception(module, "invalid local type");
+ goto got_exception;
+ }
+
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_SET_LOCAL_FAST)
+ {
+ local_offset = *frame_ip++;
+ if (local_offset & 0x80)
+ PUT_I64_TO_ADDR(
+ (uint32 *)(frame_lp + (local_offset & 0x7F)),
+ POP_I64());
+ else
+ *(int32 *)(frame_lp + local_offset) = POP_I32();
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_TEE_LOCAL)
+ {
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ *(int32 *)(frame_lp + local_offset) =
+ *(int32 *)(frame_sp - 1);
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset),
+ GET_I64_FROM_ADDR(frame_sp - 2));
+ break;
+ default:
+ wasm_set_exception(module, "invalid local type");
+ goto got_exception;
+ }
+
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_TEE_LOCAL_FAST)
+ {
+ local_offset = *frame_ip++;
+ if (local_offset & 0x80)
+ PUT_I64_TO_ADDR(
+ (uint32 *)(frame_lp + (local_offset & 0x7F)),
+ GET_I64_FROM_ADDR(frame_sp - 2));
+ else
+ *(int32 *)(frame_lp + local_offset) =
+ *(int32 *)(frame_sp - 1);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_GET_GLOBAL)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ PUSH_I32(*(uint32 *)global_addr);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_GET_GLOBAL_64)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ PUSH_I64(GET_I64_FROM_ADDR((uint32 *)global_addr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_GLOBAL)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ *(int32 *)global_addr = POP_I32();
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_GLOBAL_AUX_STACK)
+ {
+ uint32 aux_stack_top;
+
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ aux_stack_top = *(uint32 *)(frame_sp - 1);
+ if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) {
+ wasm_set_exception(module, "wasm auxiliary stack overflow");
+ goto got_exception;
+ }
+ if (aux_stack_top > exec_env->aux_stack_bottom.bottom) {
+ wasm_set_exception(module,
+ "wasm auxiliary stack underflow");
+ goto got_exception;
+ }
+ *(int32 *)global_addr = aux_stack_top;
+ frame_sp--;
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ if (module->module->aux_stack_top_global_index != (uint32)-1) {
+ uint32 aux_stack_used = module->module->aux_stack_bottom
+ - *(uint32 *)global_addr;
+ if (aux_stack_used > module->e->max_aux_stack_used)
+ module->e->max_aux_stack_used = aux_stack_used;
+ }
+#endif
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_GLOBAL_64)
+ {
+ read_leb_uint32(frame_ip, frame_ip_end, global_idx);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ PUT_I64_TO_ADDR((uint32 *)global_addr, POP_I64());
+ HANDLE_OP_END();
+ }
+
+ /* memory load instructions */
+ HANDLE_OP(WASM_OP_I32_LOAD)
+ HANDLE_OP(WASM_OP_F32_LOAD)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(4);
+ PUSH_I32(LOAD_I32(maddr));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD)
+ HANDLE_OP(WASM_OP_F64_LOAD)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(8);
+ PUSH_I64(LOAD_I64(maddr));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD8_S)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(1);
+ PUSH_I32(sign_ext_8_32(*(int8 *)maddr));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD8_U)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(1);
+ PUSH_I32((uint32)(*(uint8 *)maddr));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD16_S)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(2);
+ PUSH_I32(sign_ext_16_32(LOAD_I16(maddr)));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD16_U)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(2);
+ PUSH_I32((uint32)(LOAD_U16(maddr)));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD8_S)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(1);
+ PUSH_I64(sign_ext_8_64(*(int8 *)maddr));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD8_U)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(1);
+ PUSH_I64((uint64)(*(uint8 *)maddr));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD16_S)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(2);
+ PUSH_I64(sign_ext_16_64(LOAD_I16(maddr)));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD16_U)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(2);
+ PUSH_I64((uint64)(LOAD_U16(maddr)));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD32_S)
+ {
+ uint32 offset, flags, addr;
+
+ opcode = *(frame_ip - 1);
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(4);
+ PUSH_I64(sign_ext_32_64(LOAD_I32(maddr)));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD32_U)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(4);
+ PUSH_I64((uint64)(LOAD_U32(maddr)));
+ CHECK_READ_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ /* memory store instructions */
+ HANDLE_OP(WASM_OP_I32_STORE)
+ HANDLE_OP(WASM_OP_F32_STORE)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ frame_sp--;
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(4);
+ STORE_U32(maddr, frame_sp[1]);
+ CHECK_WRITE_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_STORE)
+ HANDLE_OP(WASM_OP_F64_STORE)
+ {
+ uint32 offset, flags, addr;
+
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ frame_sp -= 2;
+ addr = POP_I32();
+ CHECK_MEMORY_OVERFLOW(8);
+ PUT_I64_TO_ADDR((uint32 *)maddr,
+ GET_I64_FROM_ADDR(frame_sp + 1));
+ CHECK_WRITE_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_STORE8)
+ HANDLE_OP(WASM_OP_I32_STORE16)
+ {
+ uint32 offset, flags, addr;
+ uint32 sval;
+
+ opcode = *(frame_ip - 1);
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ sval = (uint32)POP_I32();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_I32_STORE8) {
+ CHECK_MEMORY_OVERFLOW(1);
+ *(uint8 *)maddr = (uint8)sval;
+ }
+ else {
+ CHECK_MEMORY_OVERFLOW(2);
+ STORE_U16(maddr, (uint16)sval);
+ }
+ CHECK_WRITE_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_STORE8)
+ HANDLE_OP(WASM_OP_I64_STORE16)
+ HANDLE_OP(WASM_OP_I64_STORE32)
+ {
+ uint32 offset, flags, addr;
+ uint64 sval;
+
+ opcode = *(frame_ip - 1);
+ read_leb_uint32(frame_ip, frame_ip_end, flags);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ sval = (uint64)POP_I64();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_I64_STORE8) {
+ CHECK_MEMORY_OVERFLOW(1);
+ *(uint8 *)maddr = (uint8)sval;
+ }
+ else if (opcode == WASM_OP_I64_STORE16) {
+ CHECK_MEMORY_OVERFLOW(2);
+ STORE_U16(maddr, (uint16)sval);
+ }
+ else {
+ CHECK_MEMORY_OVERFLOW(4);
+ STORE_U32(maddr, (uint32)sval);
+ }
+ CHECK_WRITE_WATCHPOINT(addr, offset);
+ (void)flags;
+ HANDLE_OP_END();
+ }
+
+ /* memory size and memory grow instructions */
+ HANDLE_OP(WASM_OP_MEMORY_SIZE)
+ {
+ uint32 reserved;
+ read_leb_uint32(frame_ip, frame_ip_end, reserved);
+ PUSH_I32(memory->cur_page_count);
+ (void)reserved;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_MEMORY_GROW)
+ {
+ uint32 reserved, delta,
+ prev_page_count = memory->cur_page_count;
+
+ read_leb_uint32(frame_ip, frame_ip_end, reserved);
+ delta = (uint32)POP_I32();
+
+ if (!wasm_enlarge_memory(module, delta)) {
+ /* failed to memory.grow, return -1 */
+ PUSH_I32(-1);
+ }
+ else {
+ /* success, return previous page count */
+ PUSH_I32(prev_page_count);
+ /* update memory size, no need to update memory ptr as
+ it isn't changed in wasm_enlarge_memory */
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ linear_mem_size = memory->memory_data_size;
+#endif
+ }
+
+ (void)reserved;
+ HANDLE_OP_END();
+ }
+
+ /* constant instructions */
+ HANDLE_OP(WASM_OP_I32_CONST)
+ DEF_OP_I_CONST(int32, I32);
+ HANDLE_OP_END();
+
+ HANDLE_OP(WASM_OP_I64_CONST)
+ DEF_OP_I_CONST(int64, I64);
+ HANDLE_OP_END();
+
+ HANDLE_OP(WASM_OP_F32_CONST)
+ {
+ uint8 *p_float = (uint8 *)frame_sp++;
+ for (i = 0; i < sizeof(float32); i++)
+ *p_float++ = *frame_ip++;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONST)
+ {
+ uint8 *p_float = (uint8 *)frame_sp++;
+ frame_sp++;
+ for (i = 0; i < sizeof(float64); i++)
+ *p_float++ = *frame_ip++;
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of i32 */
+ HANDLE_OP(WASM_OP_I32_EQZ)
+ {
+ DEF_OP_EQZ(I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_EQ)
+ {
+ DEF_OP_CMP(uint32, I32, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_NE)
+ {
+ DEF_OP_CMP(uint32, I32, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LT_S)
+ {
+ DEF_OP_CMP(int32, I32, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LT_U)
+ {
+ DEF_OP_CMP(uint32, I32, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GT_S)
+ {
+ DEF_OP_CMP(int32, I32, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GT_U)
+ {
+ DEF_OP_CMP(uint32, I32, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LE_S)
+ {
+ DEF_OP_CMP(int32, I32, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LE_U)
+ {
+ DEF_OP_CMP(uint32, I32, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GE_S)
+ {
+ DEF_OP_CMP(int32, I32, >=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GE_U)
+ {
+ DEF_OP_CMP(uint32, I32, >=);
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of i64 */
+ HANDLE_OP(WASM_OP_I64_EQZ)
+ {
+ DEF_OP_EQZ(I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EQ)
+ {
+ DEF_OP_CMP(uint64, I64, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_NE)
+ {
+ DEF_OP_CMP(uint64, I64, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LT_S)
+ {
+ DEF_OP_CMP(int64, I64, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LT_U)
+ {
+ DEF_OP_CMP(uint64, I64, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GT_S)
+ {
+ DEF_OP_CMP(int64, I64, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GT_U)
+ {
+ DEF_OP_CMP(uint64, I64, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LE_S)
+ {
+ DEF_OP_CMP(int64, I64, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LE_U)
+ {
+ DEF_OP_CMP(uint64, I64, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GE_S)
+ {
+ DEF_OP_CMP(int64, I64, >=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GE_U)
+ {
+ DEF_OP_CMP(uint64, I64, >=);
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of f32 */
+ HANDLE_OP(WASM_OP_F32_EQ)
+ {
+ DEF_OP_CMP(float32, F32, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_NE)
+ {
+ DEF_OP_CMP(float32, F32, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_LT)
+ {
+ DEF_OP_CMP(float32, F32, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_GT)
+ {
+ DEF_OP_CMP(float32, F32, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_LE)
+ {
+ DEF_OP_CMP(float32, F32, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_GE)
+ {
+ DEF_OP_CMP(float32, F32, >=);
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of f64 */
+ HANDLE_OP(WASM_OP_F64_EQ)
+ {
+ DEF_OP_CMP(float64, F64, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_NE)
+ {
+ DEF_OP_CMP(float64, F64, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_LT)
+ {
+ DEF_OP_CMP(float64, F64, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_GT)
+ {
+ DEF_OP_CMP(float64, F64, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_LE)
+ {
+ DEF_OP_CMP(float64, F64, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_GE)
+ {
+ DEF_OP_CMP(float64, F64, >=);
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of i32 */
+ HANDLE_OP(WASM_OP_I32_CLZ)
+ {
+ DEF_OP_BIT_COUNT(uint32, I32, clz32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_CTZ)
+ {
+ DEF_OP_BIT_COUNT(uint32, I32, ctz32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_POPCNT)
+ {
+ DEF_OP_BIT_COUNT(uint32, I32, popcount32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_ADD)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SUB)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_MUL)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_DIV_S)
+ {
+ int32 a, b;
+
+ b = POP_I32();
+ a = POP_I32();
+ if (a == (int32)0x80000000 && b == -1) {
+ wasm_set_exception(module, "integer overflow");
+ goto got_exception;
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I32(a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_DIV_U)
+ {
+ uint32 a, b;
+
+ b = (uint32)POP_I32();
+ a = (uint32)POP_I32();
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I32(a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_REM_S)
+ {
+ int32 a, b;
+
+ b = POP_I32();
+ a = POP_I32();
+ if (a == (int32)0x80000000 && b == -1) {
+ PUSH_I32(0);
+ HANDLE_OP_END();
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I32(a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_REM_U)
+ {
+ uint32 a, b;
+
+ b = (uint32)POP_I32();
+ a = (uint32)POP_I32();
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I32(a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_AND)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, &);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_OR)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, |);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_XOR)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, ^);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SHL)
+ {
+ DEF_OP_NUMERIC2(uint32, uint32, I32, <<);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SHR_S)
+ {
+ DEF_OP_NUMERIC2(int32, uint32, I32, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SHR_U)
+ {
+ DEF_OP_NUMERIC2(uint32, uint32, I32, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_ROTL)
+ {
+ uint32 a, b;
+
+ b = (uint32)POP_I32();
+ a = (uint32)POP_I32();
+ PUSH_I32(rotl32(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_ROTR)
+ {
+ uint32 a, b;
+
+ b = (uint32)POP_I32();
+ a = (uint32)POP_I32();
+ PUSH_I32(rotr32(a, b));
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of i64 */
+ HANDLE_OP(WASM_OP_I64_CLZ)
+ {
+ DEF_OP_BIT_COUNT(uint64, I64, clz64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_CTZ)
+ {
+ DEF_OP_BIT_COUNT(uint64, I64, ctz64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_POPCNT)
+ {
+ DEF_OP_BIT_COUNT(uint64, I64, popcount64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_ADD)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SUB)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_MUL)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_DIV_S)
+ {
+ int64 a, b;
+
+ b = POP_I64();
+ a = POP_I64();
+ if (a == (int64)0x8000000000000000LL && b == -1) {
+ wasm_set_exception(module, "integer overflow");
+ goto got_exception;
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I64(a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_DIV_U)
+ {
+ uint64 a, b;
+
+ b = (uint64)POP_I64();
+ a = (uint64)POP_I64();
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I64(a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_REM_S)
+ {
+ int64 a, b;
+
+ b = POP_I64();
+ a = POP_I64();
+ if (a == (int64)0x8000000000000000LL && b == -1) {
+ PUSH_I64(0);
+ HANDLE_OP_END();
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I64(a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_REM_U)
+ {
+ uint64 a, b;
+
+ b = (uint64)POP_I64();
+ a = (uint64)POP_I64();
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUSH_I64(a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_AND)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, &);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_OR)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, |);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_XOR)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, ^);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SHL)
+ {
+ DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SHR_S)
+ {
+ DEF_OP_NUMERIC2_64(int64, uint64, I64, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SHR_U)
+ {
+ DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_ROTL)
+ {
+ uint64 a, b;
+
+ b = (uint64)POP_I64();
+ a = (uint64)POP_I64();
+ PUSH_I64(rotl64(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_ROTR)
+ {
+ uint64 a, b;
+
+ b = (uint64)POP_I64();
+ a = (uint64)POP_I64();
+ PUSH_I64(rotr64(a, b));
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of f32 */
+ HANDLE_OP(WASM_OP_F32_ABS)
+ {
+ DEF_OP_MATH(float32, F32, fabsf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_NEG)
+ {
+ uint32 u32 = frame_sp[-1];
+ uint32 sign_bit = u32 & ((uint32)1 << 31);
+ if (sign_bit)
+ frame_sp[-1] = u32 & ~((uint32)1 << 31);
+ else
+ frame_sp[-1] = u32 | ((uint32)1 << 31);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CEIL)
+ {
+ DEF_OP_MATH(float32, F32, ceilf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_FLOOR)
+ {
+ DEF_OP_MATH(float32, F32, floorf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_TRUNC)
+ {
+ DEF_OP_MATH(float32, F32, truncf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_NEAREST)
+ {
+ DEF_OP_MATH(float32, F32, rintf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_SQRT)
+ {
+ DEF_OP_MATH(float32, F32, sqrtf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_ADD)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_SUB)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_MUL)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_DIV)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, /);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_MIN)
+ {
+ float32 a, b;
+
+ b = POP_F32();
+ a = POP_F32();
+
+ PUSH_F32(f32_min(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_MAX)
+ {
+ float32 a, b;
+
+ b = POP_F32();
+ a = POP_F32();
+
+ PUSH_F32(f32_max(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_COPYSIGN)
+ {
+ float32 a, b;
+
+ b = POP_F32();
+ a = POP_F32();
+ PUSH_F32(local_copysignf(a, b));
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of f64 */
+ HANDLE_OP(WASM_OP_F64_ABS)
+ {
+ DEF_OP_MATH(float64, F64, fabs);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_NEG)
+ {
+ uint64 u64 = GET_I64_FROM_ADDR(frame_sp - 2);
+ uint64 sign_bit = u64 & (((uint64)1) << 63);
+ if (sign_bit)
+ PUT_I64_TO_ADDR(frame_sp - 2, (u64 & ~(((uint64)1) << 63)));
+ else
+ PUT_I64_TO_ADDR(frame_sp - 2, (u64 | (((uint64)1) << 63)));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CEIL)
+ {
+ DEF_OP_MATH(float64, F64, ceil);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_FLOOR)
+ {
+ DEF_OP_MATH(float64, F64, floor);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_TRUNC)
+ {
+ DEF_OP_MATH(float64, F64, trunc);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_NEAREST)
+ {
+ DEF_OP_MATH(float64, F64, rint);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_SQRT)
+ {
+ DEF_OP_MATH(float64, F64, sqrt);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_ADD)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_SUB)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_MUL)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_DIV)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, /);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_MIN)
+ {
+ float64 a, b;
+
+ b = POP_F64();
+ a = POP_F64();
+
+ PUSH_F64(f64_min(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_MAX)
+ {
+ float64 a, b;
+
+ b = POP_F64();
+ a = POP_F64();
+
+ PUSH_F64(f64_max(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_COPYSIGN)
+ {
+ float64 a, b;
+
+ b = POP_F64();
+ a = POP_F64();
+ PUSH_F64(local_copysign(a, b));
+ HANDLE_OP_END();
+ }
+
+ /* conversions of i32 */
+ HANDLE_OP(WASM_OP_I32_WRAP_I64)
+ {
+ int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL);
+ PUSH_I32(value);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_S_F32)
+ {
+ /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX,
+ since float/double values of ieee754 cannot precisely
+ represent all int32/uint32/int64/uint64 values, e.g.
+ UINT32_MAX is 4294967295, but (float32)4294967295 is
+ 4294967296.0f, but not 4294967295.0f. */
+ DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_U_F32)
+ {
+ DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_S_F64)
+ {
+ DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true);
+ /* frame_sp can't be moved in trunc function, we need to
+ manually adjust it if src and dst op's cell num is
+ different */
+ frame_sp--;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_U_F64)
+ {
+ DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false);
+ frame_sp--;
+ HANDLE_OP_END();
+ }
+
+ /* conversions of i64 */
+ HANDLE_OP(WASM_OP_I64_EXTEND_S_I32)
+ {
+ DEF_OP_CONVERT(int64, I64, int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND_U_I32)
+ {
+ DEF_OP_CONVERT(int64, I64, uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_S_F32)
+ {
+ DEF_OP_TRUNC_F32(-9223373136366403584.0f,
+ 9223372036854775808.0f, false, true);
+ frame_sp++;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_U_F32)
+ {
+ DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f, false, false);
+ frame_sp++;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_S_F64)
+ {
+ DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0,
+ false, true);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_U_F64)
+ {
+ DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0, false, false);
+ HANDLE_OP_END();
+ }
+
+ /* conversions of f32 */
+ HANDLE_OP(WASM_OP_F32_CONVERT_S_I32)
+ {
+ DEF_OP_CONVERT(float32, F32, int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONVERT_U_I32)
+ {
+ DEF_OP_CONVERT(float32, F32, uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONVERT_S_I64)
+ {
+ DEF_OP_CONVERT(float32, F32, int64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONVERT_U_I64)
+ {
+ DEF_OP_CONVERT(float32, F32, uint64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_DEMOTE_F64)
+ {
+ DEF_OP_CONVERT(float32, F32, float64, F64);
+ HANDLE_OP_END();
+ }
+
+ /* conversions of f64 */
+ HANDLE_OP(WASM_OP_F64_CONVERT_S_I32)
+ {
+ DEF_OP_CONVERT(float64, F64, int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONVERT_U_I32)
+ {
+ DEF_OP_CONVERT(float64, F64, uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONVERT_S_I64)
+ {
+ DEF_OP_CONVERT(float64, F64, int64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONVERT_U_I64)
+ {
+ DEF_OP_CONVERT(float64, F64, uint64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_PROMOTE_F32)
+ {
+ DEF_OP_CONVERT(float64, F64, float32, F32);
+ HANDLE_OP_END();
+ }
+
+ /* reinterpretations */
+ HANDLE_OP(WASM_OP_I32_REINTERPRET_F32)
+ HANDLE_OP(WASM_OP_I64_REINTERPRET_F64)
+ HANDLE_OP(WASM_OP_F32_REINTERPRET_I32)
+ HANDLE_OP(WASM_OP_F64_REINTERPRET_I64) { HANDLE_OP_END(); }
+
+ HANDLE_OP(WASM_OP_I32_EXTEND8_S)
+ {
+ DEF_OP_CONVERT(int32, I32, int8, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_EXTEND16_S)
+ {
+ DEF_OP_CONVERT(int32, I32, int16, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND8_S)
+ {
+ DEF_OP_CONVERT(int64, I64, int8, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND16_S)
+ {
+ DEF_OP_CONVERT(int64, I64, int16, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND32_S)
+ {
+ DEF_OP_CONVERT(int64, I64, int32, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_MISC_PREFIX)
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(frame_ip, frame_ip_end, opcode1);
+ opcode = (uint8)opcode1;
+
+ switch (opcode) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f,
+ true, true);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f, true, false);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0, true,
+ true);
+ frame_sp--;
+ break;
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0, true, false);
+ frame_sp--;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f,
+ 9223372036854775808.0f, false,
+ true);
+ frame_sp++;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f,
+ false, false);
+ frame_sp++;
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0,
+ 9223372036854775808.0, false,
+ true);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ DEF_OP_TRUNC_SAT_F64(-1.0f, 18446744073709551616.0,
+ false, false);
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ {
+ uint32 addr, segment;
+ uint64 bytes, offset, seg_len;
+ uint8 *data;
+
+ read_leb_uint32(frame_ip, frame_ip_end, segment);
+ /* skip memory index */
+ frame_ip++;
+
+ bytes = (uint64)(uint32)POP_I32();
+ offset = (uint64)(uint32)POP_I32();
+ addr = (uint32)POP_I32();
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ linear_mem_size = memory->memory_data_size;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr);
+#else
+ if ((uint64)(uint32)addr + bytes
+ > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ maddr = memory->memory_data + (uint32)addr;
+#endif
+
+ seg_len = (uint64)module->module->data_segments[segment]
+ ->data_length;
+ data = module->module->data_segments[segment]->data;
+ if (offset + bytes > seg_len)
+ goto out_of_bounds;
+
+ bh_memcpy_s(maddr, linear_mem_size - addr,
+ data + offset, (uint32)bytes);
+ break;
+ }
+ case WASM_OP_DATA_DROP:
+ {
+ uint32 segment;
+
+ read_leb_uint32(frame_ip, frame_ip_end, segment);
+ module->module->data_segments[segment]->data_length = 0;
+ break;
+ }
+ case WASM_OP_MEMORY_COPY:
+ {
+ uint32 dst, src, len;
+ uint8 *mdst, *msrc;
+
+ frame_ip += 2;
+
+ len = POP_I32();
+ src = POP_I32();
+ dst = POP_I32();
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ linear_mem_size = memory->memory_data_size;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc);
+ CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
+#else
+ if ((uint64)(uint32)src + len > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ msrc = memory->memory_data + (uint32)src;
+
+ if ((uint64)(uint32)dst + len > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ mdst = memory->memory_data + (uint32)dst;
+#endif
+
+ /* allowing the destination and source to overlap */
+ bh_memmove_s(mdst, linear_mem_size - dst, msrc, len);
+ break;
+ }
+ case WASM_OP_MEMORY_FILL:
+ {
+ uint32 dst, len;
+ uint8 fill_val, *mdst;
+ frame_ip++;
+
+ len = POP_I32();
+ fill_val = POP_I32();
+ dst = POP_I32();
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ linear_mem_size = memory->memory_data_size;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
+#else
+ if ((uint64)(uint32)dst + len > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ mdst = memory->memory_data + (uint32)dst;
+#endif
+
+ memset(mdst, fill_val, len);
+ break;
+ }
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ {
+ uint32 tbl_idx, elem_idx;
+ uint64 n, s, d;
+ WASMTableInstance *tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
+ bh_assert(elem_idx < module->module->table_seg_count);
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ n = (uint32)POP_I32();
+ s = (uint32)POP_I32();
+ d = (uint32)POP_I32();
+
+ /* TODO: what if the element is not passive? */
+
+ if (!n) {
+ break;
+ }
+
+ if (n + s > module->module->table_segments[elem_idx]
+ .function_count
+ || d + n > tbl_inst->cur_size) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ if (module->module->table_segments[elem_idx]
+ .is_dropped) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ if (!wasm_elem_is_passive(
+ module->module->table_segments[elem_idx]
+ .mode)) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ bh_memcpy_s(
+ (uint8 *)tbl_inst
+ + offsetof(WASMTableInstance, elems)
+ + d * sizeof(uint32),
+ (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)),
+ module->module->table_segments[elem_idx]
+ .func_indexes
+ + s,
+ (uint32)(n * sizeof(uint32)));
+
+ break;
+ }
+ case WASM_OP_ELEM_DROP:
+ {
+ uint32 elem_idx;
+ read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
+ bh_assert(elem_idx < module->module->table_seg_count);
+
+ module->module->table_segments[elem_idx].is_dropped =
+ true;
+ break;
+ }
+ case WASM_OP_TABLE_COPY:
+ {
+ uint32 src_tbl_idx, dst_tbl_idx;
+ uint64 n, s, d;
+ WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
+ bh_assert(dst_tbl_idx < module->table_count);
+
+ dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx);
+
+ read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx);
+ bh_assert(src_tbl_idx < module->table_count);
+
+ src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx);
+
+ n = (uint32)POP_I32();
+ s = (uint32)POP_I32();
+ d = (uint32)POP_I32();
+
+ if (d + n > dst_tbl_inst->cur_size
+ || s + n > src_tbl_inst->cur_size) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ /* if s >= d, copy from front to back */
+ /* if s < d, copy from back to front */
+ /* merge all together */
+ bh_memmove_s((uint8 *)dst_tbl_inst
+ + offsetof(WASMTableInstance, elems)
+ + d * sizeof(uint32),
+ (uint32)((dst_tbl_inst->cur_size - d)
+ * sizeof(uint32)),
+ (uint8 *)src_tbl_inst
+ + offsetof(WASMTableInstance, elems)
+ + s * sizeof(uint32),
+ (uint32)(n * sizeof(uint32)));
+ break;
+ }
+ case WASM_OP_TABLE_GROW:
+ {
+ uint32 tbl_idx, n, init_val, orig_tbl_sz;
+ WASMTableInstance *tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ orig_tbl_sz = tbl_inst->cur_size;
+
+ n = POP_I32();
+ init_val = POP_I32();
+
+ if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) {
+ PUSH_I32(-1);
+ }
+ else {
+ PUSH_I32(orig_tbl_sz);
+ }
+ break;
+ }
+ case WASM_OP_TABLE_SIZE:
+ {
+ uint32 tbl_idx;
+ WASMTableInstance *tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ PUSH_I32(tbl_inst->cur_size);
+ break;
+ }
+ case WASM_OP_TABLE_FILL:
+ {
+ uint32 tbl_idx, n, fill_val;
+ WASMTableInstance *tbl_inst;
+
+ read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ n = POP_I32();
+ fill_val = POP_I32();
+ i = POP_I32();
+
+ /* TODO: what if the element is not passive? */
+ /* TODO: what if the element is dropped? */
+
+ if (i + n > tbl_inst->cur_size) {
+ /* TODO: verify warning content */
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ for (; n != 0; i++, n--) {
+ tbl_inst->elems[i] = fill_val;
+ }
+
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ wasm_set_exception(module, "unsupported opcode");
+ goto got_exception;
+ }
+ HANDLE_OP_END();
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ HANDLE_OP(WASM_OP_ATOMIC_PREFIX)
+ {
+ uint32 offset = 0, align, addr;
+
+ opcode = *frame_ip++;
+
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ read_leb_uint32(frame_ip, frame_ip_end, align);
+ read_leb_uint32(frame_ip, frame_ip_end, offset);
+ }
+
+ switch (opcode) {
+ case WASM_OP_ATOMIC_NOTIFY:
+ {
+ uint32 notify_count, ret;
+
+ notify_count = POP_I32();
+ addr = POP_I32();
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ ret = wasm_runtime_atomic_notify(
+ (WASMModuleInstanceCommon *)module, maddr,
+ notify_count);
+ if (ret == (uint32)-1)
+ goto got_exception;
+
+ PUSH_I32(ret);
+ break;
+ }
+ case WASM_OP_ATOMIC_WAIT32:
+ {
+ uint64 timeout;
+ uint32 expect, ret;
+
+ timeout = POP_I64();
+ expect = POP_I32();
+ addr = POP_I32();
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ ret = wasm_runtime_atomic_wait(
+ (WASMModuleInstanceCommon *)module, maddr,
+ (uint64)expect, timeout, false);
+ if (ret == (uint32)-1)
+ goto got_exception;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+
+ PUSH_I32(ret);
+ break;
+ }
+ case WASM_OP_ATOMIC_WAIT64:
+ {
+ uint64 timeout, expect;
+ uint32 ret;
+
+ timeout = POP_I64();
+ expect = POP_I64();
+ addr = POP_I32();
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ ret = wasm_runtime_atomic_wait(
+ (WASMModuleInstanceCommon *)module, maddr, expect,
+ timeout, true);
+ if (ret == (uint32)-1)
+ goto got_exception;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+
+ PUSH_I32(ret);
+ break;
+ }
+ case WASM_OP_ATOMIC_FENCE:
+ {
+ /* Skip the memory index */
+ frame_ip++;
+ os_atomic_thread_fence(os_memory_order_seq_cst);
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I32_LOAD:
+ case WASM_OP_ATOMIC_I32_LOAD8_U:
+ case WASM_OP_ATOMIC_I32_LOAD16_U:
+ {
+ uint32 readv;
+
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)(*(uint8 *)maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)LOAD_U16(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = LOAD_I32(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+
+ PUSH_I32(readv);
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I64_LOAD:
+ case WASM_OP_ATOMIC_I64_LOAD8_U:
+ case WASM_OP_ATOMIC_I64_LOAD16_U:
+ case WASM_OP_ATOMIC_I64_LOAD32_U:
+ {
+ uint64 readv;
+
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)(*(uint8 *)maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U16(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U32(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = LOAD_I64(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+
+ PUSH_I64(readv);
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I32_STORE:
+ case WASM_OP_ATOMIC_I32_STORE8:
+ case WASM_OP_ATOMIC_I32_STORE16:
+ {
+ uint32 sval;
+
+ sval = (uint32)POP_I32();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ *(uint8 *)maddr = (uint8)sval;
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U16(maddr, (uint16)sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U32(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I64_STORE:
+ case WASM_OP_ATOMIC_I64_STORE8:
+ case WASM_OP_ATOMIC_I64_STORE16:
+ case WASM_OP_ATOMIC_I64_STORE32:
+ {
+ uint64 sval;
+
+ sval = (uint64)POP_I64();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ *(uint8 *)maddr = (uint8)sval;
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U16(maddr, (uint16)sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U32(maddr, (uint32)sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+ os_mutex_lock(&node->shared_mem_lock);
+ PUT_I64_TO_ADDR((uint32 *)maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ break;
+ }
+
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
+ {
+ uint32 readv, sval, expect;
+
+ sval = POP_I32();
+ expect = POP_I32();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ expect = (uint8)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)(*(uint8 *)maddr);
+ if (readv == expect)
+ *(uint8 *)maddr = (uint8)(sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ expect = (uint16)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)LOAD_U16(maddr);
+ if (readv == expect)
+ STORE_U16(maddr, (uint16)(sval));
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = LOAD_I32(maddr);
+ if (readv == expect)
+ STORE_U32(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ PUSH_I32(readv);
+ break;
+ }
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
+ {
+ uint64 readv, sval, expect;
+
+ sval = (uint64)POP_I64();
+ expect = (uint64)POP_I64();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ expect = (uint8)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)(*(uint8 *)maddr);
+ if (readv == expect)
+ *(uint8 *)maddr = (uint8)(sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ expect = (uint16)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U16(maddr);
+ if (readv == expect)
+ STORE_U16(maddr, (uint16)(sval));
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ expect = (uint32)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U32(maddr);
+ if (readv == expect)
+ STORE_U32(maddr, (uint32)(sval));
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS();
+
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_I64(maddr);
+ if (readv == expect)
+ STORE_I64(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ PUSH_I64(readv);
+ break;
+ }
+
+ DEF_ATOMIC_RMW_OPCODE(ADD, +);
+ DEF_ATOMIC_RMW_OPCODE(SUB, -);
+ DEF_ATOMIC_RMW_OPCODE(AND, &);
+ DEF_ATOMIC_RMW_OPCODE(OR, |);
+ DEF_ATOMIC_RMW_OPCODE(XOR, ^);
+ /* xchg, ignore the read value, and store the given
+ value: readv * 0 + sval */
+ DEF_ATOMIC_RMW_OPCODE(XCHG, *0 +);
+ }
+
+ HANDLE_OP_END();
+ }
+#endif
+
+ HANDLE_OP(WASM_OP_IMPDEP)
+ {
+ frame = prev_frame;
+ frame_ip = frame->ip;
+ frame_sp = frame->sp;
+ frame_csp = frame->csp;
+ goto call_func_from_entry;
+ }
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ HANDLE_OP(DEBUG_OP_BREAK)
+ {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
+ exec_env->suspend_flags.flags |= 2;
+ frame_ip--;
+ SYNC_ALL_TO_FRAME();
+ CHECK_SUSPEND_FLAGS();
+ HANDLE_OP_END();
+ }
+#endif
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ default:
+ wasm_set_exception(module, "unsupported opcode");
+ goto got_exception;
+ }
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+ HANDLE_OP(WASM_OP_UNUSED_0x06)
+ HANDLE_OP(WASM_OP_UNUSED_0x07)
+ HANDLE_OP(WASM_OP_UNUSED_0x08)
+ HANDLE_OP(WASM_OP_UNUSED_0x09)
+ HANDLE_OP(WASM_OP_UNUSED_0x0a)
+#if WASM_ENABLE_TAIL_CALL == 0
+ HANDLE_OP(WASM_OP_RETURN_CALL)
+ HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT)
+#endif
+#if WASM_ENABLE_SHARED_MEMORY == 0
+ HANDLE_OP(WASM_OP_ATOMIC_PREFIX)
+#endif
+#if WASM_ENABLE_REF_TYPES == 0
+ HANDLE_OP(WASM_OP_SELECT_T)
+ HANDLE_OP(WASM_OP_TABLE_GET)
+ HANDLE_OP(WASM_OP_TABLE_SET)
+ HANDLE_OP(WASM_OP_REF_NULL)
+ HANDLE_OP(WASM_OP_REF_IS_NULL)
+ HANDLE_OP(WASM_OP_REF_FUNC)
+#endif
+ HANDLE_OP(WASM_OP_UNUSED_0x14)
+ HANDLE_OP(WASM_OP_UNUSED_0x15)
+ HANDLE_OP(WASM_OP_UNUSED_0x16)
+ HANDLE_OP(WASM_OP_UNUSED_0x17)
+ HANDLE_OP(WASM_OP_UNUSED_0x18)
+ HANDLE_OP(WASM_OP_UNUSED_0x19)
+ HANDLE_OP(WASM_OP_UNUSED_0x27)
+ /* Used by fast interpreter */
+ HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64)
+ HANDLE_OP(EXT_OP_TEE_LOCAL_FAST_I64)
+ HANDLE_OP(EXT_OP_COPY_STACK_TOP)
+ HANDLE_OP(EXT_OP_COPY_STACK_TOP_I64)
+ HANDLE_OP(EXT_OP_COPY_STACK_VALUES)
+ {
+ wasm_set_exception(module, "unsupported opcode");
+ goto got_exception;
+ }
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ continue;
+#else
+ FETCH_OPCODE_AND_DISPATCH();
+#endif
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ call_func_from_return_call:
+ {
+ POP(cur_func->param_cell_num);
+ if (cur_func->param_cell_num > 0) {
+ word_copy(frame->lp, frame_sp, cur_func->param_cell_num);
+ }
+ FREE_FRAME(exec_env, frame);
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+ goto call_func_from_entry;
+ }
+#endif
+ call_func_from_interp:
+ {
+ /* Only do the copy when it's called from interpreter. */
+ WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env);
+ POP(cur_func->param_cell_num);
+ SYNC_ALL_TO_FRAME();
+ if (cur_func->param_cell_num > 0) {
+ word_copy(outs_area->lp, frame_sp, cur_func->param_cell_num);
+ }
+ prev_frame = frame;
+ }
+
+ call_func_from_entry:
+ {
+ if (cur_func->is_import_func) {
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (cur_func->import_func_inst) {
+ wasm_interp_call_func_import(module, exec_env, cur_func,
+ prev_frame);
+ }
+ else
+#endif
+ {
+ 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();
+
+ /* update memory size, no need to update memory ptr as
+ it isn't changed in wasm_enlarge_memory */
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ if (memory)
+ linear_mem_size = memory->memory_data_size;
+#endif
+ if (wasm_copy_exception(module, NULL))
+ goto got_exception;
+ }
+ else {
+ WASMFunction *cur_wasm_func = cur_func->u.func;
+ WASMType *func_type;
+
+ func_type = cur_wasm_func->func_type;
+
+ all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num
+ + cur_wasm_func->max_stack_cell_num
+ + cur_wasm_func->max_block_num
+ * (uint32)sizeof(WASMBranchBlock) / 4;
+ /* param_cell_num, local_cell_num, max_stack_cell_num and
+ max_block_num are all no larger than UINT16_MAX (checked
+ in loader), all_cell_num must be smaller than 1MB */
+ bh_assert(all_cell_num < 1 * BH_MB);
+
+ frame_size = wasm_interp_interp_frame_size(all_cell_num);
+ 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_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 + cur_func->local_cell_num;
+ frame->sp_boundary =
+ frame->sp_bottom + cur_wasm_func->max_stack_cell_num;
+
+ frame_csp = frame->csp_bottom =
+ (WASMBranchBlock *)frame->sp_boundary;
+ frame->csp_boundary =
+ frame->csp_bottom + cur_wasm_func->max_block_num;
+
+ /* Initialize the local variables */
+ memset(frame_lp + cur_func->param_cell_num, 0,
+ (uint32)(cur_func->local_cell_num * 4));
+
+ /* Push function block as first block */
+ cell_num = func_type->ret_cell_num;
+ PUSH_CSP(LABEL_TYPE_FUNCTION, 0, cell_num, frame_ip_end - 1);
+
+ wasm_exec_env_set_cur_frame(exec_env, frame);
+ }
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ HANDLE_OP_END();
+ }
+
+ return_func:
+ {
+ FREE_FRAME(exec_env, frame);
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+
+ if (!prev_frame->ip)
+ /* Called from native. */
+ return;
+
+ RECOVER_CONTEXT(prev_frame);
+ HANDLE_OP_END();
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ unaligned_atomic:
+ wasm_set_exception(module, "unaligned atomic");
+ goto got_exception;
+#endif
+
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ out_of_bounds:
+ wasm_set_exception(module, "out of bounds memory access");
+#endif
+
+ got_exception:
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (wasm_exec_env_get_instance(exec_env) != NULL) {
+ uint8 *frame_ip_temp = frame_ip;
+ frame_ip = frame_ip_orig;
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
+ CHECK_SUSPEND_FLAGS();
+ frame_ip = frame_ip_temp;
+ }
+#endif
+ SYNC_ALL_TO_FRAME();
+ return;
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ }
+#else
+ FETCH_OPCODE_AND_DISPATCH();
+#endif
+}
+
+#if WASM_ENABLE_FAST_JIT != 0
+static void
+fast_jit_call_func_bytecode(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *function,
+ WASMInterpFrame *frame)
+{
+ JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+ JitInterpSwitchInfo info;
+ WASMModule *module = module_inst->module;
+ WASMType *func_type = function->u.func->func_type;
+ uint8 type = func_type->result_count
+ ? func_type->types[func_type->param_count]
+ : VALUE_TYPE_VOID;
+ uint32 func_idx = (uint32)(function - module_inst->e->functions);
+ uint32 func_idx_non_import = func_idx - module->import_function_count;
+ int32 action;
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF)
+ type = VALUE_TYPE_I32;
+#endif
+
+#if WASM_ENABLE_LAZY_JIT != 0
+ if (!jit_compiler_compile(module, func_idx)) {
+ wasm_set_exception(module_inst, "failed to compile fast jit function");
+ return;
+ }
+#endif
+ bh_assert(jit_compiler_is_compiled(module, func_idx));
+
+ /* Switch to jitted code to call the jit function */
+ info.out.ret.last_return_type = type;
+ info.frame = frame;
+ frame->jitted_return_addr =
+ (uint8 *)jit_globals->return_to_interp_from_jitted;
+ action = jit_interp_switch_to_jitted(
+ exec_env, &info, func_idx,
+ module_inst->fast_jit_func_ptrs[func_idx_non_import]);
+ bh_assert(action == JIT_INTERP_ACTION_NORMAL
+ || (action == JIT_INTERP_ACTION_THROWN
+ && wasm_copy_exception(
+ (WASMModuleInstance *)exec_env->module_inst, NULL)));
+
+ /* Get the return values form info.out.ret */
+ if (func_type->result_count) {
+ switch (type) {
+ case VALUE_TYPE_I32:
+ *(frame->sp - function->ret_cell_num) = info.out.ret.ival[0];
+ break;
+ case VALUE_TYPE_I64:
+ *(frame->sp - function->ret_cell_num) = info.out.ret.ival[0];
+ *(frame->sp - function->ret_cell_num + 1) =
+ info.out.ret.ival[1];
+ break;
+ case VALUE_TYPE_F32:
+ *(frame->sp - function->ret_cell_num) = info.out.ret.fval[0];
+ break;
+ case VALUE_TYPE_F64:
+ *(frame->sp - function->ret_cell_num) = info.out.ret.fval[0];
+ *(frame->sp - function->ret_cell_num + 1) =
+ info.out.ret.fval[1];
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+ (void)action;
+ (void)func_idx;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 */
+
+#if WASM_ENABLE_JIT != 0
+static bool
+llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *function, uint32 argc,
+ uint32 argv[])
+{
+ WASMType *func_type = function->u.func->func_type;
+ uint32 result_count = func_type->result_count;
+ uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
+ uint32 func_idx = (uint32)(function - module_inst->e->functions);
+ bool ret;
+
+#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
+ if (!llvm_jit_alloc_frame(exec_env, function - module_inst->e->functions)) {
+ /* wasm operand stack overflow has been thrown,
+ no need to throw again */
+ return false;
+ }
+#endif
+
+ if (ext_ret_count > 0) {
+ uint32 cell_num = 0, i;
+ uint8 *ext_ret_types = func_type->types + func_type->param_count + 1;
+ uint32 argv1_buf[32], *argv1 = argv1_buf, *ext_rets = NULL;
+ uint32 *argv_ret = argv;
+ uint32 ext_ret_cell = wasm_get_cell_num(ext_ret_types, ext_ret_count);
+ uint64 size;
+
+ /* Allocate memory all arguments */
+ size =
+ sizeof(uint32) * (uint64)argc /* original arguments */
+ + sizeof(void *)
+ * (uint64)ext_ret_count /* extra result values' addr */
+ + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */
+ if (size > sizeof(argv1_buf)) {
+ if (size > UINT32_MAX
+ || !(argv1 = wasm_runtime_malloc((uint32)size))) {
+ wasm_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+
+ /* Copy original arguments */
+ bh_memcpy_s(argv1, (uint32)size, argv, sizeof(uint32) * argc);
+
+ /* Get the extra result value's address */
+ ext_rets =
+ argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
+
+ /* Append each extra result value's address to original arguments */
+ for (i = 0; i < ext_ret_count; i++) {
+ *(uintptr_t *)(argv1 + argc + sizeof(void *) / sizeof(uint32) * i) =
+ (uintptr_t)(ext_rets + cell_num);
+ cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
+ }
+
+ ret = wasm_runtime_invoke_native(
+ exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
+ argv1, argc, argv);
+ if (!ret) {
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+ return ret;
+ }
+
+ /* Get extra result values */
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ argv_ret++;
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ argv_ret += 2;
+ break;
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ argv_ret += 4;
+ break;
+#endif
+ default:
+ bh_assert(0);
+ break;
+ }
+
+ ext_rets =
+ argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
+ bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, ext_rets,
+ sizeof(uint32) * cell_num);
+
+ if (argv1 != argv1_buf)
+ wasm_runtime_free(argv1);
+ return true;
+ }
+ else {
+ ret = wasm_runtime_invoke_native(
+ exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
+ argv, argc, argv);
+
+ return ret && !wasm_copy_exception(module_inst, NULL) ? true : false;
+ }
+}
+#endif /* end of WASM_ENABLE_JIT != 0 */
+
+void
+wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
+ WASMFunctionInstance *function, uint32 argc,
+ uint32 argv[])
+{
+ WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
+ WASMInterpFrame *frame, *outs_area;
+ /* Allocate sufficient cells for all kinds of return values. */
+ unsigned all_cell_num =
+ function->ret_cell_num > 2 ? function->ret_cell_num : 2;
+ /* This frame won't be used by JITed code, so only allocate interp
+ frame here. */
+ unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
+ unsigned i;
+ bool copy_argv_from_frame = true;
+ char exception[EXCEPTION_BUF_LEN];
+
+ if (argc < function->param_cell_num) {
+ char buf[128];
+ snprintf(buf, sizeof(buf),
+ "invalid argument count %" PRIu32
+ ", must be no smaller than %u",
+ argc, function->param_cell_num);
+ wasm_set_exception(module_inst, buf);
+ return;
+ }
+ argc = function->param_cell_num;
+
+ RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
+#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
+ && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
+ if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
+ wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
+ "native stack overflow");
+ return;
+ }
+#endif
+
+ if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame)))
+ return;
+
+ outs_area = wasm_exec_env_wasm_stack_top(exec_env);
+ frame->function = NULL;
+ frame->ip = NULL;
+ /* There is no local variable. */
+ frame->sp = frame->lp + 0;
+
+ if ((uint8 *)(outs_area->lp + function->param_cell_num)
+ > exec_env->wasm_stack.s.top_boundary) {
+ wasm_set_exception(module_inst, "wasm operand stack overflow");
+ return;
+ }
+
+ if (argc > 0)
+ word_copy(outs_area->lp, argv, argc);
+
+ wasm_exec_env_set_cur_frame(exec_env, frame);
+
+ if (function->is_import_func) {
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (function->import_module_inst) {
+ wasm_interp_call_func_import(module_inst, exec_env, function,
+ frame);
+ }
+ else
+#endif
+ {
+ /* it is a native function */
+ wasm_interp_call_func_native(module_inst, exec_env, function,
+ frame);
+ }
+ }
+ else {
+ RunningMode running_mode =
+ wasm_runtime_get_running_mode((wasm_module_inst_t)module_inst);
+
+ if (running_mode == Mode_Interp) {
+ wasm_interp_call_func_bytecode(module_inst, exec_env, function,
+ frame);
+ }
+#if WASM_ENABLE_FAST_JIT != 0
+ else if (running_mode == Mode_Fast_JIT) {
+ fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
+ }
+#endif
+#if WASM_ENABLE_JIT != 0
+ else if (running_mode == Mode_LLVM_JIT) {
+ llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
+ argv);
+ /* For llvm jit, the results have been stored in argv,
+ no need to copy them from stack frame again */
+ copy_argv_from_frame = false;
+ }
+#endif
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
+ && WASM_ENABLE_JIT != 0
+ else if (running_mode == Mode_Multi_Tier_JIT) {
+ /* Tier-up from Fast JIT to LLVM JIT, call llvm jit function
+ if it is compiled, else call fast jit function */
+ uint32 func_idx = (uint32)(function - module_inst->e->functions);
+ if (module_inst->module->func_ptrs_compiled
+ [func_idx - module_inst->module->import_function_count]) {
+ llvm_jit_call_func_bytecode(module_inst, exec_env, function,
+ argc, argv);
+ /* For llvm jit, the results have been stored in argv,
+ no need to copy them from stack frame again */
+ copy_argv_from_frame = false;
+ }
+ else {
+ fast_jit_call_func_bytecode(module_inst, exec_env, function,
+ frame);
+ }
+ }
+#endif
+ else {
+ /* There should always be a supported running mode selected */
+ bh_assert(0);
+ }
+
+ (void)wasm_interp_call_func_bytecode;
+#if WASM_ENABLE_FAST_JIT != 0
+ (void)fast_jit_call_func_bytecode;
+#endif
+ }
+
+ /* Output the return value to the caller */
+ if (!wasm_copy_exception(module_inst, NULL)) {
+ if (copy_argv_from_frame) {
+ for (i = 0; i < function->ret_cell_num; i++) {
+ argv[i] = *(frame->sp + i - function->ret_cell_num);
+ }
+ }
+ }
+ else {
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (wasm_interp_create_call_stack(exec_env)) {
+ wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
+ }
+#endif
+ wasm_copy_exception(module_inst, exception);
+ LOG_DEBUG("meet an exception %s", exception);
+ }
+
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+ FREE_FRAME(exec_env, frame);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_fast.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_fast.c
new file mode 100644
index 000000000..6ddeaa9c0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_interp_fast.c
@@ -0,0 +1,4021 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_interp.h"
+#include "bh_log.h"
+#include "wasm_runtime.h"
+#include "wasm_opcode.h"
+#include "wasm_loader.h"
+#include "wasm_memory.h"
+#include "../common/wasm_exec_env.h"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "../common/wasm_shared_memory.h"
+#endif
+
+typedef int32 CellType_I32;
+typedef int64 CellType_I64;
+typedef float32 CellType_F32;
+typedef float64 CellType_F64;
+
+#if WASM_ENABLE_THREAD_MGR == 0
+#define get_linear_mem_size() linear_mem_size
+#else
+/**
+ * Load memory data size in each time boundary check in
+ * multi-threading mode since it may be changed by other
+ * threads in memory.grow
+ */
+#define get_linear_mem_size() memory->memory_data_size
+#endif
+
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+#define CHECK_MEMORY_OVERFLOW(bytes) \
+ do { \
+ uint64 offset1 = (uint64)offset + (uint64)addr; \
+ if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
+ /* If offset1 is in valid range, maddr must also \
+ be in valid range, no need to check it again. */ \
+ maddr = memory->memory_data + offset1; \
+ else \
+ goto out_of_bounds; \
+ } while (0)
+
+#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
+ do { \
+ uint64 offset1 = (uint32)(start); \
+ if (offset1 + bytes <= get_linear_mem_size()) \
+ /* App heap space is not valid space for \
+ bulk memory operation */ \
+ maddr = memory->memory_data + offset1; \
+ else \
+ goto out_of_bounds; \
+ } while (0)
+#else
+#define CHECK_MEMORY_OVERFLOW(bytes) \
+ do { \
+ uint64 offset1 = (uint64)offset + (uint64)addr; \
+ maddr = memory->memory_data + offset1; \
+ } while (0)
+
+#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
+ do { \
+ maddr = memory->memory_data + (uint32)(start); \
+ } while (0)
+#endif /* !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
+
+#define CHECK_ATOMIC_MEMORY_ACCESS(align) \
+ do { \
+ if (((uintptr_t)maddr & (align - 1)) != 0) \
+ goto unaligned_atomic; \
+ } while (0)
+
+static inline uint32
+rotl32(uint32 n, uint32 c)
+{
+ const uint32 mask = (31);
+ c = c % 32;
+ c &= mask;
+ return (n << c) | (n >> ((0 - c) & mask));
+}
+
+static inline uint32
+rotr32(uint32 n, uint32 c)
+{
+ const uint32 mask = (31);
+ c = c % 32;
+ c &= mask;
+ return (n >> c) | (n << ((0 - c) & mask));
+}
+
+static inline uint64
+rotl64(uint64 n, uint64 c)
+{
+ const uint64 mask = (63);
+ c = c % 64;
+ c &= mask;
+ return (n << c) | (n >> ((0 - c) & mask));
+}
+
+static inline uint64
+rotr64(uint64 n, uint64 c)
+{
+ const uint64 mask = (63);
+ c = c % 64;
+ c &= mask;
+ return (n >> c) | (n << ((0 - c) & mask));
+}
+
+static inline float32
+f32_min(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+static inline float32
+f32_max(float32 a, float32 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+static inline float64
+f64_min(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? a : b;
+ else
+ return a > b ? b : a;
+}
+
+static inline float64
+f64_max(float64 a, float64 b)
+{
+ if (isnan(a) || isnan(b))
+ return NAN;
+ else if (a == 0 && a == b)
+ return signbit(a) ? b : a;
+ else
+ return a > b ? a : b;
+}
+
+static inline uint32
+clz32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 0x80000000)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+static inline uint32
+clz64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 0x8000000000000000LL)) {
+ num++;
+ type <<= 1;
+ }
+ return num;
+}
+
+static inline uint32
+ctz32(uint32 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 32;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+static inline uint32
+ctz64(uint64 type)
+{
+ uint32 num = 0;
+ if (type == 0)
+ return 64;
+ while (!(type & 1)) {
+ num++;
+ type >>= 1;
+ }
+ return num;
+}
+
+static inline uint32
+popcount32(uint32 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+static inline uint32
+popcount64(uint64 u)
+{
+ uint32 ret = 0;
+ while (u) {
+ u = (u & (u - 1));
+ ret++;
+ }
+ return ret;
+}
+
+static float
+local_copysignf(float x, float y)
+{
+ union {
+ float f;
+ uint32 i;
+ } ux = { x }, uy = { y };
+ ux.i &= 0x7fffffff;
+ ux.i |= uy.i & 0x80000000;
+ return ux.f;
+}
+
+static double
+local_copysign(double x, double y)
+{
+ union {
+ double f;
+ uint64 i;
+ } ux = { x }, uy = { y };
+ ux.i &= UINT64_MAX / 2;
+ ux.i |= uy.i & 1ULL << 63;
+ return ux.f;
+}
+
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define LOAD_U32_WITH_2U16S(addr) (*(uint32 *)(addr))
+#define LOAD_PTR(addr) (*(void **)(addr))
+#else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+static inline uint32
+LOAD_U32_WITH_2U16S(void *addr)
+{
+ union {
+ uint32 val;
+ uint16 u16[2];
+ } u;
+
+ bh_assert(((uintptr_t)addr & 1) == 0);
+ u.u16[0] = ((uint16 *)addr)[0];
+ u.u16[1] = ((uint16 *)addr)[1];
+ return u.val;
+}
+#if UINTPTR_MAX == UINT32_MAX
+#define LOAD_PTR(addr) ((void *)LOAD_U32_WITH_2U16S(addr))
+#elif UINTPTR_MAX == UINT64_MAX
+static inline void *
+LOAD_PTR(void *addr)
+{
+ uintptr_t addr1 = (uintptr_t)addr;
+ union {
+ void *val;
+ uint32 u32[2];
+ uint16 u16[4];
+ } u;
+
+ bh_assert(((uintptr_t)addr & 1) == 0);
+ if ((addr1 & (uintptr_t)7) == 0)
+ return *(void **)addr;
+
+ if ((addr1 & (uintptr_t)3) == 0) {
+ u.u32[0] = ((uint32 *)addr)[0];
+ u.u32[1] = ((uint32 *)addr)[1];
+ }
+ else {
+ u.u16[0] = ((uint16 *)addr)[0];
+ u.u16[1] = ((uint16 *)addr)[1];
+ u.u16[2] = ((uint16 *)addr)[2];
+ u.u16[3] = ((uint16 *)addr)[3];
+ }
+ return u.val;
+}
+#endif /* end of UINTPTR_MAX */
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+
+#define read_uint32(p) \
+ (p += sizeof(uint32), LOAD_U32_WITH_2U16S(p - sizeof(uint32)))
+
+#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \
+ do { \
+ uint32 param_count = cur_func->param_count; \
+ local_idx = read_uint32(frame_ip); \
+ bh_assert(local_idx < param_count + cur_func->local_count); \
+ local_offset = cur_func->local_offsets[local_idx]; \
+ if (local_idx < param_count) \
+ local_type = cur_func->param_types[local_idx]; \
+ else \
+ local_type = cur_func->local_types[local_idx - param_count]; \
+ } while (0)
+
+#define GET_OFFSET() (frame_ip += 2, *(int16 *)(frame_ip - 2))
+
+#define SET_OPERAND_I32(off, value) \
+ do { \
+ *(uint32 *)(frame_lp + *(int16 *)(frame_ip + off)) = value; \
+ } while (0)
+#define SET_OPERAND_F32(off, value) \
+ do { \
+ *(float32 *)(frame_lp + *(int16 *)(frame_ip + off)) = value; \
+ } while (0)
+#define SET_OPERAND_I64(off, value) \
+ do { \
+ uint32 *addr_tmp = frame_lp + *(int16 *)(frame_ip + off); \
+ PUT_I64_TO_ADDR(addr_tmp, value); \
+ } while (0)
+#define SET_OPERAND_F64(off, value) \
+ do { \
+ uint32 *addr_tmp = frame_lp + *(int16 *)(frame_ip + off); \
+ PUT_F64_TO_ADDR(addr_tmp, value); \
+ } while (0)
+
+#define SET_OPERAND(op_type, off, value) SET_OPERAND_##op_type(off, value)
+
+#define GET_OPERAND_I32(type, off) \
+ *(type *)(frame_lp + *(int16 *)(frame_ip + off))
+#define GET_OPERAND_F32(type, off) \
+ *(type *)(frame_lp + *(int16 *)(frame_ip + off))
+#define GET_OPERAND_I64(type, off) \
+ (type) GET_I64_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off))
+#define GET_OPERAND_F64(type, off) \
+ (type) GET_F64_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off))
+
+#define GET_OPERAND(type, op_type, off) GET_OPERAND_##op_type(type, off)
+
+#define PUSH_I32(value) \
+ do { \
+ *(int32 *)(frame_lp + GET_OFFSET()) = value; \
+ } while (0)
+
+#define PUSH_F32(value) \
+ do { \
+ *(float32 *)(frame_lp + GET_OFFSET()) = value; \
+ } while (0)
+
+#define PUSH_I64(value) \
+ do { \
+ uint32 *addr_tmp = frame_lp + GET_OFFSET(); \
+ PUT_I64_TO_ADDR(addr_tmp, value); \
+ } while (0)
+
+#define PUSH_F64(value) \
+ do { \
+ uint32 *addr_tmp = frame_lp + GET_OFFSET(); \
+ PUT_F64_TO_ADDR(addr_tmp, value); \
+ } while (0)
+
+#define POP_I32() (*(int32 *)(frame_lp + GET_OFFSET()))
+
+#define POP_F32() (*(float32 *)(frame_lp + GET_OFFSET()))
+
+#define POP_I64() (GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()))
+
+#define POP_F64() (GET_F64_FROM_ADDR(frame_lp + GET_OFFSET()))
+
+#define SYNC_ALL_TO_FRAME() \
+ do { \
+ frame->ip = frame_ip; \
+ } while (0)
+
+#define UPDATE_ALL_FROM_FRAME() \
+ do { \
+ frame_ip = frame->ip; \
+ } while (0)
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#define UPDATE_FRAME_IP_END() (void)0
+#else
+#define UPDATE_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func)
+#endif
+
+#define RECOVER_CONTEXT(new_frame) \
+ do { \
+ frame = (new_frame); \
+ cur_func = frame->function; \
+ prev_frame = frame->prev_frame; \
+ frame_ip = frame->ip; \
+ UPDATE_FRAME_IP_END(); \
+ frame_lp = frame->lp; \
+ } while (0)
+
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define GET_OPCODE() opcode = *frame_ip++;
+#else
+#define GET_OPCODE() \
+ opcode = *frame_ip; \
+ frame_ip += 2;
+#endif
+
+#define DEF_OP_EQZ(ctype, src_op_type) \
+ do { \
+ SET_OPERAND(I32, 2, (GET_OPERAND(ctype, src_op_type, 0) == 0)); \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_CMP(src_type, src_op_type, cond) \
+ do { \
+ SET_OPERAND(I32, 4, \
+ GET_OPERAND(src_type, src_op_type, 2) \
+ cond GET_OPERAND(src_type, src_op_type, 0)); \
+ frame_ip += 6; \
+ } while (0)
+
+#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) \
+ do { \
+ SET_OPERAND( \
+ src_op_type, 2, \
+ (src_type)operation(GET_OPERAND(src_type, src_op_type, 0))); \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_NUMERIC(src_type1, src_type2, src_op_type, operation) \
+ do { \
+ SET_OPERAND(src_op_type, 4, \
+ GET_OPERAND(src_type1, src_op_type, 2) \
+ operation GET_OPERAND(src_type2, src_op_type, 0)); \
+ frame_ip += 6; \
+ } while (0)
+
+#define DEF_OP_REINTERPRET(src_type, src_op_type) \
+ do { \
+ SET_OPERAND(src_op_type, 2, GET_OPERAND(src_type, src_op_type, 0)); \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_NUMERIC_64 DEF_OP_NUMERIC
+
+#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) \
+ do { \
+ SET_OPERAND(src_op_type, 4, \
+ GET_OPERAND(src_type1, src_op_type, 2) operation( \
+ GET_OPERAND(src_type2, src_op_type, 0) % 32)); \
+ frame_ip += 6; \
+ } while (0)
+
+#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) \
+ do { \
+ SET_OPERAND(src_op_type, 4, \
+ GET_OPERAND(src_type1, src_op_type, 2) operation( \
+ GET_OPERAND(src_type2, src_op_type, 0) % 64)); \
+ frame_ip += 6; \
+ } while (0)
+
+#define DEF_ATOMIC_RMW_OPCODE(OP_NAME, op) \
+ case WASM_OP_ATOMIC_RMW_I32_##OP_NAME: \
+ case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U: \
+ case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U: \
+ { \
+ uint32 readv, sval; \
+ \
+ sval = POP_I32(); \
+ addr = POP_I32(); \
+ \
+ if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(1); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint32)(*(uint8 *)maddr); \
+ *(uint8 *)maddr = (uint8)(readv op sval); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(2); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint32)LOAD_U16(maddr); \
+ STORE_U16(maddr, (uint16)(readv op sval)); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(4); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = LOAD_I32(maddr); \
+ STORE_U32(maddr, readv op sval); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ PUSH_I32(readv); \
+ break; \
+ } \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME: \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U: \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U: \
+ case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U: \
+ { \
+ uint64 readv, sval; \
+ \
+ sval = (uint64)POP_I64(); \
+ addr = POP_I32(); \
+ \
+ if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(1); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)(*(uint8 *)maddr); \
+ *(uint8 *)maddr = (uint8)(readv op sval); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(2); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)LOAD_U16(maddr); \
+ STORE_U16(maddr, (uint16)(readv op sval)); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(4); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)LOAD_U32(maddr); \
+ STORE_U32(maddr, (uint32)(readv op sval)); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ else { \
+ uint64 op_result; \
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
+ CHECK_ATOMIC_MEMORY_ACCESS(8); \
+ \
+ os_mutex_lock(&node->shared_mem_lock); \
+ readv = (uint64)LOAD_I64(maddr); \
+ op_result = readv op sval; \
+ STORE_I64(maddr, op_result); \
+ os_mutex_unlock(&node->shared_mem_lock); \
+ } \
+ PUSH_I64(readv); \
+ break; \
+ }
+
+#define DEF_OP_MATH(src_type, src_op_type, method) \
+ do { \
+ SET_OPERAND(src_op_type, 2, \
+ (src_type)method(GET_OPERAND(src_type, src_op_type, 0))); \
+ frame_ip += 4; \
+ } while (0)
+
+#define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type) \
+ static dst_type func_name(src_type src_value, src_type src_min, \
+ src_type src_max, dst_type dst_min, \
+ dst_type dst_max, bool is_sign) \
+ { \
+ dst_type dst_value = 0; \
+ if (!isnan(src_value)) { \
+ if (src_value <= src_min) \
+ dst_value = dst_min; \
+ else if (src_value >= src_max) \
+ dst_value = dst_max; \
+ else { \
+ if (is_sign) \
+ dst_value = (dst_type)(signed_type)src_value; \
+ else \
+ dst_value = (dst_type)src_value; \
+ } \
+ } \
+ return dst_value; \
+ }
+
+TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32)
+TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64)
+TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32)
+TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64)
+
+static bool
+trunc_f32_to_int(WASMModuleInstance *module, uint8 *frame_ip, uint32 *frame_lp,
+ float32 src_min, float32 src_max, bool saturating, bool is_i32,
+ bool is_sign)
+{
+ float32 src_value = GET_OPERAND(float32, F32, 0);
+ uint64 dst_value_i64;
+ uint32 dst_value_i32;
+
+ if (!saturating) {
+ if (isnan(src_value)) {
+ wasm_set_exception(module, "invalid conversion to integer");
+ return false;
+ }
+ else if (src_value <= src_min || src_value >= src_max) {
+ wasm_set_exception(module, "integer overflow");
+ return false;
+ }
+ }
+
+ if (is_i32) {
+ uint32 dst_min = is_sign ? INT32_MIN : 0;
+ uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+ dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ SET_OPERAND(I32, 2, dst_value_i32);
+ }
+ else {
+ uint64 dst_min = is_sign ? INT64_MIN : 0;
+ uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+ dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ SET_OPERAND(I64, 2, dst_value_i64);
+ }
+ return true;
+}
+
+static bool
+trunc_f64_to_int(WASMModuleInstance *module, uint8 *frame_ip, uint32 *frame_lp,
+ float64 src_min, float64 src_max, bool saturating, bool is_i32,
+ bool is_sign)
+{
+ float64 src_value = GET_OPERAND(float64, F64, 0);
+ uint64 dst_value_i64;
+ uint32 dst_value_i32;
+
+ if (!saturating) {
+ if (isnan(src_value)) {
+ wasm_set_exception(module, "invalid conversion to integer");
+ return false;
+ }
+ else if (src_value <= src_min || src_value >= src_max) {
+ wasm_set_exception(module, "integer overflow");
+ return false;
+ }
+ }
+
+ if (is_i32) {
+ uint32 dst_min = is_sign ? INT32_MIN : 0;
+ uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+ dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ SET_OPERAND(I32, 2, dst_value_i32);
+ }
+ else {
+ uint64 dst_min = is_sign ? INT64_MIN : 0;
+ uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+ dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max, dst_min,
+ dst_max, is_sign);
+ SET_OPERAND(I64, 2, dst_value_i64);
+ }
+ return true;
+}
+
+#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) \
+ do { \
+ if (!trunc_f32_to_int(module, frame_ip, frame_lp, min, max, false, \
+ is_i32, is_sign)) \
+ goto got_exception; \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) \
+ do { \
+ if (!trunc_f64_to_int(module, frame_ip, frame_lp, min, max, false, \
+ is_i32, is_sign)) \
+ goto got_exception; \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) \
+ do { \
+ (void)trunc_f32_to_int(module, frame_ip, frame_lp, min, max, true, \
+ is_i32, is_sign); \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) \
+ do { \
+ (void)trunc_f64_to_int(module, frame_ip, frame_lp, min, max, true, \
+ is_i32, is_sign); \
+ frame_ip += 4; \
+ } while (0)
+
+#define DEF_OP_CONVERT(dst_type, dst_op_type, src_type, src_op_type) \
+ do { \
+ dst_type value = (dst_type)(src_type)POP_##src_op_type(); \
+ PUSH_##dst_op_type(value); \
+ } while (0)
+
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define CELL_SIZE sizeof(uint8)
+#else
+#define CELL_SIZE (sizeof(uint8) * 2)
+#endif
+
+static bool
+copy_stack_values(WASMModuleInstance *module, uint32 *frame_lp, uint32 arity,
+ uint32 total_cell_num, const uint8 *cells,
+ const int16 *src_offsets, const uint16 *dst_offsets)
+{
+ /* To avoid the overlap issue between src offsets and dst offset,
+ * we use 2 steps to do the copy. First step, copy the src values
+ * to a tmp buf. Second step, copy the values from tmp buf to dst.
+ */
+ uint32 buf[16] = { 0 }, i;
+ uint32 *tmp_buf = buf;
+ uint8 cell;
+ int16 src, buf_index = 0;
+ uint16 dst;
+
+ /* Allocate memory if the buf is not large enough */
+ if (total_cell_num > sizeof(buf) / sizeof(uint32)) {
+ uint64 total_size = sizeof(uint32) * (uint64)total_cell_num;
+ if (total_size >= UINT32_MAX
+ || !(tmp_buf = wasm_runtime_malloc((uint32)total_size))) {
+ wasm_set_exception(module, "allocate memory failed");
+ return false;
+ }
+ }
+
+ /* 1) Copy values from src to tmp buf */
+ for (i = 0; i < arity; i++) {
+ cell = cells[i * CELL_SIZE];
+ src = src_offsets[i];
+ if (cell == 1)
+ tmp_buf[buf_index] = frame_lp[src];
+ else {
+ tmp_buf[buf_index] = frame_lp[src];
+ tmp_buf[buf_index + 1] = frame_lp[src + 1];
+ }
+ buf_index += cell;
+ }
+
+ /* 2) Copy values from tmp buf to dest */
+ buf_index = 0;
+ for (i = 0; i < arity; i++) {
+ cell = cells[i * CELL_SIZE];
+ dst = dst_offsets[i];
+ if (cell == 1)
+ frame_lp[dst] = tmp_buf[buf_index];
+ else {
+ frame_lp[dst] = tmp_buf[buf_index];
+ frame_lp[dst + 1] = tmp_buf[buf_index + 1];
+ }
+ buf_index += cell;
+ }
+
+ if (tmp_buf != buf) {
+ wasm_runtime_free(tmp_buf);
+ }
+
+ return true;
+}
+
+#define RECOVER_BR_INFO() \
+ do { \
+ uint32 arity; \
+ /* read arity */ \
+ arity = read_uint32(frame_ip); \
+ if (arity) { \
+ uint32 total_cell; \
+ uint16 *dst_offsets = NULL; \
+ uint8 *cells; \
+ int16 *src_offsets = NULL; \
+ /* read total cell num */ \
+ total_cell = read_uint32(frame_ip); \
+ /* cells */ \
+ cells = (uint8 *)frame_ip; \
+ frame_ip += arity * CELL_SIZE; \
+ /* src offsets */ \
+ src_offsets = (int16 *)frame_ip; \
+ frame_ip += arity * sizeof(int16); \
+ /* dst offsets */ \
+ dst_offsets = (uint16 *)frame_ip; \
+ frame_ip += arity * sizeof(uint16); \
+ if (arity == 1) { \
+ if (cells[0] == 1) \
+ frame_lp[dst_offsets[0]] = frame_lp[src_offsets[0]]; \
+ else if (cells[0] == 2) { \
+ frame_lp[dst_offsets[0]] = frame_lp[src_offsets[0]]; \
+ frame_lp[dst_offsets[0] + 1] = \
+ frame_lp[src_offsets[0] + 1]; \
+ } \
+ } \
+ else { \
+ if (!copy_stack_values(module, frame_lp, arity, total_cell, \
+ cells, src_offsets, dst_offsets)) \
+ goto got_exception; \
+ } \
+ } \
+ frame_ip = (uint8 *)LOAD_PTR(frame_ip); \
+ } while (0)
+
+#define SKIP_BR_INFO() \
+ do { \
+ uint32 arity; \
+ /* read and skip arity */ \
+ arity = read_uint32(frame_ip); \
+ if (arity) { \
+ /* skip total cell num */ \
+ frame_ip += sizeof(uint32); \
+ /* skip cells, src offsets and dst offsets */ \
+ frame_ip += (CELL_SIZE + sizeof(int16) + sizeof(uint16)) * arity; \
+ } \
+ /* skip target address */ \
+ frame_ip += sizeof(uint8 *); \
+ } while (0)
+
+static inline int32
+sign_ext_8_32(int8 val)
+{
+ if (val & 0x80)
+ return (int32)val | (int32)0xffffff00;
+ return val;
+}
+
+static inline int32
+sign_ext_16_32(int16 val)
+{
+ if (val & 0x8000)
+ return (int32)val | (int32)0xffff0000;
+ return val;
+}
+
+static inline int64
+sign_ext_8_64(int8 val)
+{
+ if (val & 0x80)
+ return (int64)val | (int64)0xffffffffffffff00LL;
+ return val;
+}
+
+static inline int64
+sign_ext_16_64(int16 val)
+{
+ if (val & 0x8000)
+ return (int64)val | (int64)0xffffffffffff0000LL;
+ return val;
+}
+
+static inline int64
+sign_ext_32_64(int32 val)
+{
+ if (val & (int32)0x80000000)
+ return (int64)val | (int64)0xffffffff00000000LL;
+ return val;
+}
+
+static inline void
+word_copy(uint32 *dest, uint32 *src, unsigned num)
+{
+ bh_assert(dest != NULL);
+ bh_assert(src != NULL);
+ bh_assert(num > 0);
+ if (dest != src) {
+ /* No overlap buffer */
+ bh_assert(!((src < dest) && (dest < src + num)));
+ for (; num > 0; num--)
+ *dest++ = *src++;
+ }
+}
+
+static inline WASMInterpFrame *
+ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame)
+{
+ WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size);
+
+ if (frame) {
+ frame->prev_frame = prev_frame;
+#if WASM_ENABLE_PERF_PROFILING != 0
+ frame->time_started = os_time_get_boot_microsecond();
+#endif
+ }
+ else {
+ wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
+ "wasm operand stack overflow");
+ }
+
+ return frame;
+}
+
+static inline void
+FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame)
+{
+#if WASM_ENABLE_PERF_PROFILING != 0
+ if (frame->function) {
+ frame->function->total_exec_time +=
+ os_time_get_boot_microsecond() - frame->time_started;
+ frame->function->total_exec_cnt++;
+ }
+#endif
+ wasm_exec_env_free_wasm_frame(exec_env, frame);
+}
+
+static void
+wasm_interp_call_func_native(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame)
+{
+ WASMFunctionImport *func_import = cur_func->u.func_import;
+ CApiFuncImport *c_api_func_import = NULL;
+ unsigned local_cell_num = 2;
+ WASMInterpFrame *frame;
+ uint32 argv_ret[2], cur_func_index;
+ void *native_func_pointer = NULL;
+ bool ret;
+
+ 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->lp = frame->operand;
+
+ wasm_exec_env_set_cur_frame(exec_env, frame);
+
+ cur_func_index = (uint32)(cur_func - module_inst->e->functions);
+ bh_assert(cur_func_index < module_inst->module->import_function_count);
+ if (!func_import->call_conv_wasm_c_api) {
+ native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
+ }
+ else if (module_inst->e->c_api_func_imports) {
+ c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index;
+ native_func_pointer = c_api_func_import->func_ptr_linked;
+ }
+
+ if (!native_func_pointer) {
+ char buf[128];
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ func_import->module_name, func_import->field_name);
+ wasm_set_exception((WASMModuleInstance *)module_inst, buf);
+ return;
+ }
+
+ if (func_import->call_conv_wasm_c_api) {
+ ret = wasm_runtime_invoke_c_api_native(
+ (WASMModuleInstanceCommon *)module_inst, native_func_pointer,
+ func_import->func_type, cur_func->param_cell_num, frame->lp,
+ c_api_func_import->with_env_arg, c_api_func_import->env_arg);
+ if (ret) {
+ argv_ret[0] = frame->lp[0];
+ argv_ret[1] = frame->lp[1];
+ }
+ }
+ else if (!func_import->call_conv_raw) {
+ ret = wasm_runtime_invoke_native(
+ exec_env, native_func_pointer, func_import->func_type,
+ func_import->signature, func_import->attachment, frame->lp,
+ cur_func->param_cell_num, argv_ret);
+ }
+ else {
+ ret = wasm_runtime_invoke_native_raw(
+ exec_env, native_func_pointer, func_import->func_type,
+ func_import->signature, func_import->attachment, frame->lp,
+ cur_func->param_cell_num, argv_ret);
+ }
+
+ if (!ret)
+ return;
+
+ if (cur_func->ret_cell_num == 1) {
+ prev_frame->lp[prev_frame->ret_offset] = argv_ret[0];
+ }
+ else if (cur_func->ret_cell_num == 2) {
+ prev_frame->lp[prev_frame->ret_offset] = argv_ret[0];
+ prev_frame->lp[prev_frame->ret_offset + 1] = argv_ret[1];
+ }
+
+ FREE_FRAME(exec_env, frame);
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+}
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static void
+wasm_interp_call_func_bytecode(WASMModuleInstance *module,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame);
+
+static void
+wasm_interp_call_func_import(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame)
+{
+ WASMModuleInstance *sub_module_inst = cur_func->import_module_inst;
+ WASMFunctionInstance *sub_func_inst = cur_func->import_func_inst;
+ WASMFunctionImport *func_import = cur_func->u.func_import;
+ uint8 *ip = prev_frame->ip;
+ char buf[128];
+ WASMExecEnv *sub_module_exec_env = NULL;
+ uint32 aux_stack_origin_boundary = 0;
+ uint32 aux_stack_origin_bottom = 0;
+
+ if (!sub_func_inst) {
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ func_import->module_name, func_import->field_name);
+ wasm_set_exception(module_inst, buf);
+ return;
+ }
+
+ /* Switch exec_env but keep using the same one by replacing necessary
+ * variables */
+ sub_module_exec_env = wasm_runtime_get_exec_env_singleton(
+ (WASMModuleInstanceCommon *)sub_module_inst);
+ if (!sub_module_exec_env) {
+ wasm_set_exception(module_inst, "create singleton exec_env failed");
+ return;
+ }
+
+ /* - module_inst */
+ exec_env->module_inst = (WASMModuleInstanceCommon *)sub_module_inst;
+ /* - aux_stack_boundary */
+ aux_stack_origin_boundary = exec_env->aux_stack_boundary.boundary;
+ exec_env->aux_stack_boundary.boundary =
+ sub_module_exec_env->aux_stack_boundary.boundary;
+ /* - aux_stack_bottom */
+ aux_stack_origin_bottom = exec_env->aux_stack_bottom.bottom;
+ exec_env->aux_stack_bottom.bottom =
+ sub_module_exec_env->aux_stack_bottom.bottom;
+
+ /* set ip NULL to make call_func_bytecode return after executing
+ this function */
+ prev_frame->ip = NULL;
+
+ /* call function of sub-module*/
+ wasm_interp_call_func_bytecode(sub_module_inst, exec_env, sub_func_inst,
+ prev_frame);
+
+ /* restore ip and other replaced */
+ prev_frame->ip = ip;
+ exec_env->aux_stack_boundary.boundary = aux_stack_origin_boundary;
+ exec_env->aux_stack_bottom.bottom = aux_stack_origin_bottom;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+
+ /* transfer exception if it is thrown */
+ if (wasm_copy_exception(sub_module_inst, NULL)) {
+ bh_memcpy_s(module_inst->cur_exception,
+ sizeof(module_inst->cur_exception),
+ sub_module_inst->cur_exception,
+ sizeof(sub_module_inst->cur_exception));
+ }
+}
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+#define CHECK_SUSPEND_FLAGS() \
+ do { \
+ os_mutex_lock(&exec_env->wait_lock); \
+ if (exec_env->suspend_flags.flags != 0) { \
+ if (exec_env->suspend_flags.flags & 0x01) { \
+ /* terminate current thread */ \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ return; \
+ } \
+ /* TODO: support suspend and breakpoint */ \
+ } \
+ os_mutex_unlock(&exec_env->wait_lock); \
+ } while (0)
+#endif
+
+#if WASM_ENABLE_OPCODE_COUNTER != 0
+typedef struct OpcodeInfo {
+ char *name;
+ uint64 count;
+} OpcodeInfo;
+
+/* clang-format off */
+#define HANDLE_OPCODE(op) \
+ { \
+ #op, 0 \
+ }
+DEFINE_GOTO_TABLE(OpcodeInfo, opcode_table);
+#undef HANDLE_OPCODE
+/* clang-format on */
+
+static void
+wasm_interp_dump_op_count()
+{
+ uint32 i;
+ uint64 total_count = 0;
+ for (i = 0; i < WASM_OP_IMPDEP; i++)
+ total_count += opcode_table[i].count;
+
+ printf("total opcode count: %ld\n", total_count);
+ for (i = 0; i < WASM_OP_IMPDEP; i++)
+ if (opcode_table[i].count > 0)
+ printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n", opcode_table[i].name,
+ opcode_table[i].count,
+ opcode_table[i].count * 100.0f / total_count);
+}
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+
+/* #define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n"); */
+#if WASM_ENABLE_OPCODE_COUNTER != 0
+#define HANDLE_OP(opcode) HANDLE_##opcode : opcode_table[opcode].count++;
+#else
+#define HANDLE_OP(opcode) HANDLE_##opcode:
+#endif
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define FETCH_OPCODE_AND_DISPATCH() \
+ do { \
+ const void *p_label_addr = *(void **)frame_ip; \
+ frame_ip += sizeof(void *); \
+ goto *p_label_addr; \
+ } while (0)
+#else
+#define FETCH_OPCODE_AND_DISPATCH() \
+ do { \
+ const void *p_label_addr = label_base + *(int16 *)frame_ip; \
+ frame_ip += sizeof(int16); \
+ goto *p_label_addr; \
+ } while (0)
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH()
+
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+
+#define HANDLE_OP(opcode) case opcode:
+#define HANDLE_OP_END() continue
+
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+static void **global_handle_table;
+#endif
+
+static inline uint8 *
+get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
+{
+#if WASM_ENABLE_MULTI_MODULE == 0
+ return global_data + global->data_offset;
+#else
+ return global->import_global_inst
+ ? global->import_module_inst->global_data
+ + global->import_global_inst->data_offset
+ : global_data + global->data_offset;
+#endif
+}
+
+static void
+wasm_interp_call_func_bytecode(WASMModuleInstance *module,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *cur_func,
+ WASMInterpFrame *prev_frame)
+{
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *node =
+ wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
+#endif
+ WASMMemoryInstance *memory = wasm_get_default_memory(module);
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ uint32 linear_mem_size = memory ? memory->memory_data_size : 0;
+#endif
+ WASMGlobalInstance *globals = module->e ? module->e->globals : NULL;
+ WASMGlobalInstance *global;
+ uint8 *global_data = module->global_data;
+ uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
+ WASMInterpFrame *frame = NULL;
+ /* Points to this special opcode so as to jump to the
+ * call_method_from_entry. */
+ register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */
+ register uint32 *frame_lp = NULL; /* cache of frame->lp */
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ /* cache of label base addr */
+ register uint8 *label_base = &&HANDLE_WASM_OP_UNREACHABLE;
+#endif
+#endif
+ uint8 *frame_ip_end = frame_ip + 1;
+ uint32 cond, count, fidx, tidx, frame_size = 0;
+ uint32 all_cell_num = 0;
+ int16 addr1, addr2, addr_ret = 0;
+ int32 didx, val;
+ uint8 *maddr = NULL;
+ uint32 local_idx, local_offset, global_idx;
+ uint8 opcode, local_type, *global_addr;
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#define HANDLE_OPCODE(op) &&HANDLE_##op
+ DEFINE_GOTO_TABLE(const void *, handle_table);
+#undef HANDLE_OPCODE
+ if (exec_env == NULL) {
+ global_handle_table = (void **)handle_table;
+ return;
+ }
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ while (frame_ip < frame_ip_end) {
+ opcode = *frame_ip++;
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ frame_ip++;
+#endif
+ switch (opcode) {
+#else
+ goto *handle_table[WASM_OP_IMPDEP];
+#endif
+ /* control instructions */
+ HANDLE_OP(WASM_OP_UNREACHABLE)
+ {
+ wasm_set_exception(module, "unreachable");
+ goto got_exception;
+ }
+
+ HANDLE_OP(WASM_OP_IF)
+ {
+ cond = (uint32)POP_I32();
+
+ if (cond == 0) {
+ uint8 *else_addr = (uint8 *)LOAD_PTR(frame_ip);
+ if (else_addr == NULL) {
+ frame_ip =
+ (uint8 *)LOAD_PTR(frame_ip + sizeof(uint8 *));
+ }
+ else {
+ frame_ip = else_addr;
+ }
+ }
+ else {
+ frame_ip += sizeof(uint8 *) * 2;
+ }
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_ELSE)
+ {
+ frame_ip = (uint8 *)LOAD_PTR(frame_ip);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_BR)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ recover_br_info:
+ RECOVER_BR_INFO();
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_BR_IF)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ cond = frame_lp[GET_OFFSET()];
+
+ if (cond)
+ goto recover_br_info;
+ else
+ SKIP_BR_INFO();
+
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_BR_TABLE)
+ {
+ uint32 arity, br_item_size;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ count = read_uint32(frame_ip);
+ didx = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+
+ if (!(didx >= 0 && (uint32)didx < count))
+ didx = count;
+
+ /* all br items must have the same arity and item size,
+ so we only calculate the first item size */
+ arity = LOAD_U32_WITH_2U16S(frame_ip);
+ br_item_size = sizeof(uint32); /* arity */
+ if (arity) {
+ /* total cell num */
+ br_item_size += sizeof(uint32);
+ /* cells, src offsets and dst offsets */
+ br_item_size +=
+ (CELL_SIZE + sizeof(int16) + sizeof(uint16)) * arity;
+ }
+ /* target address */
+ br_item_size += sizeof(uint8 *);
+
+ frame_ip += br_item_size * didx;
+ goto recover_br_info;
+ }
+
+ HANDLE_OP(WASM_OP_RETURN)
+ {
+ uint32 ret_idx;
+ WASMType *func_type;
+ uint32 off, ret_offset;
+ uint8 *ret_types;
+ if (cur_func->is_import_func)
+ func_type = cur_func->u.func_import->func_type;
+ else
+ func_type = cur_func->u.func->func_type;
+
+ /* types of each return value */
+ ret_types = func_type->types + func_type->param_count;
+ ret_offset = prev_frame->ret_offset;
+
+ for (ret_idx = 0,
+ off = sizeof(int16) * (func_type->result_count - 1);
+ ret_idx < func_type->result_count;
+ ret_idx++, off -= sizeof(int16)) {
+ if (ret_types[ret_idx] == VALUE_TYPE_I64
+ || ret_types[ret_idx] == VALUE_TYPE_F64) {
+ PUT_I64_TO_ADDR(prev_frame->lp + ret_offset,
+ GET_OPERAND(uint64, I64, off));
+ ret_offset += 2;
+ }
+ else {
+ prev_frame->lp[ret_offset] =
+ GET_OPERAND(uint32, I32, off);
+ ret_offset++;
+ }
+ }
+ goto return_func;
+ }
+
+ HANDLE_OP(WASM_OP_CALL_INDIRECT)
+#if WASM_ENABLE_TAIL_CALL != 0
+ HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT)
+#endif
+ {
+ WASMType *cur_type, *cur_func_type;
+ WASMTableInstance *tbl_inst;
+ uint32 tbl_idx;
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ GET_OPCODE();
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+
+ tidx = read_uint32(frame_ip);
+ cur_type = module->module->types[tidx];
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ val = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+
+ if ((uint32)val >= tbl_inst->cur_size) {
+ wasm_set_exception(module, "undefined element");
+ goto got_exception;
+ }
+
+ fidx = tbl_inst->elems[val];
+ if (fidx == NULL_REF) {
+ wasm_set_exception(module, "uninitialized element");
+ goto got_exception;
+ }
+
+ /*
+ * we might be using a table injected by host or
+ * another module. in that case, we don't validate
+ * the elem value while loading
+ */
+ if (fidx >= module->e->function_count) {
+ wasm_set_exception(module, "unknown function");
+ goto got_exception;
+ }
+
+ /* always call module own functions */
+ cur_func = module->e->functions + fidx;
+
+ if (cur_func->is_import_func)
+ cur_func_type = cur_func->u.func_import->func_type;
+ else
+ cur_func_type = cur_func->u.func->func_type;
+
+ if (cur_type != cur_func_type) {
+ wasm_set_exception(module, "indirect call type mismatch");
+ goto got_exception;
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
+ goto call_func_from_return_call;
+#endif
+ goto call_func_from_interp;
+ }
+
+ /* parametric instructions */
+ HANDLE_OP(WASM_OP_SELECT)
+ {
+ cond = frame_lp[GET_OFFSET()];
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ addr_ret = GET_OFFSET();
+
+ if (!cond) {
+ if (addr_ret != addr1)
+ frame_lp[addr_ret] = frame_lp[addr1];
+ }
+ else {
+ if (addr_ret != addr2)
+ frame_lp[addr_ret] = frame_lp[addr2];
+ }
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SELECT_64)
+ {
+ cond = frame_lp[GET_OFFSET()];
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ addr_ret = GET_OFFSET();
+
+ if (!cond) {
+ if (addr_ret != addr1)
+ PUT_I64_TO_ADDR(frame_lp + addr_ret,
+ GET_I64_FROM_ADDR(frame_lp + addr1));
+ }
+ else {
+ if (addr_ret != addr2)
+ PUT_I64_TO_ADDR(frame_lp + addr_ret,
+ GET_I64_FROM_ADDR(frame_lp + addr2));
+ }
+ HANDLE_OP_END();
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ HANDLE_OP(WASM_OP_TABLE_GET)
+ {
+ uint32 tbl_idx, elem_idx;
+ WASMTableInstance *tbl_inst;
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ elem_idx = POP_I32();
+ if (elem_idx >= tbl_inst->cur_size) {
+ wasm_set_exception(module, "out of bounds table access");
+ goto got_exception;
+ }
+
+ PUSH_I32(tbl_inst->elems[elem_idx]);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_TABLE_SET)
+ {
+ uint32 tbl_idx, elem_idx, elem_val;
+ WASMTableInstance *tbl_inst;
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ elem_val = POP_I32();
+ elem_idx = POP_I32();
+ if (elem_idx >= tbl_inst->cur_size) {
+ wasm_set_exception(module, "out of bounds table access");
+ goto got_exception;
+ }
+
+ tbl_inst->elems[elem_idx] = elem_val;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_REF_NULL)
+ {
+ PUSH_I32(NULL_REF);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_REF_IS_NULL)
+ {
+ uint32 ref_val;
+ ref_val = POP_I32();
+ PUSH_I32(ref_val == NULL_REF ? 1 : 0);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_REF_FUNC)
+ {
+ uint32 func_idx = read_uint32(frame_ip);
+ PUSH_I32(func_idx);
+ HANDLE_OP_END();
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+
+ /* variable instructions */
+ HANDLE_OP(EXT_OP_SET_LOCAL_FAST)
+ HANDLE_OP(EXT_OP_TEE_LOCAL_FAST)
+ {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ local_offset = *frame_ip++;
+#else
+ /* clang-format off */
+ local_offset = *frame_ip;
+ frame_ip += 2;
+ /* clang-format on */
+#endif
+ *(uint32 *)(frame_lp + local_offset) =
+ GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64)
+ HANDLE_OP(EXT_OP_TEE_LOCAL_FAST_I64)
+ {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ local_offset = *frame_ip++;
+#else
+ /* clang-format off */
+ local_offset = *frame_ip;
+ frame_ip += 2;
+ /* clang-format on */
+#endif
+ PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset),
+ GET_OPERAND(uint64, I64, 0));
+ frame_ip += 2;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_GET_GLOBAL)
+ {
+ global_idx = read_uint32(frame_ip);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ addr_ret = GET_OFFSET();
+ frame_lp[addr_ret] = *(uint32 *)global_addr;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_GET_GLOBAL_64)
+ {
+ global_idx = read_uint32(frame_ip);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ addr_ret = GET_OFFSET();
+ PUT_I64_TO_ADDR(frame_lp + addr_ret,
+ GET_I64_FROM_ADDR((uint32 *)global_addr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_GLOBAL)
+ {
+ global_idx = read_uint32(frame_ip);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ addr1 = GET_OFFSET();
+ *(int32 *)global_addr = frame_lp[addr1];
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_GLOBAL_AUX_STACK)
+ {
+ uint32 aux_stack_top;
+
+ global_idx = read_uint32(frame_ip);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ aux_stack_top = frame_lp[GET_OFFSET()];
+ if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) {
+ wasm_set_exception(module, "wasm auxiliary stack overflow");
+ goto got_exception;
+ }
+ if (aux_stack_top > exec_env->aux_stack_bottom.bottom) {
+ wasm_set_exception(module,
+ "wasm auxiliary stack underflow");
+ goto got_exception;
+ }
+ *(int32 *)global_addr = aux_stack_top;
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ if (module->module->aux_stack_top_global_index != (uint32)-1) {
+ uint32 aux_stack_used = module->module->aux_stack_bottom
+ - *(uint32 *)global_addr;
+ if (aux_stack_used > module->e->max_aux_stack_used)
+ module->e->max_aux_stack_used = aux_stack_used;
+ }
+#endif
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_GLOBAL_64)
+ {
+ global_idx = read_uint32(frame_ip);
+ bh_assert(global_idx < module->e->global_count);
+ global = globals + global_idx;
+ global_addr = get_global_addr(global_data, global);
+ addr1 = GET_OFFSET();
+ PUT_I64_TO_ADDR((uint32 *)global_addr,
+ GET_I64_FROM_ADDR(frame_lp + addr1));
+ HANDLE_OP_END();
+ }
+
+ /* memory load instructions */
+ HANDLE_OP(WASM_OP_I32_LOAD)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(4);
+ frame_lp[addr_ret] = LOAD_I32(maddr);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(8);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret, LOAD_I64(maddr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD8_S)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(1);
+ frame_lp[addr_ret] = sign_ext_8_32(*(int8 *)maddr);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD8_U)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(1);
+ frame_lp[addr_ret] = (uint32)(*(uint8 *)maddr);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD16_S)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(2);
+ frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LOAD16_U)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(2);
+ frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD8_S)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(1);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret,
+ sign_ext_8_64(*(int8 *)maddr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD8_U)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(1);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(*(uint8 *)maddr));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD16_S)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(2);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret,
+ sign_ext_16_64(LOAD_I16(maddr)));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD16_U)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(2);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(LOAD_U16(maddr)));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD32_S)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(4);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret,
+ sign_ext_32_64(LOAD_I32(maddr)));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LOAD32_U)
+ {
+ uint32 offset, addr;
+ offset = read_uint32(frame_ip);
+ addr = GET_OPERAND(uint32, I32, 0);
+ frame_ip += 2;
+ addr_ret = GET_OFFSET();
+ CHECK_MEMORY_OVERFLOW(4);
+ PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(LOAD_U32(maddr)));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_STORE)
+ {
+ uint32 offset, addr;
+ uint32 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint32, I32, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(4);
+ STORE_U32(maddr, sval);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_STORE8)
+ {
+ uint32 offset, addr;
+ uint32 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint32, I32, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(1);
+ *(uint8 *)maddr = (uint8)sval;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_STORE16)
+ {
+ uint32 offset, addr;
+ uint32 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint32, I32, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(2);
+ STORE_U16(maddr, (uint16)sval);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_STORE)
+ {
+ uint32 offset, addr;
+ uint64 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint64, I64, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(8);
+ STORE_I64(maddr, sval);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_STORE8)
+ {
+ uint32 offset, addr;
+ uint64 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint64, I64, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(1);
+ *(uint8 *)maddr = (uint8)sval;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_STORE16)
+ {
+ uint32 offset, addr;
+ uint64 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint64, I64, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(2);
+ STORE_U16(maddr, (uint16)sval);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_STORE32)
+ {
+ uint32 offset, addr;
+ uint64 sval;
+ offset = read_uint32(frame_ip);
+ sval = GET_OPERAND(uint64, I64, 0);
+ addr = GET_OPERAND(uint32, I32, 2);
+ frame_ip += 4;
+ CHECK_MEMORY_OVERFLOW(4);
+ STORE_U32(maddr, (uint32)sval);
+ HANDLE_OP_END();
+ }
+
+ /* memory size and memory grow instructions */
+ HANDLE_OP(WASM_OP_MEMORY_SIZE)
+ {
+ uint32 reserved;
+ addr_ret = GET_OFFSET();
+ frame_lp[addr_ret] = memory->cur_page_count;
+ (void)reserved;
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_MEMORY_GROW)
+ {
+ uint32 reserved, delta,
+ prev_page_count = memory->cur_page_count;
+
+ addr1 = GET_OFFSET();
+ addr_ret = GET_OFFSET();
+ delta = (uint32)frame_lp[addr1];
+
+ if (!wasm_enlarge_memory(module, delta)) {
+ /* failed to memory.grow, return -1 */
+ frame_lp[addr_ret] = -1;
+ }
+ else {
+ /* success, return previous page count */
+ frame_lp[addr_ret] = prev_page_count;
+ /* update memory size, no need to update memory ptr as
+ it isn't changed in wasm_enlarge_memory */
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ linear_mem_size = memory->memory_data_size;
+#endif
+ }
+
+ (void)reserved;
+ HANDLE_OP_END();
+ }
+
+ /* constant instructions */
+ HANDLE_OP(WASM_OP_F64_CONST)
+ HANDLE_OP(WASM_OP_I64_CONST)
+ {
+ uint8 *orig_ip = frame_ip;
+
+ frame_ip += sizeof(uint64);
+ addr_ret = GET_OFFSET();
+
+ bh_memcpy_s(frame_lp + addr_ret, sizeof(uint64), orig_ip,
+ sizeof(uint64));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONST)
+ HANDLE_OP(WASM_OP_I32_CONST)
+ {
+ uint8 *orig_ip = frame_ip;
+
+ frame_ip += sizeof(uint32);
+ addr_ret = GET_OFFSET();
+
+ bh_memcpy_s(frame_lp + addr_ret, sizeof(uint32), orig_ip,
+ sizeof(uint32));
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of i32 */
+ HANDLE_OP(WASM_OP_I32_EQZ)
+ {
+ DEF_OP_EQZ(int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_EQ)
+ {
+ DEF_OP_CMP(uint32, I32, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_NE)
+ {
+ DEF_OP_CMP(uint32, I32, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LT_S)
+ {
+ DEF_OP_CMP(int32, I32, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LT_U)
+ {
+ DEF_OP_CMP(uint32, I32, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GT_S)
+ {
+ DEF_OP_CMP(int32, I32, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GT_U)
+ {
+ DEF_OP_CMP(uint32, I32, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LE_S)
+ {
+ DEF_OP_CMP(int32, I32, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_LE_U)
+ {
+ DEF_OP_CMP(uint32, I32, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GE_S)
+ {
+ DEF_OP_CMP(int32, I32, >=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_GE_U)
+ {
+ DEF_OP_CMP(uint32, I32, >=);
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of i64 */
+ HANDLE_OP(WASM_OP_I64_EQZ)
+ {
+ DEF_OP_EQZ(int64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EQ)
+ {
+ DEF_OP_CMP(uint64, I64, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_NE)
+ {
+ DEF_OP_CMP(uint64, I64, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LT_S)
+ {
+ DEF_OP_CMP(int64, I64, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LT_U)
+ {
+ DEF_OP_CMP(uint64, I64, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GT_S)
+ {
+ DEF_OP_CMP(int64, I64, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GT_U)
+ {
+ DEF_OP_CMP(uint64, I64, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LE_S)
+ {
+ DEF_OP_CMP(int64, I64, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_LE_U)
+ {
+ DEF_OP_CMP(uint64, I64, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GE_S)
+ {
+ DEF_OP_CMP(int64, I64, >=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_GE_U)
+ {
+ DEF_OP_CMP(uint64, I64, >=);
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of f32 */
+ HANDLE_OP(WASM_OP_F32_EQ)
+ {
+ DEF_OP_CMP(float32, F32, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_NE)
+ {
+ DEF_OP_CMP(float32, F32, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_LT)
+ {
+ DEF_OP_CMP(float32, F32, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_GT)
+ {
+ DEF_OP_CMP(float32, F32, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_LE)
+ {
+ DEF_OP_CMP(float32, F32, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_GE)
+ {
+ DEF_OP_CMP(float32, F32, >=);
+ HANDLE_OP_END();
+ }
+
+ /* comparison instructions of f64 */
+ HANDLE_OP(WASM_OP_F64_EQ)
+ {
+ DEF_OP_CMP(float64, F64, ==);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_NE)
+ {
+ DEF_OP_CMP(float64, F64, !=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_LT)
+ {
+ DEF_OP_CMP(float64, F64, <);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_GT)
+ {
+ DEF_OP_CMP(float64, F64, >);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_LE)
+ {
+ DEF_OP_CMP(float64, F64, <=);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_GE)
+ {
+ DEF_OP_CMP(float64, F64, >=);
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of i32 */
+ HANDLE_OP(WASM_OP_I32_CLZ)
+ {
+ DEF_OP_BIT_COUNT(uint32, I32, clz32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_CTZ)
+ {
+ DEF_OP_BIT_COUNT(uint32, I32, ctz32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_POPCNT)
+ {
+ DEF_OP_BIT_COUNT(uint32, I32, popcount32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_ADD)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SUB)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_MUL)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_DIV_S)
+ {
+ int32 a, b;
+
+ b = frame_lp[GET_OFFSET()];
+ a = frame_lp[GET_OFFSET()];
+ addr_ret = GET_OFFSET();
+ if (a == (int32)0x80000000 && b == -1) {
+ wasm_set_exception(module, "integer overflow");
+ goto got_exception;
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ frame_lp[addr_ret] = (a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_DIV_U)
+ {
+ uint32 a, b;
+
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ addr_ret = GET_OFFSET();
+
+ b = (uint32)frame_lp[addr1];
+ a = (uint32)frame_lp[addr2];
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ frame_lp[addr_ret] = (a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_REM_S)
+ {
+ int32 a, b;
+
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ addr_ret = GET_OFFSET();
+
+ b = frame_lp[addr1];
+ a = frame_lp[addr2];
+ if (a == (int32)0x80000000 && b == -1) {
+ frame_lp[addr_ret] = 0;
+ HANDLE_OP_END();
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ frame_lp[addr_ret] = (a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_REM_U)
+ {
+ uint32 a, b;
+
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ addr_ret = GET_OFFSET();
+
+ b = (uint32)frame_lp[addr1];
+ a = (uint32)frame_lp[addr2];
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ frame_lp[addr_ret] = (a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_AND)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, &);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_OR)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, |);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_XOR)
+ {
+ DEF_OP_NUMERIC(uint32, uint32, I32, ^);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SHL)
+ {
+ DEF_OP_NUMERIC2(uint32, uint32, I32, <<);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SHR_S)
+ {
+ DEF_OP_NUMERIC2(int32, uint32, I32, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_SHR_U)
+ {
+ DEF_OP_NUMERIC2(uint32, uint32, I32, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_ROTL)
+ {
+ uint32 a, b;
+
+ b = (uint32)frame_lp[GET_OFFSET()];
+ a = (uint32)frame_lp[GET_OFFSET()];
+ frame_lp[GET_OFFSET()] = rotl32(a, b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_ROTR)
+ {
+ uint32 a, b;
+
+ b = (uint32)frame_lp[GET_OFFSET()];
+ a = (uint32)frame_lp[GET_OFFSET()];
+ frame_lp[GET_OFFSET()] = rotr32(a, b);
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of i64 */
+ HANDLE_OP(WASM_OP_I64_CLZ)
+ {
+ DEF_OP_BIT_COUNT(uint64, I64, clz64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_CTZ)
+ {
+ DEF_OP_BIT_COUNT(uint64, I64, ctz64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_POPCNT)
+ {
+ DEF_OP_BIT_COUNT(uint64, I64, popcount64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_ADD)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SUB)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_MUL)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_DIV_S)
+ {
+ int64 a, b;
+
+ b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ if (a == (int64)0x8000000000000000LL && b == -1) {
+ wasm_set_exception(module, "integer overflow");
+ goto got_exception;
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_DIV_U)
+ {
+ uint64 a, b;
+
+ b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a / b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_REM_S)
+ {
+ int64 a, b;
+
+ b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ if (a == (int64)0x8000000000000000LL && b == -1) {
+ *(int64 *)(frame_lp + GET_OFFSET()) = 0;
+ HANDLE_OP_END();
+ }
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_REM_U)
+ {
+ uint64 a, b;
+
+ b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ if (b == 0) {
+ wasm_set_exception(module, "integer divide by zero");
+ goto got_exception;
+ }
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a % b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_AND)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, &);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_OR)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, |);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_XOR)
+ {
+ DEF_OP_NUMERIC_64(uint64, uint64, I64, ^);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SHL)
+ {
+ DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SHR_S)
+ {
+ DEF_OP_NUMERIC2_64(int64, uint64, I64, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_SHR_U)
+ {
+ DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_ROTL)
+ {
+ uint64 a, b;
+
+ b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), rotl64(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_ROTR)
+ {
+ uint64 a, b;
+
+ b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), rotr64(a, b));
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of f32 */
+ HANDLE_OP(WASM_OP_F32_ABS)
+ {
+ DEF_OP_MATH(float32, F32, fabsf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_NEG)
+ {
+ uint32 u32 = frame_lp[GET_OFFSET()];
+ uint32 sign_bit = u32 & ((uint32)1 << 31);
+ addr_ret = GET_OFFSET();
+ if (sign_bit)
+ frame_lp[addr_ret] = u32 & ~((uint32)1 << 31);
+ else
+ frame_lp[addr_ret] = u32 | ((uint32)1 << 31);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CEIL)
+ {
+ DEF_OP_MATH(float32, F32, ceilf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_FLOOR)
+ {
+ DEF_OP_MATH(float32, F32, floorf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_TRUNC)
+ {
+ DEF_OP_MATH(float32, F32, truncf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_NEAREST)
+ {
+ DEF_OP_MATH(float32, F32, rintf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_SQRT)
+ {
+ DEF_OP_MATH(float32, F32, sqrtf);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_ADD)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_SUB)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_MUL)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_DIV)
+ {
+ DEF_OP_NUMERIC(float32, float32, F32, /);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_MIN)
+ {
+ float32 a, b;
+
+ b = *(float32 *)(frame_lp + GET_OFFSET());
+ a = *(float32 *)(frame_lp + GET_OFFSET());
+
+ *(float32 *)(frame_lp + GET_OFFSET()) = f32_min(a, b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_MAX)
+ {
+ float32 a, b;
+
+ b = *(float32 *)(frame_lp + GET_OFFSET());
+ a = *(float32 *)(frame_lp + GET_OFFSET());
+
+ *(float32 *)(frame_lp + GET_OFFSET()) = f32_max(a, b);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_COPYSIGN)
+ {
+ float32 a, b;
+
+ b = *(float32 *)(frame_lp + GET_OFFSET());
+ a = *(float32 *)(frame_lp + GET_OFFSET());
+ *(float32 *)(frame_lp + GET_OFFSET()) = local_copysignf(a, b);
+ HANDLE_OP_END();
+ }
+
+ /* numberic instructions of f64 */
+ HANDLE_OP(WASM_OP_F64_ABS)
+ {
+ DEF_OP_MATH(float64, F64, fabs);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_NEG)
+ {
+ uint64 u64 = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET());
+ uint64 sign_bit = u64 & (((uint64)1) << 63);
+ if (sign_bit)
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(),
+ (u64 & ~(((uint64)1) << 63)));
+ else
+ PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(),
+ (u64 | (((uint64)1) << 63)));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CEIL)
+ {
+ DEF_OP_MATH(float64, F64, ceil);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_FLOOR)
+ {
+ DEF_OP_MATH(float64, F64, floor);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_TRUNC)
+ {
+ DEF_OP_MATH(float64, F64, trunc);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_NEAREST)
+ {
+ DEF_OP_MATH(float64, F64, rint);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_SQRT)
+ {
+ DEF_OP_MATH(float64, F64, sqrt);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_ADD)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, +);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_SUB)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, -);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_MUL)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, *);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_DIV)
+ {
+ DEF_OP_NUMERIC_64(float64, float64, F64, /);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_MIN)
+ {
+ float64 a, b;
+
+ b = POP_F64();
+ a = POP_F64();
+
+ PUSH_F64(f64_min(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_MAX)
+ {
+ float64 a, b;
+
+ b = POP_F64();
+ a = POP_F64();
+
+ PUSH_F64(f64_max(a, b));
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_COPYSIGN)
+ {
+ float64 a, b;
+
+ b = POP_F64();
+ a = POP_F64();
+ PUSH_F64(local_copysign(a, b));
+ HANDLE_OP_END();
+ }
+
+ /* conversions of i32 */
+ HANDLE_OP(WASM_OP_I32_WRAP_I64)
+ {
+ int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL);
+ PUSH_I32(value);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_S_F32)
+ {
+ /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX,
+ since float/double values of ieee754 cannot precisely
+ represent all int32/uint32/int64/uint64 values, e.g.:
+ UINT32_MAX is 4294967295, but (float32)4294967295 is
+ 4294967296.0f, but not 4294967295.0f. */
+ DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_U_F32)
+ {
+ DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_S_F64)
+ {
+ DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_TRUNC_U_F64)
+ {
+ DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false);
+ HANDLE_OP_END();
+ }
+
+ /* conversions of i64 */
+ HANDLE_OP(WASM_OP_I64_EXTEND_S_I32)
+ {
+ DEF_OP_CONVERT(int64, I64, int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND_U_I32)
+ {
+ DEF_OP_CONVERT(int64, I64, uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_S_F32)
+ {
+ DEF_OP_TRUNC_F32(-9223373136366403584.0f,
+ 9223372036854775808.0f, false, true);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_U_F32)
+ {
+ DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f, false, false);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_S_F64)
+ {
+ DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0,
+ false, true);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_TRUNC_U_F64)
+ {
+ DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0, false, false);
+ HANDLE_OP_END();
+ }
+
+ /* conversions of f32 */
+ HANDLE_OP(WASM_OP_F32_CONVERT_S_I32)
+ {
+ DEF_OP_CONVERT(float32, F32, int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONVERT_U_I32)
+ {
+ DEF_OP_CONVERT(float32, F32, uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONVERT_S_I64)
+ {
+ DEF_OP_CONVERT(float32, F32, int64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_CONVERT_U_I64)
+ {
+ DEF_OP_CONVERT(float32, F32, uint64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F32_DEMOTE_F64)
+ {
+ DEF_OP_CONVERT(float32, F32, float64, F64);
+ HANDLE_OP_END();
+ }
+
+ /* conversions of f64 */
+ HANDLE_OP(WASM_OP_F64_CONVERT_S_I32)
+ {
+ DEF_OP_CONVERT(float64, F64, int32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONVERT_U_I32)
+ {
+ DEF_OP_CONVERT(float64, F64, uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONVERT_S_I64)
+ {
+ DEF_OP_CONVERT(float64, F64, int64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_CONVERT_U_I64)
+ {
+ DEF_OP_CONVERT(float64, F64, uint64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_F64_PROMOTE_F32)
+ {
+ DEF_OP_CONVERT(float64, F64, float32, F32);
+ HANDLE_OP_END();
+ }
+
+ /* reinterpretations */
+ HANDLE_OP(WASM_OP_I32_REINTERPRET_F32)
+ HANDLE_OP(WASM_OP_F32_REINTERPRET_I32)
+ {
+ DEF_OP_REINTERPRET(uint32, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_REINTERPRET_F64)
+ HANDLE_OP(WASM_OP_F64_REINTERPRET_I64)
+ {
+ DEF_OP_REINTERPRET(int64, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_COPY_STACK_TOP)
+ {
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ frame_lp[addr2] = frame_lp[addr1];
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_COPY_STACK_TOP_I64)
+ {
+ addr1 = GET_OFFSET();
+ addr2 = GET_OFFSET();
+ frame_lp[addr2] = frame_lp[addr1];
+ frame_lp[addr2 + 1] = frame_lp[addr1 + 1];
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(EXT_OP_COPY_STACK_VALUES)
+ {
+ uint32 values_count, total_cell;
+ uint8 *cells;
+ int16 *src_offsets = NULL;
+ uint16 *dst_offsets = NULL;
+
+ /* read values_count */
+ values_count = read_uint32(frame_ip);
+ /* read total cell num */
+ total_cell = read_uint32(frame_ip);
+ /* cells */
+ cells = (uint8 *)frame_ip;
+ frame_ip += values_count * CELL_SIZE;
+ /* src offsets */
+ src_offsets = (int16 *)frame_ip;
+ frame_ip += values_count * sizeof(int16);
+ /* dst offsets */
+ dst_offsets = (uint16 *)frame_ip;
+ frame_ip += values_count * sizeof(uint16);
+
+ if (!copy_stack_values(module, frame_lp, values_count,
+ total_cell, cells, src_offsets,
+ dst_offsets))
+ goto got_exception;
+
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_SET_LOCAL)
+ HANDLE_OP(WASM_OP_TEE_LOCAL)
+ {
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+ addr1 = GET_OFFSET();
+
+ if (local_type == VALUE_TYPE_I32
+ || local_type == VALUE_TYPE_F32) {
+ *(int32 *)(frame_lp + local_offset) = frame_lp[addr1];
+ }
+ else if (local_type == VALUE_TYPE_I64
+ || local_type == VALUE_TYPE_F64) {
+ PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset),
+ GET_I64_FROM_ADDR(frame_lp + addr1));
+ }
+ else {
+ wasm_set_exception(module, "invalid local type");
+ goto got_exception;
+ }
+
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_EXTEND8_S)
+ {
+ DEF_OP_CONVERT(int32, I32, int8, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I32_EXTEND16_S)
+ {
+ DEF_OP_CONVERT(int32, I32, int16, I32);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND8_S)
+ {
+ DEF_OP_CONVERT(int64, I64, int8, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND16_S)
+ {
+ DEF_OP_CONVERT(int64, I64, int16, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_I64_EXTEND32_S)
+ {
+ DEF_OP_CONVERT(int64, I64, int32, I64);
+ HANDLE_OP_END();
+ }
+
+ HANDLE_OP(WASM_OP_MISC_PREFIX)
+ {
+ GET_OPCODE();
+ switch (opcode) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f,
+ true, true);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f, true, false);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0, true,
+ true);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0, true, false);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f,
+ 9223372036854775808.0f, false,
+ true);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f,
+ false, false);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0,
+ 9223372036854775808.0, false,
+ true);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ DEF_OP_TRUNC_SAT_F64(-1.0, 18446744073709551616.0,
+ false, false);
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ {
+ uint32 addr, segment;
+ uint64 bytes, offset, seg_len;
+ uint8 *data;
+
+ segment = read_uint32(frame_ip);
+
+ bytes = (uint64)POP_I32();
+ offset = (uint64)POP_I32();
+ addr = POP_I32();
+
+#if WASM_ENABLE_THREAD_MGR
+ linear_mem_size = memory->memory_data_size;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr);
+#else
+ if ((uint64)(uint32)addr + bytes
+ > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ maddr = memory->memory_data + (uint32)addr;
+#endif
+
+ seg_len = (uint64)module->module->data_segments[segment]
+ ->data_length;
+ data = module->module->data_segments[segment]->data;
+ if (offset + bytes > seg_len)
+ goto out_of_bounds;
+
+ bh_memcpy_s(maddr, linear_mem_size - addr,
+ data + offset, (uint32)bytes);
+ break;
+ }
+ case WASM_OP_DATA_DROP:
+ {
+ uint32 segment;
+
+ segment = read_uint32(frame_ip);
+
+ module->module->data_segments[segment]->data_length = 0;
+ break;
+ }
+ case WASM_OP_MEMORY_COPY:
+ {
+ uint32 dst, src, len;
+ uint8 *mdst, *msrc;
+
+ len = POP_I32();
+ src = POP_I32();
+ dst = POP_I32();
+
+#if WASM_ENABLE_THREAD_MGR
+ linear_mem_size = memory->memory_data_size;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc);
+ CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
+#else
+ if ((uint64)(uint32)src + len > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ msrc = memory->memory_data + (uint32)src;
+
+ if ((uint64)(uint32)dst + len > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ mdst = memory->memory_data + (uint32)dst;
+#endif
+
+ /* allowing the destination and source to overlap */
+ bh_memmove_s(mdst, linear_mem_size - dst, msrc, len);
+ break;
+ }
+ case WASM_OP_MEMORY_FILL:
+ {
+ uint32 dst, len;
+ uint8 fill_val, *mdst;
+
+ len = POP_I32();
+ fill_val = POP_I32();
+ dst = POP_I32();
+
+#if WASM_ENABLE_THREAD_MGR
+ linear_mem_size = memory->memory_data_size;
+#endif
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
+#else
+ if ((uint64)(uint32)dst + len > (uint64)linear_mem_size)
+ goto out_of_bounds;
+ mdst = memory->memory_data + (uint32)dst;
+#endif
+
+ memset(mdst, fill_val, len);
+ break;
+ }
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ {
+ uint32 tbl_idx, elem_idx;
+ uint64 n, s, d;
+ WASMTableInstance *tbl_inst;
+
+ elem_idx = read_uint32(frame_ip);
+ bh_assert(elem_idx < module->module->table_seg_count);
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ n = (uint32)POP_I32();
+ s = (uint32)POP_I32();
+ d = (uint32)POP_I32();
+
+ if (!n) {
+ break;
+ }
+
+ if (n + s > module->module->table_segments[elem_idx]
+ .function_count
+ || d + n > tbl_inst->cur_size) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ if (module->module->table_segments[elem_idx]
+ .is_dropped) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ if (!wasm_elem_is_passive(
+ module->module->table_segments[elem_idx]
+ .mode)) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ bh_memcpy_s(
+ (uint8 *)tbl_inst
+ + offsetof(WASMTableInstance, elems)
+ + d * sizeof(uint32),
+ (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)),
+ module->module->table_segments[elem_idx]
+ .func_indexes
+ + s,
+ (uint32)(n * sizeof(uint32)));
+ break;
+ }
+ case WASM_OP_ELEM_DROP:
+ {
+ uint32 elem_idx = read_uint32(frame_ip);
+ bh_assert(elem_idx < module->module->table_seg_count);
+
+ module->module->table_segments[elem_idx].is_dropped =
+ true;
+ break;
+ }
+ case WASM_OP_TABLE_COPY:
+ {
+ uint32 src_tbl_idx, dst_tbl_idx;
+ uint64 n, s, d;
+ WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
+
+ dst_tbl_idx = read_uint32(frame_ip);
+ bh_assert(dst_tbl_idx < module->table_count);
+
+ dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx);
+
+ src_tbl_idx = read_uint32(frame_ip);
+ bh_assert(src_tbl_idx < module->table_count);
+
+ src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx);
+
+ n = (uint32)POP_I32();
+ s = (uint32)POP_I32();
+ d = (uint32)POP_I32();
+
+ if (d + n > dst_tbl_inst->cur_size
+ || s + n > src_tbl_inst->cur_size) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ /* if s >= d, copy from front to back */
+ /* if s < d, copy from back to front */
+ /* merge all together */
+ bh_memmove_s((uint8 *)dst_tbl_inst
+ + offsetof(WASMTableInstance, elems)
+ + d * sizeof(uint32),
+ (uint32)((dst_tbl_inst->cur_size - d)
+ * sizeof(uint32)),
+ (uint8 *)src_tbl_inst
+ + offsetof(WASMTableInstance, elems)
+ + s * sizeof(uint32),
+ (uint32)(n * sizeof(uint32)));
+ break;
+ }
+ case WASM_OP_TABLE_GROW:
+ {
+ uint32 tbl_idx, n, init_val, orig_tbl_sz;
+ WASMTableInstance *tbl_inst;
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ orig_tbl_sz = tbl_inst->cur_size;
+
+ n = POP_I32();
+ init_val = POP_I32();
+
+ if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) {
+ PUSH_I32(-1);
+ }
+ else {
+ PUSH_I32(orig_tbl_sz);
+ }
+
+ break;
+ }
+ case WASM_OP_TABLE_SIZE:
+ {
+ uint32 tbl_idx;
+ WASMTableInstance *tbl_inst;
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ PUSH_I32(tbl_inst->cur_size);
+ break;
+ }
+ case WASM_OP_TABLE_FILL:
+ {
+ uint32 tbl_idx, n, fill_val, i;
+ WASMTableInstance *tbl_inst;
+
+ tbl_idx = read_uint32(frame_ip);
+ bh_assert(tbl_idx < module->table_count);
+
+ tbl_inst = wasm_get_table_inst(module, tbl_idx);
+
+ n = POP_I32();
+ fill_val = POP_I32();
+ i = POP_I32();
+
+ if (i + n > tbl_inst->cur_size) {
+ wasm_set_exception(module,
+ "out of bounds table access");
+ goto got_exception;
+ }
+
+ for (; n != 0; i++, n--) {
+ tbl_inst->elems[i] = fill_val;
+ }
+
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ wasm_set_exception(module, "unsupported opcode");
+ goto got_exception;
+ }
+ HANDLE_OP_END();
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ HANDLE_OP(WASM_OP_ATOMIC_PREFIX)
+ {
+ uint32 offset = 0, addr;
+
+ GET_OPCODE();
+
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ offset = read_uint32(frame_ip);
+ }
+
+ switch (opcode) {
+ case WASM_OP_ATOMIC_NOTIFY:
+ {
+ uint32 notify_count, ret;
+
+ notify_count = POP_I32();
+ addr = POP_I32();
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+
+ ret = wasm_runtime_atomic_notify(
+ (WASMModuleInstanceCommon *)module, maddr,
+ notify_count);
+ if (ret == (uint32)-1)
+ goto got_exception;
+
+ PUSH_I32(ret);
+ break;
+ }
+ case WASM_OP_ATOMIC_WAIT32:
+ {
+ uint64 timeout;
+ uint32 expect, ret;
+
+ timeout = POP_I64();
+ expect = POP_I32();
+ addr = POP_I32();
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+
+ ret = wasm_runtime_atomic_wait(
+ (WASMModuleInstanceCommon *)module, maddr,
+ (uint64)expect, timeout, false);
+ if (ret == (uint32)-1)
+ goto got_exception;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+
+ PUSH_I32(ret);
+ break;
+ }
+ case WASM_OP_ATOMIC_WAIT64:
+ {
+ uint64 timeout, expect;
+ uint32 ret;
+
+ timeout = POP_I64();
+ expect = POP_I64();
+ addr = POP_I32();
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(8);
+
+ ret = wasm_runtime_atomic_wait(
+ (WASMModuleInstanceCommon *)module, maddr, expect,
+ timeout, true);
+ if (ret == (uint32)-1)
+ goto got_exception;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+
+ PUSH_I32(ret);
+ break;
+ }
+ case WASM_OP_ATOMIC_FENCE:
+ {
+ os_atomic_thread_fence(os_memory_order_seq_cst);
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I32_LOAD:
+ case WASM_OP_ATOMIC_I32_LOAD8_U:
+ case WASM_OP_ATOMIC_I32_LOAD16_U:
+ {
+ uint32 readv;
+
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(1);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)(*(uint8 *)maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(2);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)LOAD_U16(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = LOAD_I32(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+
+ PUSH_I32(readv);
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I64_LOAD:
+ case WASM_OP_ATOMIC_I64_LOAD8_U:
+ case WASM_OP_ATOMIC_I64_LOAD16_U:
+ case WASM_OP_ATOMIC_I64_LOAD32_U:
+ {
+ uint64 readv;
+
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(1);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)(*(uint8 *)maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(2);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U16(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U32(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(8);
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = LOAD_I64(maddr);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+
+ PUSH_I64(readv);
+ break;
+ }
+ case WASM_OP_ATOMIC_I32_STORE:
+ case WASM_OP_ATOMIC_I32_STORE8:
+ case WASM_OP_ATOMIC_I32_STORE16:
+ {
+ uint32 sval;
+
+ sval = (uint32)POP_I32();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(1);
+ os_mutex_lock(&node->shared_mem_lock);
+ *(uint8 *)maddr = (uint8)sval;
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(2);
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U16(maddr, (uint16)sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U32(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ break;
+ }
+
+ case WASM_OP_ATOMIC_I64_STORE:
+ case WASM_OP_ATOMIC_I64_STORE8:
+ case WASM_OP_ATOMIC_I64_STORE16:
+ case WASM_OP_ATOMIC_I64_STORE32:
+ {
+ uint64 sval;
+
+ sval = (uint64)POP_I64();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(1);
+ os_mutex_lock(&node->shared_mem_lock);
+ *(uint8 *)maddr = (uint8)sval;
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(2);
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U16(maddr, (uint16)sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_U32(maddr, (uint32)sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(8);
+ os_mutex_lock(&node->shared_mem_lock);
+ STORE_I64(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ break;
+ }
+
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
+ {
+ uint32 readv, sval, expect;
+
+ sval = POP_I32();
+ expect = POP_I32();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(1);
+
+ expect = (uint8)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)(*(uint8 *)maddr);
+ if (readv == expect)
+ *(uint8 *)maddr = (uint8)(sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(2);
+
+ expect = (uint16)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint32)LOAD_U16(maddr);
+ if (readv == expect)
+ STORE_U16(maddr, (uint16)(sval));
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = LOAD_I32(maddr);
+ if (readv == expect)
+ STORE_U32(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ PUSH_I32(readv);
+ break;
+ }
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
+ {
+ uint64 readv, sval, expect;
+
+ sval = (uint64)POP_I64();
+ expect = (uint64)POP_I64();
+ addr = POP_I32();
+
+ if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(1);
+
+ expect = (uint8)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)(*(uint8 *)maddr);
+ if (readv == expect)
+ *(uint8 *)maddr = (uint8)(sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(2);
+
+ expect = (uint16)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U16(maddr);
+ if (readv == expect)
+ STORE_U16(maddr, (uint16)(sval));
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(4);
+
+ expect = (uint32)expect;
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_U32(maddr);
+ if (readv == expect)
+ STORE_U32(maddr, (uint32)(sval));
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ else {
+ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
+ CHECK_ATOMIC_MEMORY_ACCESS(8);
+
+ os_mutex_lock(&node->shared_mem_lock);
+ readv = (uint64)LOAD_I64(maddr);
+ if (readv == expect)
+ STORE_I64(maddr, sval);
+ os_mutex_unlock(&node->shared_mem_lock);
+ }
+ PUSH_I64(readv);
+ break;
+ }
+
+ DEF_ATOMIC_RMW_OPCODE(ADD, +);
+ DEF_ATOMIC_RMW_OPCODE(SUB, -);
+ DEF_ATOMIC_RMW_OPCODE(AND, &);
+ DEF_ATOMIC_RMW_OPCODE(OR, |);
+ DEF_ATOMIC_RMW_OPCODE(XOR, ^);
+ /* xchg, ignore the read value, and store the given
+ value: readv * 0 + sval */
+ DEF_ATOMIC_RMW_OPCODE(XCHG, *0 +);
+ }
+
+ HANDLE_OP_END();
+ }
+#endif
+
+ HANDLE_OP(WASM_OP_IMPDEP)
+ {
+ frame = prev_frame;
+ frame_ip = frame->ip;
+ goto call_func_from_entry;
+ }
+
+ HANDLE_OP(WASM_OP_CALL)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ fidx = read_uint32(frame_ip);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (fidx >= module->e->function_count) {
+ wasm_set_exception(module, "unknown function");
+ goto got_exception;
+ }
+#endif
+ cur_func = module->e->functions + fidx;
+ goto call_func_from_interp;
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ HANDLE_OP(WASM_OP_RETURN_CALL)
+ {
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ fidx = read_uint32(frame_ip);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (fidx >= module->e->function_count) {
+ wasm_set_exception(module, "unknown function");
+ goto got_exception;
+ }
+#endif
+ cur_func = module->e->functions + fidx;
+ goto call_func_from_return_call;
+ }
+#endif /* WASM_ENABLE_TAIL_CALL */
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ default:
+ wasm_set_exception(module, "unsupported opcode");
+ goto got_exception;
+ }
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+ HANDLE_OP(WASM_OP_UNUSED_0x06)
+ HANDLE_OP(WASM_OP_UNUSED_0x07)
+ HANDLE_OP(WASM_OP_UNUSED_0x08)
+ HANDLE_OP(WASM_OP_UNUSED_0x09)
+ HANDLE_OP(WASM_OP_UNUSED_0x0a)
+#if WASM_ENABLE_TAIL_CALL == 0
+ HANDLE_OP(WASM_OP_RETURN_CALL)
+ HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT)
+#endif
+#if WASM_ENABLE_SHARED_MEMORY == 0
+ HANDLE_OP(WASM_OP_ATOMIC_PREFIX)
+#endif
+#if WASM_ENABLE_REF_TYPES == 0
+ HANDLE_OP(WASM_OP_TABLE_GET)
+ HANDLE_OP(WASM_OP_TABLE_SET)
+ HANDLE_OP(WASM_OP_REF_NULL)
+ HANDLE_OP(WASM_OP_REF_IS_NULL)
+ HANDLE_OP(WASM_OP_REF_FUNC)
+#endif
+ /* SELECT_T is converted to SELECT or SELECT_64 */
+ HANDLE_OP(WASM_OP_SELECT_T)
+ HANDLE_OP(WASM_OP_UNUSED_0x14)
+ HANDLE_OP(WASM_OP_UNUSED_0x15)
+ HANDLE_OP(WASM_OP_UNUSED_0x16)
+ HANDLE_OP(WASM_OP_UNUSED_0x17)
+ HANDLE_OP(WASM_OP_UNUSED_0x18)
+ HANDLE_OP(WASM_OP_UNUSED_0x19)
+ HANDLE_OP(WASM_OP_UNUSED_0x27)
+ /* optimized op code */
+ HANDLE_OP(WASM_OP_F32_STORE)
+ HANDLE_OP(WASM_OP_F64_STORE)
+ HANDLE_OP(WASM_OP_F32_LOAD)
+ HANDLE_OP(WASM_OP_F64_LOAD)
+ HANDLE_OP(EXT_OP_GET_LOCAL_FAST)
+ HANDLE_OP(WASM_OP_GET_LOCAL)
+ HANDLE_OP(WASM_OP_DROP)
+ HANDLE_OP(WASM_OP_DROP_64)
+ HANDLE_OP(WASM_OP_BLOCK)
+ HANDLE_OP(WASM_OP_LOOP)
+ HANDLE_OP(WASM_OP_END)
+ HANDLE_OP(WASM_OP_NOP)
+ HANDLE_OP(EXT_OP_BLOCK)
+ HANDLE_OP(EXT_OP_LOOP)
+ HANDLE_OP(EXT_OP_IF)
+ HANDLE_OP(EXT_OP_BR_TABLE_CACHE)
+ {
+ wasm_set_exception(module, "unsupported opcode");
+ goto got_exception;
+ }
+#endif
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ continue;
+#else
+ FETCH_OPCODE_AND_DISPATCH();
+#endif
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ call_func_from_return_call:
+ {
+ uint32 *lp_base;
+ uint32 *lp;
+ int i;
+
+ if (!(lp_base = lp = wasm_runtime_malloc(cur_func->param_cell_num
+ * sizeof(uint32)))) {
+ wasm_set_exception(module, "allocate memory failed");
+ goto got_exception;
+ }
+ for (i = 0; i < cur_func->param_count; i++) {
+ if (cur_func->param_types[i] == VALUE_TYPE_I64
+ || cur_func->param_types[i] == VALUE_TYPE_F64) {
+ PUT_I64_TO_ADDR(
+ lp, GET_OPERAND(uint64, I64,
+ 2 * (cur_func->param_count - i - 1)));
+ lp += 2;
+ }
+ else {
+ *lp = GET_OPERAND(uint32, I32,
+ (2 * (cur_func->param_count - i - 1)));
+ lp++;
+ }
+ }
+ frame->lp = frame->operand + cur_func->const_cell_num;
+ if (lp - lp_base > 0) {
+ word_copy(frame->lp, lp_base, lp - lp_base);
+ }
+ wasm_runtime_free(lp_base);
+ FREE_FRAME(exec_env, frame);
+ frame_ip += cur_func->param_count * sizeof(int16);
+ wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame);
+ goto call_func_from_entry;
+ }
+#endif /* WASM_ENABLE_TAIL_CALL */
+
+ call_func_from_interp:
+ {
+ /* Only do the copy when it's called from interpreter. */
+ WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env);
+ int i;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (cur_func->is_import_func) {
+ outs_area->lp = outs_area->operand
+ + (cur_func->import_func_inst
+ ? cur_func->import_func_inst->const_cell_num
+ : 0);
+ }
+ else
+#endif
+ {
+ outs_area->lp = outs_area->operand + cur_func->const_cell_num;
+ }
+
+ if ((uint8 *)(outs_area->lp + cur_func->param_cell_num)
+ > exec_env->wasm_stack.s.top_boundary) {
+ wasm_set_exception(module, "wasm operand stack overflow");
+ goto got_exception;
+ }
+
+ for (i = 0; i < cur_func->param_count; i++) {
+ if (cur_func->param_types[i] == VALUE_TYPE_I64
+ || cur_func->param_types[i] == VALUE_TYPE_F64) {
+ PUT_I64_TO_ADDR(
+ outs_area->lp,
+ GET_OPERAND(uint64, I64,
+ 2 * (cur_func->param_count - i - 1)));
+ outs_area->lp += 2;
+ }
+ else {
+ *outs_area->lp = GET_OPERAND(
+ uint32, I32, (2 * (cur_func->param_count - i - 1)));
+ outs_area->lp++;
+ }
+ }
+ frame_ip += cur_func->param_count * sizeof(int16);
+ if (cur_func->ret_cell_num != 0) {
+ /* Get the first return value's offset. Since loader emit
+ * all return values' offset so we must skip remain return
+ * values' offsets.
+ */
+ WASMType *func_type;
+ if (cur_func->is_import_func)
+ func_type = cur_func->u.func_import->func_type;
+ else
+ func_type = cur_func->u.func->func_type;
+ frame->ret_offset = GET_OFFSET();
+ frame_ip += 2 * (func_type->result_count - 1);
+ }
+ SYNC_ALL_TO_FRAME();
+ prev_frame = frame;
+ }
+
+ call_func_from_entry:
+ {
+ if (cur_func->is_import_func) {
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (cur_func->import_func_inst) {
+ wasm_interp_call_func_import(module, exec_env, cur_func,
+ prev_frame);
+ }
+ else
+#endif
+ {
+ 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();
+
+ /* update memory size, no need to update memory ptr as
+ it isn't changed in wasm_enlarge_memory */
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ if (memory)
+ linear_mem_size = memory->memory_data_size;
+#endif
+ if (wasm_copy_exception(module, NULL))
+ goto got_exception;
+ }
+ else {
+ WASMFunction *cur_wasm_func = cur_func->u.func;
+
+ all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num
+ + cur_func->const_cell_num
+ + cur_wasm_func->max_stack_cell_num;
+ /* param_cell_num, local_cell_num, const_cell_num and
+ max_stack_cell_num are all no larger than UINT16_MAX (checked
+ in loader), all_cell_num must be smaller than 1MB */
+ bh_assert(all_cell_num < 1 * BH_MB);
+
+ frame_size = wasm_interp_interp_frame_size(all_cell_num);
+ 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_get_func_code(cur_func);
+ frame_ip_end = wasm_get_func_code_end(cur_func);
+
+ frame_lp = frame->lp =
+ frame->operand + cur_wasm_func->const_cell_num;
+
+ /* Initialize the consts */
+ if (cur_wasm_func->const_cell_num > 0) {
+ word_copy(frame->operand, (uint32 *)cur_wasm_func->consts,
+ cur_wasm_func->const_cell_num);
+ }
+
+ /* Initialize the local variables */
+ memset(frame_lp + cur_func->param_cell_num, 0,
+ (uint32)(cur_func->local_cell_num * 4));
+
+ wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame);
+ }
+#if WASM_ENABLE_THREAD_MGR != 0
+ CHECK_SUSPEND_FLAGS();
+#endif
+ HANDLE_OP_END();
+ }
+
+ return_func:
+ {
+ FREE_FRAME(exec_env, frame);
+ wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame);
+
+ if (!prev_frame->ip)
+ /* Called from native. */
+ return;
+
+ RECOVER_CONTEXT(prev_frame);
+ HANDLE_OP_END();
+ }
+
+ (void)frame_ip_end;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ unaligned_atomic:
+ wasm_set_exception(module, "unaligned atomic");
+ goto got_exception;
+#endif
+
+#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
+ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
+ || WASM_ENABLE_BULK_MEMORY != 0
+ out_of_bounds:
+ wasm_set_exception(module, "out of bounds memory access");
+#endif
+
+ got_exception:
+ SYNC_ALL_TO_FRAME();
+ return;
+
+#if WASM_ENABLE_LABELS_AS_VALUES == 0
+ }
+#else
+ FETCH_OPCODE_AND_DISPATCH();
+#endif
+}
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+void **
+wasm_interp_get_handle_table()
+{
+ WASMModuleInstance module;
+ memset(&module, 0, sizeof(WASMModuleInstance));
+ wasm_interp_call_func_bytecode(&module, NULL, NULL, NULL);
+ return global_handle_table;
+}
+#endif
+
+void
+wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
+ WASMFunctionInstance *function, uint32 argc,
+ uint32 argv[])
+{
+ WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
+ WASMInterpFrame *frame, *outs_area;
+
+ /* Allocate sufficient cells for all kinds of return values. */
+ unsigned all_cell_num =
+ function->ret_cell_num > 2 ? function->ret_cell_num : 2,
+ i;
+ /* This frame won't be used by JITed code, so only allocate interp
+ frame here. */
+ unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
+ char exception[EXCEPTION_BUF_LEN];
+
+ if (argc < function->param_cell_num) {
+ char buf[128];
+ snprintf(buf, sizeof(buf),
+ "invalid argument count %" PRIu32
+ ", must be no smaller than %" PRIu32,
+ argc, (uint32)function->param_cell_num);
+ wasm_set_exception(module_inst, buf);
+ return;
+ }
+ argc = function->param_cell_num;
+
+ RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
+#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
+ && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
+ if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
+ wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
+ "native stack overflow");
+ return;
+ }
+#endif
+
+ if (!(frame =
+ ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame *)prev_frame)))
+ return;
+
+ outs_area = wasm_exec_env_wasm_stack_top(exec_env);
+ frame->function = NULL;
+ frame->ip = NULL;
+ /* There is no local variable. */
+ frame->lp = frame->operand + 0;
+ frame->ret_offset = 0;
+
+ if ((uint8 *)(outs_area->operand + function->const_cell_num + argc)
+ > exec_env->wasm_stack.s.top_boundary) {
+ wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
+ "wasm operand stack overflow");
+ return;
+ }
+
+ if (argc > 0)
+ word_copy(outs_area->operand + function->const_cell_num, argv, argc);
+
+ wasm_exec_env_set_cur_frame(exec_env, frame);
+
+ if (function->is_import_func) {
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (function->import_module_inst) {
+ LOG_DEBUG("it is a function of a sub module");
+ wasm_interp_call_func_import(module_inst, exec_env, function,
+ frame);
+ }
+ else
+#endif
+ {
+ LOG_DEBUG("it is an native function");
+ wasm_interp_call_func_native(module_inst, exec_env, function,
+ frame);
+ }
+ }
+ else {
+ wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
+ }
+
+ /* Output the return value to the caller */
+ if (!wasm_copy_exception(module_inst, NULL)) {
+ for (i = 0; i < function->ret_cell_num; i++)
+ argv[i] = *(frame->lp + i);
+ }
+ else {
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (wasm_interp_create_call_stack(exec_env)) {
+ wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
+ }
+#endif
+ wasm_copy_exception(module_inst, exception);
+ LOG_DEBUG("meet an exception %s", exception);
+ }
+
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+ FREE_FRAME(exec_env, frame);
+#if WASM_ENABLE_OPCODE_COUNTER != 0
+ wasm_interp_dump_op_count();
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.c
new file mode 100644
index 000000000..a3c4f4224
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.c
@@ -0,0 +1,10131 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_loader.h"
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm.h"
+#include "wasm_opcode.h"
+#include "wasm_runtime.h"
+#include "../common/wasm_native.h"
+#include "../common/wasm_memory.h"
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#include "../libraries/debug-engine/debug_engine.h"
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+#include "../fast-jit/jit_compiler.h"
+#include "../fast-jit/jit_codecache.h"
+#endif
+#if WASM_ENABLE_JIT != 0
+#include "../compilation/aot_llvm.h"
+#endif
+
+/* 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
+ value being read. */
+#define TEMPLATE_READ_VALUE(Type, p) \
+ (p += sizeof(Type), *(Type *)(p - sizeof(Type)))
+
+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, "WASM module load failed: %s",
+ string);
+ }
+}
+
+static void
+set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
+{
+ va_list args;
+ char buf[128];
+
+ if (error_buf != NULL) {
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ snprintf(error_buf, error_buf_size, "WASM module load failed: %s", buf);
+ }
+}
+
+static bool
+check_buf(const uint8 *buf, const uint8 *buf_end, uint32 length,
+ char *error_buf, uint32 error_buf_size)
+{
+ if ((uintptr_t)buf + length < (uintptr_t)buf
+ || (uintptr_t)buf + length > (uintptr_t)buf_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "unexpected end of section or function");
+ return false;
+ }
+ return true;
+}
+
+static bool
+check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length,
+ char *error_buf, uint32 error_buf_size)
+{
+ if ((uintptr_t)buf + length < (uintptr_t)buf
+ || (uintptr_t)buf + length > (uintptr_t)buf_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ return false;
+ }
+ return true;
+}
+
+#define CHECK_BUF(buf, buf_end, length) \
+ do { \
+ if (!check_buf(buf, buf_end, length, error_buf, error_buf_size)) { \
+ goto fail; \
+ } \
+ } while (0)
+
+#define CHECK_BUF1(buf, buf_end, length) \
+ do { \
+ if (!check_buf1(buf, buf_end, length, error_buf, error_buf_size)) { \
+ goto fail; \
+ } \
+ } while (0)
+
+#define skip_leb(p) while (*p++ & 0x80)
+#define skip_leb_int64(p, p_end) skip_leb(p)
+#define skip_leb_uint32(p, p_end) skip_leb(p)
+#define skip_leb_int32(p, p_end) skip_leb(p)
+
+static bool
+read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
+ uint64 *p_result, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ uint64 result = 0;
+ uint32 shift = 0;
+ uint32 offset = 0, bcnt = 0;
+ uint64 byte;
+
+ while (true) {
+ /* uN or SN must not exceed ceil(N/7) bytes */
+ if (bcnt + 1 > (maxbits + 6) / 7) {
+ set_error_buf(error_buf, error_buf_size,
+ "integer representation too long");
+ return false;
+ }
+
+ CHECK_BUF(buf, buf_end, offset + 1);
+ byte = buf[offset];
+ offset += 1;
+ result |= ((byte & 0x7f) << shift);
+ shift += 7;
+ bcnt += 1;
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ }
+
+ if (!sign && maxbits == 32 && shift >= maxbits) {
+ /* The top bits set represent values > 32 bits */
+ if (((uint8)byte) & 0xf0)
+ goto fail_integer_too_large;
+ }
+ else if (sign && maxbits == 32) {
+ if (shift < maxbits) {
+ /* Sign extend, second highest bit is the sign bit */
+ if ((uint8)byte & 0x40)
+ result |= (~((uint64)0)) << shift;
+ }
+ else {
+ /* The top bits should be a sign-extension of the sign bit */
+ bool sign_bit_set = ((uint8)byte) & 0x8;
+ int top_bits = ((uint8)byte) & 0xf0;
+ if ((sign_bit_set && top_bits != 0x70)
+ || (!sign_bit_set && top_bits != 0))
+ goto fail_integer_too_large;
+ }
+ }
+ else if (sign && maxbits == 64) {
+ if (shift < maxbits) {
+ /* Sign extend, second highest bit is the sign bit */
+ if ((uint8)byte & 0x40)
+ result |= (~((uint64)0)) << shift;
+ }
+ else {
+ /* The top bits should be a sign-extension of the sign bit */
+ bool sign_bit_set = ((uint8)byte) & 0x1;
+ int top_bits = ((uint8)byte) & 0xfe;
+
+ if ((sign_bit_set && top_bits != 0x7e)
+ || (!sign_bit_set && top_bits != 0))
+ goto fail_integer_too_large;
+ }
+ }
+
+ *p_buf += offset;
+ *p_result = result;
+ return true;
+
+fail_integer_too_large:
+ set_error_buf(error_buf, error_buf_size, "integer too large");
+fail:
+ return false;
+}
+
+#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p)
+#define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p)
+#define read_bool(p) TEMPLATE_READ_VALUE(bool, p)
+
+#define read_leb_int64(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ if (!read_leb((uint8 **)&p, p_end, 64, true, &res64, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ res = (int64)res64; \
+ } while (0)
+
+#define read_leb_uint32(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ if (!read_leb((uint8 **)&p, p_end, 32, false, &res64, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ res = (uint32)res64; \
+ } while (0)
+
+#define read_leb_int32(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ if (!read_leb((uint8 **)&p, p_end, 32, true, &res64, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ res = (int32)res64; \
+ } while (0)
+
+static char *
+type2str(uint8 type)
+{
+ char *type_str[] = { "v128", "f64", "f32", "i64", "i32" };
+
+ if (type >= VALUE_TYPE_V128 && type <= VALUE_TYPE_I32)
+ return type_str[type - VALUE_TYPE_V128];
+ else if (type == VALUE_TYPE_FUNCREF)
+ return "funcref";
+ else if (type == VALUE_TYPE_EXTERNREF)
+ return "externref";
+ else
+ return "unknown type";
+}
+
+static bool
+is_32bit_type(uint8 type)
+{
+ if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+#if WASM_ENABLE_REF_TYPES != 0
+ || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+#endif
+ )
+ return true;
+ return false;
+}
+
+static bool
+is_64bit_type(uint8 type)
+{
+ if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)
+ return true;
+ return false;
+}
+
+static bool
+is_value_type(uint8 type)
+{
+ if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_I64
+ || type == VALUE_TYPE_F32 || type == VALUE_TYPE_F64
+#if WASM_ENABLE_REF_TYPES != 0
+ || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+#endif
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ || type == VALUE_TYPE_V128
+#endif
+#endif
+ )
+ return true;
+ return false;
+}
+
+static bool
+is_byte_a_type(uint8 type)
+{
+ return is_value_type(type) || (type == VALUE_TYPE_VOID);
+}
+
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+static V128
+read_i8x16(uint8 *p_buf, char *error_buf, uint32 error_buf_size)
+{
+ V128 result;
+ uint8 i;
+
+ for (i = 0; i != 16; ++i) {
+ result.i8x16[i] = read_uint8(p_buf);
+ }
+
+ return result;
+}
+#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
+#endif /* end of WASM_ENABLE_SIMD */
+
+static void *
+loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+static bool
+check_utf8_str(const uint8 *str, uint32 len)
+{
+ /* The valid ranges are taken from page 125, below link
+ https://www.unicode.org/versions/Unicode9.0.0/ch03.pdf */
+ const uint8 *p = str, *p_end = str + len;
+ uint8 chr;
+
+ while (p < p_end) {
+ chr = *p;
+ if (chr < 0x80) {
+ p++;
+ }
+ else if (chr >= 0xC2 && chr <= 0xDF && p + 1 < p_end) {
+ if (p[1] < 0x80 || p[1] > 0xBF) {
+ return false;
+ }
+ p += 2;
+ }
+ else if (chr >= 0xE0 && chr <= 0xEF && p + 2 < p_end) {
+ if (chr == 0xE0) {
+ if (p[1] < 0xA0 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr == 0xED) {
+ if (p[1] < 0x80 || p[1] > 0x9F || p[2] < 0x80 || p[2] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr >= 0xE1 && chr <= 0xEF) {
+ if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) {
+ return false;
+ }
+ }
+ p += 3;
+ }
+ else if (chr >= 0xF0 && chr <= 0xF4 && p + 3 < p_end) {
+ if (chr == 0xF0) {
+ if (p[1] < 0x90 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF
+ || p[3] < 0x80 || p[3] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr >= 0xF1 && chr <= 0xF3) {
+ if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF
+ || p[3] < 0x80 || p[3] > 0xBF) {
+ return false;
+ }
+ }
+ else if (chr == 0xF4) {
+ if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF
+ || p[3] < 0x80 || p[3] > 0xBF) {
+ return false;
+ }
+ }
+ p += 4;
+ }
+ else {
+ return false;
+ }
+ }
+ return (p == p_end);
+}
+
+static char *
+const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ StringNode *node, *node_next;
+
+ if (!check_utf8_str(str, len)) {
+ set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding");
+ return NULL;
+ }
+
+ if (len == 0) {
+ return "";
+ }
+ else if (is_load_from_file_buf) {
+ /* As the file buffer can be referred to after loading, we use
+ the previous byte of leb encoded size to adjust the string:
+ move string 1 byte backward and then append '\0' */
+ char *c_str = (char *)str - 1;
+ bh_memmove_s(c_str, len + 1, c_str + 1, len);
+ c_str[len] = '\0';
+ return c_str;
+ }
+
+ /* Search const str list */
+ node = module->const_str_list;
+ while (node) {
+ node_next = node->next;
+ if (strlen(node->str) == len && !memcmp(node->str, str, len))
+ break;
+ node = node_next;
+ }
+
+ if (node) {
+ return node->str;
+ }
+
+ if (!(node = loader_malloc(sizeof(StringNode) + len + 1, error_buf,
+ error_buf_size))) {
+ return NULL;
+ }
+
+ node->str = ((char *)node) + sizeof(StringNode);
+ bh_memcpy_s(node->str, len + 1, str, len);
+ node->str[len] = '\0';
+
+ if (!module->const_str_list) {
+ /* set as head */
+ module->const_str_list = node;
+ node->next = NULL;
+ }
+ else {
+ /* insert it */
+ node->next = module->const_str_list;
+ module->const_str_list = node;
+ }
+
+ return node->str;
+}
+
+static void
+destroy_wasm_type(WASMType *type)
+{
+ if (type->ref_count > 1) {
+ /* The type is referenced by other types
+ of current wasm module */
+ type->ref_count--;
+ return;
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ if (type->call_to_llvm_jit_from_fast_jit)
+ jit_code_cache_free(type->call_to_llvm_jit_from_fast_jit);
+#endif
+
+ wasm_runtime_free(type);
+}
+
+static bool
+load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
+ InitializerExpression *init_expr, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint8 flag, end_byte, *p_float;
+ uint32 i;
+
+ CHECK_BUF(p, p_end, 1);
+ init_expr->init_expr_type = read_uint8(p);
+ flag = init_expr->init_expr_type;
+
+ switch (flag) {
+ /* i32.const */
+ case INIT_EXPR_TYPE_I32_CONST:
+ if (type != VALUE_TYPE_I32)
+ goto fail_type_mismatch;
+ read_leb_int32(p, p_end, init_expr->u.i32);
+ break;
+ /* i64.const */
+ case INIT_EXPR_TYPE_I64_CONST:
+ if (type != VALUE_TYPE_I64)
+ goto fail_type_mismatch;
+ read_leb_int64(p, p_end, init_expr->u.i64);
+ break;
+ /* f32.const */
+ case INIT_EXPR_TYPE_F32_CONST:
+ if (type != VALUE_TYPE_F32)
+ goto fail_type_mismatch;
+ CHECK_BUF(p, p_end, 4);
+ p_float = (uint8 *)&init_expr->u.f32;
+ for (i = 0; i < sizeof(float32); i++)
+ *p_float++ = *p++;
+ break;
+ /* f64.const */
+ case INIT_EXPR_TYPE_F64_CONST:
+ if (type != VALUE_TYPE_F64)
+ goto fail_type_mismatch;
+ CHECK_BUF(p, p_end, 8);
+ p_float = (uint8 *)&init_expr->u.f64;
+ for (i = 0; i < sizeof(float64); i++)
+ *p_float++ = *p++;
+ break;
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ case INIT_EXPR_TYPE_V128_CONST:
+ {
+ uint64 high, low;
+
+ if (type != VALUE_TYPE_V128)
+ goto fail_type_mismatch;
+
+ flag = read_uint8(p);
+ (void)flag;
+
+ CHECK_BUF(p, p_end, 16);
+ wasm_runtime_read_v128(p, &high, &low);
+ p += 16;
+
+ init_expr->u.v128.i64x2[0] = high;
+ init_expr->u.v128.i64x2[1] = low;
+ break;
+ }
+#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
+#endif /* end of WASM_ENABLE_SIMD */
+#if WASM_ENABLE_REF_TYPES != 0
+ case INIT_EXPR_TYPE_FUNCREF_CONST:
+ {
+ if (type != VALUE_TYPE_FUNCREF)
+ goto fail_type_mismatch;
+ read_leb_uint32(p, p_end, init_expr->u.ref_index);
+ break;
+ }
+ case INIT_EXPR_TYPE_REFNULL_CONST:
+ {
+ uint8 reftype;
+
+ CHECK_BUF(p, p_end, 1);
+ reftype = read_uint8(p);
+ if (reftype != type)
+ goto fail_type_mismatch;
+
+ init_expr->u.ref_index = NULL_REF;
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+ /* get_global */
+ case INIT_EXPR_TYPE_GET_GLOBAL:
+ read_leb_uint32(p, p_end, init_expr->u.global_index);
+ break;
+ default:
+ {
+ set_error_buf(error_buf, error_buf_size,
+ "illegal opcode "
+ "or constant expression required "
+ "or type mismatch");
+ goto fail;
+ }
+ }
+ CHECK_BUF(p, p_end, 1);
+ end_byte = read_uint8(p);
+ if (end_byte != 0x0b)
+ goto fail_type_mismatch;
+ *p_buf = p;
+ return true;
+
+fail_type_mismatch:
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch or constant expression required");
+fail:
+ return false;
+}
+
+static bool
+load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end, *p_org;
+ uint32 type_count, param_count, result_count, i, j;
+ uint32 param_cell_num, ret_cell_num;
+ uint64 total_size;
+ uint8 flag;
+ WASMType *type;
+
+ read_leb_uint32(p, p_end, type_count);
+
+ if (type_count) {
+ module->type_count = type_count;
+ total_size = sizeof(WASMType *) * (uint64)type_count;
+ if (!(module->types =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < type_count; i++) {
+ CHECK_BUF(p, p_end, 1);
+ flag = read_uint8(p);
+ if (flag != 0x60) {
+ set_error_buf(error_buf, error_buf_size, "invalid type flag");
+ return false;
+ }
+
+ read_leb_uint32(p, p_end, param_count);
+
+ /* Resolve param count and result count firstly */
+ p_org = p;
+ CHECK_BUF(p, p_end, param_count);
+ p += param_count;
+ read_leb_uint32(p, p_end, result_count);
+ CHECK_BUF(p, p_end, result_count);
+ p = p_org;
+
+ if (param_count > UINT16_MAX || result_count > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "param count or result count too large");
+ return false;
+ }
+
+ total_size = offsetof(WASMType, types)
+ + sizeof(uint8) * (uint64)(param_count + result_count);
+ if (!(type = module->types[i] =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Resolve param types and result types */
+ type->ref_count = 1;
+ type->param_count = (uint16)param_count;
+ type->result_count = (uint16)result_count;
+ for (j = 0; j < param_count; j++) {
+ CHECK_BUF(p, p_end, 1);
+ type->types[j] = read_uint8(p);
+ }
+ read_leb_uint32(p, p_end, result_count);
+ for (j = 0; j < result_count; j++) {
+ CHECK_BUF(p, p_end, 1);
+ type->types[param_count + j] = read_uint8(p);
+ }
+ for (j = 0; j < param_count + result_count; j++) {
+ if (!is_value_type(type->types[j])) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown value type");
+ return false;
+ }
+ }
+
+ param_cell_num = wasm_get_cell_num(type->types, param_count);
+ ret_cell_num =
+ wasm_get_cell_num(type->types + param_count, result_count);
+ if (param_cell_num > UINT16_MAX || ret_cell_num > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "param count or result count too large");
+ return false;
+ }
+ type->param_cell_num = (uint16)param_cell_num;
+ type->ret_cell_num = (uint16)ret_cell_num;
+
+ /* If there is already a same type created, use it instead */
+ for (j = 0; j < i; j++) {
+ if (wasm_type_equal(type, module->types[j])) {
+ if (module->types[j]->ref_count == UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "wasm type's ref count too large");
+ return false;
+ }
+ destroy_wasm_type(type);
+ module->types[i] = module->types[j];
+ module->types[j]->ref_count++;
+ break;
+ }
+ }
+ }
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load type section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static void
+adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size)
+{
+ uint32 default_max_size =
+ init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE;
+
+ if (max_size_flag) {
+ /* module defines the table limitation */
+ bh_assert(init_size <= *max_size);
+
+ if (init_size < *max_size) {
+ *max_size =
+ *max_size < default_max_size ? *max_size : default_max_size;
+ }
+ }
+ else {
+ /* partial defined table limitation, gives a default value */
+ *max_size = default_max_size;
+ }
+}
+
+#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0
+/**
+ * Find export item of a module with export info:
+ * module name, field name and export kind
+ */
+static WASMExport *
+wasm_loader_find_export(const WASMModule *module, const char *module_name,
+ const char *field_name, uint8 export_kind,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMExport *export;
+ uint32 i;
+
+ for (i = 0, export = module->exports; i < module->export_count;
+ ++i, ++export) {
+ /**
+ * need to consider a scenario that different kinds of exports
+ * may have the same name, like
+ * (table (export "m1" "exported") 10 funcref)
+ * (memory (export "m1" "exported") 10)
+ **/
+ if (export->kind == export_kind && !strcmp(field_name, export->name)) {
+ break;
+ }
+ }
+
+ if (i == module->export_count) {
+ LOG_DEBUG("can not find an export %d named %s in the module %s",
+ export_kind, field_name, module_name);
+ set_error_buf(error_buf, error_buf_size,
+ "unknown import or incompatible import type");
+ return NULL;
+ }
+
+ (void)module_name;
+
+ /* since there is a validation in load_export_section(), it is for sure
+ * export->index is valid*/
+ return export;
+}
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static WASMFunction *
+wasm_loader_resolve_function(const char *module_name, const char *function_name,
+ const WASMType *expected_function_type,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMModuleCommon *module_reg;
+ WASMFunction *function = NULL;
+ WASMExport *export = NULL;
+ WASMModule *module = NULL;
+ WASMType *target_function_type = NULL;
+
+ module_reg = wasm_runtime_find_module_registered(module_name);
+ if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
+ LOG_DEBUG("can not find a module named %s for function %s", module_name,
+ function_name);
+ set_error_buf(error_buf, error_buf_size, "unknown import");
+ return NULL;
+ }
+
+ module = (WASMModule *)module_reg;
+ export =
+ wasm_loader_find_export(module, module_name, function_name,
+ EXPORT_KIND_FUNC, error_buf, error_buf_size);
+ if (!export) {
+ return NULL;
+ }
+
+ /* resolve function type and function */
+ if (export->index < module->import_function_count) {
+ target_function_type =
+ module->import_functions[export->index].u.function.func_type;
+ function = module->import_functions[export->index]
+ .u.function.import_func_linked;
+ }
+ else {
+ target_function_type =
+ module->functions[export->index - module->import_function_count]
+ ->func_type;
+ function =
+ module->functions[export->index - module->import_function_count];
+ }
+
+ /* check function type */
+ if (!wasm_type_equal(expected_function_type, target_function_type)) {
+ LOG_DEBUG("%s.%s failed the type check", module_name, function_name);
+ set_error_buf(error_buf, error_buf_size, "incompatible import type");
+ return NULL;
+ }
+
+ return function;
+}
+
+static WASMTable *
+wasm_loader_resolve_table(const char *module_name, const char *table_name,
+ uint32 init_size, uint32 max_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModuleCommon *module_reg;
+ WASMTable *table = NULL;
+ WASMExport *export = NULL;
+ WASMModule *module = NULL;
+
+ module_reg = wasm_runtime_find_module_registered(module_name);
+ if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
+ LOG_DEBUG("can not find a module named %s for table", module_name);
+ set_error_buf(error_buf, error_buf_size, "unknown import");
+ return NULL;
+ }
+
+ module = (WASMModule *)module_reg;
+ export =
+ wasm_loader_find_export(module, module_name, table_name,
+ EXPORT_KIND_TABLE, error_buf, error_buf_size);
+ if (!export) {
+ return NULL;
+ }
+
+ /* resolve table and check the init/max size */
+ if (export->index < module->import_table_count) {
+ table =
+ module->import_tables[export->index].u.table.import_table_linked;
+ }
+ else {
+ table = &(module->tables[export->index - module->import_table_count]);
+ }
+ if (table->init_size < init_size || table->max_size > max_size) {
+ LOG_DEBUG("%s,%s failed type check(%d-%d), expected(%d-%d)",
+ module_name, table_name, table->init_size, table->max_size,
+ init_size, max_size);
+ set_error_buf(error_buf, error_buf_size, "incompatible import type");
+ return NULL;
+ }
+
+ return table;
+}
+
+static WASMMemory *
+wasm_loader_resolve_memory(const char *module_name, const char *memory_name,
+ uint32 init_page_count, uint32 max_page_count,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMModuleCommon *module_reg;
+ WASMMemory *memory = NULL;
+ WASMExport *export = NULL;
+ WASMModule *module = NULL;
+
+ module_reg = wasm_runtime_find_module_registered(module_name);
+ if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
+ LOG_DEBUG("can not find a module named %s for memory", module_name);
+ set_error_buf(error_buf, error_buf_size, "unknown import");
+ return NULL;
+ }
+
+ module = (WASMModule *)module_reg;
+ export =
+ wasm_loader_find_export(module, module_name, memory_name,
+ EXPORT_KIND_MEMORY, error_buf, error_buf_size);
+ if (!export) {
+ return NULL;
+ }
+
+ /* resolve memory and check the init/max page count */
+ if (export->index < module->import_memory_count) {
+ memory = module->import_memories[export->index]
+ .u.memory.import_memory_linked;
+ }
+ else {
+ memory =
+ &(module->memories[export->index - module->import_memory_count]);
+ }
+ if (memory->init_page_count < init_page_count
+ || memory->max_page_count > max_page_count) {
+ LOG_DEBUG("%s,%s failed type check(%d-%d), expected(%d-%d)",
+ module_name, memory_name, memory->init_page_count,
+ memory->max_page_count, init_page_count, max_page_count);
+ set_error_buf(error_buf, error_buf_size, "incompatible import type");
+ return NULL;
+ }
+ return memory;
+}
+
+static WASMGlobal *
+wasm_loader_resolve_global(const char *module_name, const char *global_name,
+ uint8 type, bool is_mutable, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModuleCommon *module_reg;
+ WASMGlobal *global = NULL;
+ WASMExport *export = NULL;
+ WASMModule *module = NULL;
+
+ module_reg = wasm_runtime_find_module_registered(module_name);
+ if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
+ LOG_DEBUG("can not find a module named %s for global", module_name);
+ set_error_buf(error_buf, error_buf_size, "unknown import");
+ return NULL;
+ }
+
+ module = (WASMModule *)module_reg;
+ export =
+ wasm_loader_find_export(module, module_name, global_name,
+ EXPORT_KIND_GLOBAL, error_buf, error_buf_size);
+ if (!export) {
+ return NULL;
+ }
+
+ /* resolve and check the global */
+ if (export->index < module->import_global_count) {
+ global =
+ module->import_globals[export->index].u.global.import_global_linked;
+ }
+ else {
+ global =
+ &(module->globals[export->index - module->import_global_count]);
+ }
+ if (global->type != type || global->is_mutable != is_mutable) {
+ LOG_DEBUG("%s,%s failed type check(%d, %d), expected(%d, %d)",
+ module_name, global_name, global->type, global->is_mutable,
+ type, is_mutable);
+ set_error_buf(error_buf, error_buf_size, "incompatible import type");
+ return NULL;
+ }
+ return global;
+}
+
+static WASMModule *
+search_sub_module(const WASMModule *parent_module, const char *sub_module_name)
+{
+ WASMRegisteredModule *node =
+ bh_list_first_elem(parent_module->import_module_list);
+ while (node && strcmp(sub_module_name, node->module_name)) {
+ node = bh_list_elem_next(node);
+ }
+ return node ? (WASMModule *)node->module : NULL;
+}
+
+static bool
+register_sub_module(const WASMModule *parent_module,
+ const char *sub_module_name, WASMModule *sub_module)
+{
+ /* register sub_module into its parent sub module list */
+ WASMRegisteredModule *node = NULL;
+ bh_list_status ret;
+
+ if (search_sub_module(parent_module, sub_module_name)) {
+ LOG_DEBUG("%s has been registered in its parent", sub_module_name);
+ return true;
+ }
+
+ node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0);
+ if (!node) {
+ return false;
+ }
+
+ node->module_name = sub_module_name;
+ node->module = (WASMModuleCommon *)sub_module;
+ ret = bh_list_insert(parent_module->import_module_list, node);
+ bh_assert(BH_LIST_SUCCESS == ret);
+ (void)ret;
+ return true;
+}
+
+static WASMModule *
+load_depended_module(const WASMModule *parent_module,
+ const char *sub_module_name, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModule *sub_module = NULL;
+ bool ret = false;
+ uint8 *buffer = NULL;
+ uint32 buffer_size = 0;
+ const module_reader reader = wasm_runtime_get_module_reader();
+ const module_destroyer destroyer = wasm_runtime_get_module_destroyer();
+
+ /* check the registered module list of the parent */
+ sub_module = search_sub_module(parent_module, sub_module_name);
+ if (sub_module) {
+ LOG_DEBUG("%s has been loaded before", sub_module_name);
+ return sub_module;
+ }
+
+ /* check the global registered module list */
+ sub_module =
+ (WASMModule *)wasm_runtime_find_module_registered(sub_module_name);
+ if (sub_module) {
+ LOG_DEBUG("%s has been loaded", sub_module_name);
+ goto register_sub_module;
+ }
+
+ LOG_VERBOSE("loading %s", sub_module_name);
+
+ if (!reader) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "no sub module reader to load %s", sub_module_name);
+ return NULL;
+ }
+
+ /* start to maintain a loading module list */
+ ret = wasm_runtime_is_loading_module(sub_module_name);
+ if (ret) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "found circular dependency on %s", sub_module_name);
+ return NULL;
+ }
+
+ ret = wasm_runtime_add_loading_module(sub_module_name, error_buf,
+ error_buf_size);
+ if (!ret) {
+ LOG_DEBUG("can not add %s into loading module list\n", sub_module_name);
+ return NULL;
+ }
+
+ ret = reader(sub_module_name, &buffer, &buffer_size);
+ if (!ret) {
+ LOG_DEBUG("read the file of %s failed", sub_module_name);
+ set_error_buf_v(error_buf, error_buf_size, "unknown import",
+ sub_module_name);
+ goto delete_loading_module;
+ }
+
+ sub_module =
+ wasm_loader_load(buffer, buffer_size, false, error_buf, error_buf_size);
+ if (!sub_module) {
+ LOG_DEBUG("error: can not load the sub_module %s", sub_module_name);
+ /* others will be destroyed in runtime_destroy() */
+ goto destroy_file_buffer;
+ }
+
+ wasm_runtime_delete_loading_module(sub_module_name);
+
+ /* register on a global list */
+ ret = wasm_runtime_register_module_internal(
+ sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size,
+ error_buf, error_buf_size);
+ if (!ret) {
+ LOG_DEBUG("error: can not register module %s globally\n",
+ sub_module_name);
+ /* others will be unloaded in runtime_destroy() */
+ goto unload_module;
+ }
+
+ /* register into its parent list */
+register_sub_module:
+ ret = register_sub_module(parent_module, sub_module_name, sub_module);
+ if (!ret) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "failed to register sub module %s", sub_module_name);
+ /* since it is in the global module list, no need to
+ * unload the module. the runtime_destroy() will do it
+ */
+ return NULL;
+ }
+
+ return sub_module;
+
+unload_module:
+ wasm_loader_unload(sub_module);
+
+destroy_file_buffer:
+ if (destroyer) {
+ destroyer(buffer, buffer_size);
+ }
+ else {
+ LOG_WARNING("need to release the reading buffer of %s manually",
+ sub_module_name);
+ }
+
+delete_loading_module:
+ wasm_runtime_delete_loading_module(sub_module_name);
+ return NULL;
+}
+#endif /* end of WASM_ENABLE_MULTI_MODULE */
+
+static bool
+load_function_import(const uint8 **p_buf, const uint8 *buf_end,
+ const WASMModule *parent_module,
+ const char *sub_module_name, const char *function_name,
+ WASMFunctionImport *function, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 declare_type_index = 0;
+ WASMType *declare_func_type = NULL;
+ WASMFunction *linked_func = NULL;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *sub_module = NULL;
+#endif
+ const char *linked_signature = NULL;
+ void *linked_attachment = NULL;
+ bool linked_call_conv_raw = false;
+ bool is_native_symbol = false;
+
+ read_leb_uint32(p, p_end, declare_type_index);
+ *p_buf = p;
+
+ if (declare_type_index >= parent_module->type_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown type");
+ return false;
+ }
+
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ declare_type_index = wasm_get_smallest_type_idx(
+ parent_module->types, parent_module->type_count, declare_type_index);
+#endif
+
+ declare_func_type = parent_module->types[declare_type_index];
+
+ /* lookup registered native symbols first */
+ linked_func = wasm_native_resolve_symbol(
+ sub_module_name, function_name, declare_func_type, &linked_signature,
+ &linked_attachment, &linked_call_conv_raw);
+ if (linked_func) {
+ is_native_symbol = true;
+ }
+#if WASM_ENABLE_MULTI_MODULE != 0
+ else {
+ if (!wasm_runtime_is_built_in_module(sub_module_name)) {
+ sub_module = load_depended_module(parent_module, sub_module_name,
+ error_buf, error_buf_size);
+ if (!sub_module) {
+ return false;
+ }
+ }
+ linked_func = wasm_loader_resolve_function(
+ sub_module_name, function_name, declare_func_type, error_buf,
+ error_buf_size);
+ }
+#endif
+
+ function->module_name = (char *)sub_module_name;
+ function->field_name = (char *)function_name;
+ function->func_type = declare_func_type;
+ /* func_ptr_linked is for native registered symbol */
+ function->func_ptr_linked = is_native_symbol ? linked_func : NULL;
+ function->signature = linked_signature;
+ function->attachment = linked_attachment;
+ function->call_conv_raw = linked_call_conv_raw;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ function->import_module = is_native_symbol ? NULL : sub_module;
+ function->import_func_linked = is_native_symbol ? NULL : linked_func;
+#endif
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_table_max_size(uint32 init_size, uint32 max_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (max_size < init_size) {
+ set_error_buf(error_buf, error_buf_size,
+ "size minimum must not be greater than maximum");
+ return false;
+ }
+ return true;
+}
+
+static bool
+load_table_import(const uint8 **p_buf, const uint8 *buf_end,
+ WASMModule *parent_module, const char *sub_module_name,
+ const char *table_name, WASMTableImport *table,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 declare_elem_type = 0, declare_max_size_flag = 0,
+ declare_init_size = 0, declare_max_size = 0;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *sub_module = NULL;
+ WASMTable *linked_table = NULL;
+#endif
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x70 or 0x6F */
+ declare_elem_type = read_uint8(p);
+ if (VALUE_TYPE_FUNCREF != declare_elem_type
+#if WASM_ENABLE_REF_TYPES != 0
+ && VALUE_TYPE_EXTERNREF != declare_elem_type
+#endif
+ ) {
+ set_error_buf(error_buf, error_buf_size, "incompatible import type");
+ return false;
+ }
+
+ read_leb_uint32(p, p_end, declare_max_size_flag);
+ if (declare_max_size_flag > 1) {
+ set_error_buf(error_buf, error_buf_size, "integer too large");
+ return false;
+ }
+
+ read_leb_uint32(p, p_end, declare_init_size);
+
+ if (declare_max_size_flag) {
+ read_leb_uint32(p, p_end, declare_max_size);
+ if (!check_table_max_size(declare_init_size, declare_max_size,
+ error_buf, error_buf_size))
+ return false;
+ }
+
+ adjust_table_max_size(declare_init_size, declare_max_size_flag,
+ &declare_max_size);
+
+ *p_buf = p;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (!wasm_runtime_is_built_in_module(sub_module_name)) {
+ sub_module = load_depended_module(parent_module, sub_module_name,
+ error_buf, error_buf_size);
+ if (!sub_module) {
+ return false;
+ }
+
+ linked_table = wasm_loader_resolve_table(
+ sub_module_name, table_name, declare_init_size, declare_max_size,
+ error_buf, error_buf_size);
+ if (!linked_table) {
+ return false;
+ }
+
+ /* reset with linked table limit */
+ declare_elem_type = linked_table->elem_type;
+ declare_init_size = linked_table->init_size;
+ declare_max_size = linked_table->max_size;
+ declare_max_size_flag = linked_table->flags;
+ table->import_table_linked = linked_table;
+ table->import_module = sub_module;
+ }
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
+
+ /* (table (export "table") 10 20 funcref) */
+ /* we need this section working in wamrc */
+ if (!strcmp("spectest", sub_module_name)) {
+ const uint32 spectest_table_init_size = 10;
+ const uint32 spectest_table_max_size = 20;
+
+ if (strcmp("table", table_name)) {
+ set_error_buf(error_buf, error_buf_size,
+ "incompatible import type or unknown import");
+ return false;
+ }
+
+ if (declare_init_size > spectest_table_init_size
+ || declare_max_size < spectest_table_max_size) {
+ set_error_buf(error_buf, error_buf_size,
+ "incompatible import type");
+ return false;
+ }
+
+ declare_init_size = spectest_table_init_size;
+ declare_max_size = spectest_table_max_size;
+ }
+
+ /* now we believe all declaration are ok */
+ table->elem_type = declare_elem_type;
+ table->init_size = declare_init_size;
+ table->flags = declare_max_size_flag;
+ table->max_size = declare_max_size;
+
+ (void)parent_module;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_memory_init_size(uint32 init_size, char *error_buf, uint32 error_buf_size)
+{
+ if (init_size > DEFAULT_MAX_PAGES) {
+ set_error_buf(error_buf, error_buf_size,
+ "memory size must be at most 65536 pages (4GiB)");
+ return false;
+ }
+ return true;
+}
+
+static bool
+check_memory_max_size(uint32 init_size, uint32 max_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (max_size < init_size) {
+ set_error_buf(error_buf, error_buf_size,
+ "size minimum must not be greater than maximum");
+ return false;
+ }
+
+ if (max_size > DEFAULT_MAX_PAGES) {
+ set_error_buf(error_buf, error_buf_size,
+ "memory size must be at most 65536 pages (4GiB)");
+ return false;
+ }
+ return true;
+}
+
+static bool
+load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
+ WASMModule *parent_module, const char *sub_module_name,
+ const char *memory_name, WASMMemoryImport *memory,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+#if WASM_ENABLE_APP_FRAMEWORK != 0
+ uint32 pool_size = wasm_runtime_memory_pool_size();
+ uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
+ / DEFAULT_NUM_BYTES_PER_PAGE;
+#else
+ uint32 max_page_count = DEFAULT_MAX_PAGES;
+#endif /* WASM_ENABLE_APP_FRAMEWORK */
+ uint32 declare_max_page_count_flag = 0;
+ uint32 declare_init_page_count = 0;
+ uint32 declare_max_page_count = 0;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *sub_module = NULL;
+ WASMMemory *linked_memory = NULL;
+#endif
+
+ read_leb_uint32(p, p_end, declare_max_page_count_flag);
+ read_leb_uint32(p, p_end, declare_init_page_count);
+ if (!check_memory_init_size(declare_init_page_count, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+
+ if (declare_max_page_count_flag & 1) {
+ read_leb_uint32(p, p_end, declare_max_page_count);
+ if (!check_memory_max_size(declare_init_page_count,
+ declare_max_page_count, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+ if (declare_max_page_count > max_page_count) {
+ declare_max_page_count = max_page_count;
+ }
+ }
+ else {
+ /* Limit the maximum memory size to max_page_count */
+ declare_max_page_count = max_page_count;
+ }
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (!wasm_runtime_is_built_in_module(sub_module_name)) {
+ sub_module = load_depended_module(parent_module, sub_module_name,
+ error_buf, error_buf_size);
+ if (!sub_module) {
+ return false;
+ }
+
+ linked_memory = wasm_loader_resolve_memory(
+ sub_module_name, memory_name, declare_init_page_count,
+ declare_max_page_count, error_buf, error_buf_size);
+ if (!linked_memory) {
+ return false;
+ }
+
+ /**
+ * reset with linked memory limit
+ */
+ memory->import_module = sub_module;
+ memory->import_memory_linked = linked_memory;
+ declare_init_page_count = linked_memory->init_page_count;
+ declare_max_page_count = linked_memory->max_page_count;
+ }
+#endif
+
+ /* (memory (export "memory") 1 2) */
+ if (!strcmp("spectest", sub_module_name)) {
+ uint32 spectest_memory_init_page = 1;
+ uint32 spectest_memory_max_page = 2;
+
+ if (strcmp("memory", memory_name)) {
+ set_error_buf(error_buf, error_buf_size,
+ "incompatible import type or unknown import");
+ return false;
+ }
+
+ if (declare_init_page_count > spectest_memory_init_page
+ || declare_max_page_count < spectest_memory_max_page) {
+ set_error_buf(error_buf, error_buf_size,
+ "incompatible import type");
+ return false;
+ }
+
+ declare_init_page_count = spectest_memory_init_page;
+ declare_max_page_count = spectest_memory_max_page;
+ }
+
+ /* now we believe all declaration are ok */
+ memory->flags = declare_max_page_count_flag;
+ memory->init_page_count = declare_init_page_count;
+ memory->max_page_count = declare_max_page_count;
+ memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+
+ *p_buf = p;
+
+ (void)parent_module;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_global_import(const uint8 **p_buf, const uint8 *buf_end,
+ const WASMModule *parent_module, char *sub_module_name,
+ char *global_name, WASMGlobalImport *global, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint8 declare_type = 0;
+ uint8 declare_mutable = 0;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *sub_module = NULL;
+ WASMGlobal *linked_global = NULL;
+#endif
+ bool ret = false;
+
+ CHECK_BUF(p, p_end, 2);
+ declare_type = read_uint8(p);
+ declare_mutable = read_uint8(p);
+ *p_buf = p;
+
+ if (declare_mutable >= 2) {
+ set_error_buf(error_buf, error_buf_size, "invalid mutability");
+ return false;
+ }
+
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+ ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
+ global);
+ if (ret) {
+ if (global->type != declare_type
+ || global->is_mutable != declare_mutable) {
+ set_error_buf(error_buf, error_buf_size,
+ "incompatible import type");
+ return false;
+ }
+ global->is_linked = true;
+ }
+#endif
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (!global->is_linked
+ && !wasm_runtime_is_built_in_module(sub_module_name)) {
+ sub_module = load_depended_module(parent_module, sub_module_name,
+ error_buf, error_buf_size);
+ if (!sub_module) {
+ return false;
+ }
+
+ /* check sub modules */
+ linked_global = wasm_loader_resolve_global(
+ sub_module_name, global_name, declare_type, declare_mutable,
+ error_buf, error_buf_size);
+ if (linked_global) {
+ global->import_module = sub_module;
+ global->import_global_linked = linked_global;
+ global->is_linked = true;
+ }
+ }
+#endif
+
+ global->module_name = sub_module_name;
+ global->field_name = global_name;
+ global->type = declare_type;
+ global->is_mutable = (declare_mutable == 1);
+
+ (void)parent_module;
+ (void)ret;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x70 or 0x6F */
+ table->elem_type = read_uint8(p);
+ if (VALUE_TYPE_FUNCREF != table->elem_type
+#if WASM_ENABLE_REF_TYPES != 0
+ && VALUE_TYPE_EXTERNREF != table->elem_type
+#endif
+ ) {
+ set_error_buf(error_buf, error_buf_size, "incompatible import type");
+ return false;
+ }
+
+ p_org = p;
+ read_leb_uint32(p, p_end, table->flags);
+#if WASM_ENABLE_SHARED_MEMORY == 0
+ if (p - p_org > 1) {
+ set_error_buf(error_buf, error_buf_size,
+ "integer representation too long");
+ return false;
+ }
+ if (table->flags > 1) {
+ set_error_buf(error_buf, error_buf_size, "integer too large");
+ return false;
+ }
+#else
+ if (p - p_org > 1) {
+ set_error_buf(error_buf, error_buf_size, "invalid limits flags");
+ return false;
+ }
+ if (table->flags == 2) {
+ set_error_buf(error_buf, error_buf_size, "tables cannot be shared");
+ return false;
+ }
+ if (table->flags > 1) {
+ set_error_buf(error_buf, error_buf_size, "invalid limits flags");
+ return false;
+ }
+#endif
+
+ read_leb_uint32(p, p_end, table->init_size);
+
+ if (table->flags) {
+ read_leb_uint32(p, p_end, table->max_size);
+ if (!check_table_max_size(table->init_size, table->max_size, error_buf,
+ error_buf_size))
+ return false;
+ }
+
+ adjust_table_max_size(table->init_size, table->flags, &table->max_size);
+
+ *p_buf = p;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
+#if WASM_ENABLE_APP_FRAMEWORK != 0
+ uint32 pool_size = wasm_runtime_memory_pool_size();
+ uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
+ / DEFAULT_NUM_BYTES_PER_PAGE;
+#else
+ uint32 max_page_count = DEFAULT_MAX_PAGES;
+#endif
+
+ p_org = p;
+ read_leb_uint32(p, p_end, memory->flags);
+#if WASM_ENABLE_SHARED_MEMORY == 0
+ if (p - p_org > 1) {
+ set_error_buf(error_buf, error_buf_size,
+ "integer representation too long");
+ return false;
+ }
+ if (memory->flags > 1) {
+ set_error_buf(error_buf, error_buf_size, "integer too large");
+ return false;
+ }
+#else
+ if (p - p_org > 1) {
+ set_error_buf(error_buf, error_buf_size, "invalid limits flags");
+ return false;
+ }
+ if (memory->flags > 3) {
+ set_error_buf(error_buf, error_buf_size, "invalid limits flags");
+ return false;
+ }
+ else if (memory->flags == 2) {
+ set_error_buf(error_buf, error_buf_size,
+ "shared memory must have maximum");
+ return false;
+ }
+#endif
+
+ read_leb_uint32(p, p_end, memory->init_page_count);
+ if (!check_memory_init_size(memory->init_page_count, error_buf,
+ error_buf_size))
+ return false;
+
+ if (memory->flags & 1) {
+ read_leb_uint32(p, p_end, memory->max_page_count);
+ if (!check_memory_max_size(memory->init_page_count,
+ memory->max_page_count, error_buf,
+ error_buf_size))
+ return false;
+ if (memory->max_page_count > max_page_count)
+ memory->max_page_count = max_page_count;
+ }
+ else {
+ /* Limit the maximum memory size to max_page_count */
+ memory->max_page_count = max_page_count;
+ }
+
+ memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+
+ *p_buf = p;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end, *p_old;
+ uint32 import_count, name_len, type_index, i, u32, flags;
+ uint64 total_size;
+ WASMImport *import;
+ WASMImport *import_functions = NULL, *import_tables = NULL;
+ WASMImport *import_memories = NULL, *import_globals = NULL;
+ char *sub_module_name, *field_name;
+ uint8 u8, kind;
+
+ read_leb_uint32(p, p_end, import_count);
+
+ if (import_count) {
+ module->import_count = import_count;
+ total_size = sizeof(WASMImport) * (uint64)import_count;
+ if (!(module->imports =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ p_old = p;
+
+ /* Scan firstly to get import count of each type */
+ for (i = 0; i < import_count; i++) {
+ /* module name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ p += name_len;
+
+ /* field name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ p += name_len;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x00/0x01/0x02/0x03 */
+ kind = read_uint8(p);
+
+ switch (kind) {
+ case IMPORT_KIND_FUNC: /* import function */
+ read_leb_uint32(p, p_end, type_index);
+ module->import_function_count++;
+ break;
+
+ case IMPORT_KIND_TABLE: /* import table */
+ CHECK_BUF(p, p_end, 1);
+ /* 0x70 */
+ u8 = read_uint8(p);
+ read_leb_uint32(p, p_end, flags);
+ read_leb_uint32(p, p_end, u32);
+ if (flags & 1)
+ read_leb_uint32(p, p_end, u32);
+ module->import_table_count++;
+
+#if WASM_ENABLE_REF_TYPES == 0
+ if (module->import_table_count > 1) {
+ set_error_buf(error_buf, error_buf_size,
+ "multiple tables");
+ return false;
+ }
+#endif
+ break;
+
+ case IMPORT_KIND_MEMORY: /* import memory */
+ read_leb_uint32(p, p_end, flags);
+ read_leb_uint32(p, p_end, u32);
+ if (flags & 1)
+ read_leb_uint32(p, p_end, u32);
+ module->import_memory_count++;
+ if (module->import_memory_count > 1) {
+ set_error_buf(error_buf, error_buf_size,
+ "multiple memories");
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_GLOBAL: /* import global */
+ CHECK_BUF(p, p_end, 2);
+ p += 2;
+ module->import_global_count++;
+ break;
+
+ default:
+ set_error_buf(error_buf, error_buf_size,
+ "invalid import kind");
+ return false;
+ }
+ }
+
+ if (module->import_function_count)
+ import_functions = module->import_functions = module->imports;
+ if (module->import_table_count)
+ import_tables = module->import_tables =
+ module->imports + module->import_function_count;
+ if (module->import_memory_count)
+ import_memories = module->import_memories =
+ module->imports + module->import_function_count
+ + module->import_table_count;
+ if (module->import_global_count)
+ import_globals = module->import_globals =
+ module->imports + module->import_function_count
+ + module->import_table_count + module->import_memory_count;
+
+ p = p_old;
+
+ /* Scan again to resolve the data */
+ for (i = 0; i < import_count; i++) {
+ /* load module name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ if (!(sub_module_name = const_str_list_insert(
+ p, name_len, module, is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ p += name_len;
+
+ /* load field name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ if (!(field_name = const_str_list_insert(
+ p, name_len, module, is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ p += name_len;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x00/0x01/0x02/0x03 */
+ kind = read_uint8(p);
+
+ switch (kind) {
+ case IMPORT_KIND_FUNC: /* import function */
+ bh_assert(import_functions);
+ import = import_functions++;
+ if (!load_function_import(
+ &p, p_end, module, sub_module_name, field_name,
+ &import->u.function, error_buf, error_buf_size)) {
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_TABLE: /* import table */
+ bh_assert(import_tables);
+ import = import_tables++;
+ if (!load_table_import(&p, p_end, module, sub_module_name,
+ field_name, &import->u.table,
+ error_buf, error_buf_size)) {
+ LOG_DEBUG("can not import such a table (%s,%s)",
+ sub_module_name, field_name);
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_MEMORY: /* import memory */
+ bh_assert(import_memories);
+ import = import_memories++;
+ if (!load_memory_import(&p, p_end, module, sub_module_name,
+ field_name, &import->u.memory,
+ error_buf, error_buf_size)) {
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_GLOBAL: /* import global */
+ bh_assert(import_globals);
+ import = import_globals++;
+ if (!load_global_import(&p, p_end, module, sub_module_name,
+ field_name, &import->u.global,
+ error_buf, error_buf_size)) {
+ return false;
+ }
+ break;
+
+ default:
+ set_error_buf(error_buf, error_buf_size,
+ "invalid import kind");
+ return false;
+ }
+ import->kind = kind;
+ import->u.names.module_name = sub_module_name;
+ import->u.names.field_name = field_name;
+ }
+
+#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")
+ || !strcmp(import->u.names.module_name,
+ "wasi_snapshot_preview1")) {
+ module->import_wasi_api = true;
+ break;
+ }
+ }
+#endif
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load import section success.\n");
+ (void)u8;
+ (void)u32;
+ (void)type_index;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+init_function_local_offsets(WASMFunction *func, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMType *param_type = func->func_type;
+ uint32 param_count = param_type->param_count;
+ uint8 *param_types = param_type->types;
+ uint32 local_count = func->local_count;
+ uint8 *local_types = func->local_types;
+ uint32 i, local_offset = 0;
+ uint64 total_size = sizeof(uint16) * ((uint64)param_count + local_count);
+
+ /*
+ * Only allocate memory when total_size is not 0,
+ * or the return value of malloc(0) might be NULL on some platforms,
+ * which causes wasm loader return false.
+ */
+ if (total_size > 0
+ && !(func->local_offsets =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < param_count; i++) {
+ func->local_offsets[i] = (uint16)local_offset;
+ local_offset += wasm_value_type_cell_num(param_types[i]);
+ }
+
+ for (i = 0; i < local_count; i++) {
+ func->local_offsets[param_count + i] = (uint16)local_offset;
+ local_offset += wasm_value_type_cell_num(local_types[i]);
+ }
+
+ bh_assert(local_offset == func->param_cell_num + func->local_cell_num);
+ return true;
+}
+
+static bool
+load_function_section(const uint8 *buf, const uint8 *buf_end,
+ const uint8 *buf_code, const uint8 *buf_code_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ const uint8 *p_code = buf_code, *p_code_end, *p_code_save;
+ uint32 func_count;
+ uint64 total_size;
+ uint32 code_count = 0, code_size, type_index, i, j, k, local_type_index;
+ uint32 local_count, local_set_count, sub_local_count, local_cell_num;
+ uint8 type;
+ WASMFunction *func;
+
+ read_leb_uint32(p, p_end, func_count);
+
+ if (buf_code)
+ read_leb_uint32(p_code, buf_code_end, code_count);
+
+ if (func_count != code_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "function and code section have inconsistent lengths or "
+ "unexpected end");
+ return false;
+ }
+
+ if (func_count) {
+ module->function_count = func_count;
+ total_size = sizeof(WASMFunction *) * (uint64)func_count;
+ if (!(module->functions =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < func_count; i++) {
+ /* Resolve function type */
+ read_leb_uint32(p, p_end, type_index);
+ if (type_index >= module->type_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown type");
+ return false;
+ }
+
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ type_index = wasm_get_smallest_type_idx(
+ module->types, module->type_count, type_index);
+#endif
+
+ read_leb_uint32(p_code, buf_code_end, code_size);
+ if (code_size == 0 || p_code + code_size > buf_code_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid function code size");
+ return false;
+ }
+
+ /* Resolve local set count */
+ p_code_end = p_code + code_size;
+ local_count = 0;
+ read_leb_uint32(p_code, buf_code_end, local_set_count);
+ p_code_save = p_code;
+
+ /* Calculate total local count */
+ for (j = 0; j < local_set_count; j++) {
+ read_leb_uint32(p_code, buf_code_end, sub_local_count);
+ if (sub_local_count > UINT32_MAX - local_count) {
+ set_error_buf(error_buf, error_buf_size, "too many locals");
+ return false;
+ }
+ CHECK_BUF(p_code, buf_code_end, 1);
+ /* 0x7F/0x7E/0x7D/0x7C */
+ type = read_uint8(p_code);
+ local_count += sub_local_count;
+ }
+
+ /* Alloc memory, layout: function structure + local types */
+ code_size = (uint32)(p_code_end - p_code);
+
+ total_size = sizeof(WASMFunction) + (uint64)local_count;
+ if (!(func = module->functions[i] =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Set function type, local count, code size and code body */
+ func->func_type = module->types[type_index];
+ func->local_count = local_count;
+ if (local_count > 0)
+ func->local_types = (uint8 *)func + sizeof(WASMFunction);
+ func->code_size = code_size;
+ /*
+ * we shall make a copy of code body [p_code, p_code + code_size]
+ * when we are worrying about inappropriate releasing behaviour.
+ * all code bodies are actually in a buffer which user allocates in
+ * his embedding environment and we don't have power on them.
+ * it will be like:
+ * code_body_cp = malloc(code_size);
+ * memcpy(code_body_cp, p_code, code_size);
+ * func->code = code_body_cp;
+ */
+ func->code = (uint8 *)p_code;
+
+ /* Load each local type */
+ p_code = p_code_save;
+ local_type_index = 0;
+ for (j = 0; j < local_set_count; j++) {
+ read_leb_uint32(p_code, buf_code_end, sub_local_count);
+ /* Note: sub_local_count is allowed to be 0 */
+ if (local_type_index > UINT32_MAX - sub_local_count
+ || local_type_index + sub_local_count > local_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid local count");
+ return false;
+ }
+ CHECK_BUF(p_code, buf_code_end, 1);
+ /* 0x7F/0x7E/0x7D/0x7C */
+ type = read_uint8(p_code);
+ if (!is_value_type(type)) {
+ if (type == VALUE_TYPE_V128)
+ set_error_buf(error_buf, error_buf_size,
+ "v128 value type requires simd feature");
+ else if (type == VALUE_TYPE_FUNCREF
+ || type == VALUE_TYPE_EXTERNREF)
+ set_error_buf(error_buf, error_buf_size,
+ "ref value type requires "
+ "reference types feature");
+ else
+ set_error_buf_v(error_buf, error_buf_size,
+ "invalid local type 0x%02X", type);
+ return false;
+ }
+ for (k = 0; k < sub_local_count; k++) {
+ func->local_types[local_type_index++] = type;
+ }
+ }
+
+ func->param_cell_num = func->func_type->param_cell_num;
+ func->ret_cell_num = func->func_type->ret_cell_num;
+ local_cell_num =
+ wasm_get_cell_num(func->local_types, func->local_count);
+
+ if (local_cell_num > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "local count too large");
+ return false;
+ }
+
+ func->local_cell_num = (uint16)local_cell_num;
+
+ if (!init_function_local_offsets(func, error_buf, error_buf_size))
+ return false;
+
+ p_code = p_code_end;
+ }
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load function section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_function_index(const WASMModule *module, uint32 function_index,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (function_index
+ >= module->import_function_count + module->function_count) {
+ set_error_buf_v(error_buf, error_buf_size, "unknown function %d",
+ function_index);
+ return false;
+ }
+ return true;
+}
+
+static bool
+load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 table_count, i;
+ uint64 total_size;
+ WASMTable *table;
+
+ read_leb_uint32(p, p_end, table_count);
+#if WASM_ENABLE_REF_TYPES == 0
+ if (module->import_table_count + table_count > 1) {
+ /* a total of one table is allowed */
+ set_error_buf(error_buf, error_buf_size, "multiple tables");
+ return false;
+ }
+#endif
+
+ if (table_count) {
+ module->table_count = table_count;
+ total_size = sizeof(WASMTable) * (uint64)table_count;
+ if (!(module->tables =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* load each table */
+ table = module->tables;
+ for (i = 0; i < table_count; i++, table++)
+ if (!load_table(&p, p_end, table, error_buf, error_buf_size))
+ return false;
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load table section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 memory_count, i;
+ uint64 total_size;
+ WASMMemory *memory;
+
+ read_leb_uint32(p, p_end, memory_count);
+ /* a total of one memory is allowed */
+ if (module->import_memory_count + memory_count > 1) {
+ set_error_buf(error_buf, error_buf_size, "multiple memories");
+ return false;
+ }
+
+ if (memory_count) {
+ module->memory_count = memory_count;
+ total_size = sizeof(WASMMemory) * (uint64)memory_count;
+ if (!(module->memories =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* load each memory */
+ memory = module->memories;
+ for (i = 0; i < memory_count; i++, memory++)
+ if (!load_memory(&p, p_end, memory, error_buf, error_buf_size))
+ return false;
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load memory section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 global_count, i;
+ uint64 total_size;
+ WASMGlobal *global;
+ uint8 mutable;
+
+ read_leb_uint32(p, p_end, global_count);
+
+ if (global_count) {
+ module->global_count = global_count;
+ total_size = sizeof(WASMGlobal) * (uint64)global_count;
+ if (!(module->globals =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ global = module->globals;
+
+ for (i = 0; i < global_count; i++, global++) {
+ CHECK_BUF(p, p_end, 2);
+ global->type = read_uint8(p);
+ mutable = read_uint8(p);
+ if (mutable >= 2) {
+ set_error_buf(error_buf, error_buf_size, "invalid mutability");
+ return false;
+ }
+ global->is_mutable = mutable ? true : false;
+
+ /* initialize expression */
+ if (!load_init_expr(&p, p_end, &(global->init_expr), global->type,
+ error_buf, error_buf_size))
+ return false;
+
+ if (INIT_EXPR_TYPE_GET_GLOBAL == global->init_expr.init_expr_type) {
+ /**
+ * Currently, constant expressions occurring as initializers
+ * of globals are further constrained in that contained
+ * global.get instructions are
+ * only allowed to refer to imported globals.
+ */
+ uint32 target_global_index = global->init_expr.u.global_index;
+ if (target_global_index >= module->import_global_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown global");
+ return false;
+ }
+ }
+ else if (INIT_EXPR_TYPE_FUNCREF_CONST
+ == global->init_expr.init_expr_type) {
+ if (!check_function_index(module, global->init_expr.u.ref_index,
+ error_buf, error_buf_size)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load global section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 export_count, i, j, index;
+ uint64 total_size;
+ uint32 str_len;
+ WASMExport *export;
+ const char *name;
+
+ read_leb_uint32(p, p_end, export_count);
+
+ if (export_count) {
+ module->export_count = export_count;
+ total_size = sizeof(WASMExport) * (uint64)export_count;
+ if (!(module->exports =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ export = module->exports;
+ for (i = 0; i < export_count; i++, export ++) {
+#if WASM_ENABLE_THREAD_MGR == 0
+ if (p == p_end) {
+ /* export section with inconsistent count:
+ n export declared, but less than n given */
+ set_error_buf(error_buf, error_buf_size,
+ "length out of bounds");
+ return false;
+ }
+#endif
+ read_leb_uint32(p, p_end, str_len);
+ CHECK_BUF(p, p_end, str_len);
+
+ for (j = 0; j < i; j++) {
+ name = module->exports[j].name;
+ if (strlen(name) == str_len && memcmp(name, p, str_len) == 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "duplicate export name");
+ return false;
+ }
+ }
+
+ if (!(export->name = const_str_list_insert(
+ p, str_len, module, is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+ p += str_len;
+ CHECK_BUF(p, p_end, 1);
+ export->kind = read_uint8(p);
+ read_leb_uint32(p, p_end, index);
+ export->index = index;
+
+ switch (export->kind) {
+ /* function index */
+ case EXPORT_KIND_FUNC:
+ if (index >= module->function_count
+ + module->import_function_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown function");
+ return false;
+ }
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ /* TODO: check func type, if it has v128 param or result,
+ report error */
+#endif
+#endif
+ break;
+ /* table index */
+ case EXPORT_KIND_TABLE:
+ if (index
+ >= module->table_count + module->import_table_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown table");
+ return false;
+ }
+ break;
+ /* memory index */
+ case EXPORT_KIND_MEMORY:
+ if (index
+ >= module->memory_count + module->import_memory_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown memory");
+ return false;
+ }
+ break;
+ /* global index */
+ case EXPORT_KIND_GLOBAL:
+ if (index
+ >= module->global_count + module->import_global_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown global");
+ return false;
+ }
+ break;
+ default:
+ set_error_buf(error_buf, error_buf_size,
+ "invalid export kind");
+ return false;
+ }
+ }
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load export section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_table_index(const WASMModule *module, uint32 table_index, char *error_buf,
+ uint32 error_buf_size)
+{
+#if WASM_ENABLE_REF_TYPES == 0
+ if (table_index != 0) {
+ set_error_buf(error_buf, error_buf_size, "zero byte expected");
+ return false;
+ }
+#endif
+
+ if (table_index >= module->import_table_count + module->table_count) {
+ set_error_buf_v(error_buf, error_buf_size, "unknown table %d",
+ table_index);
+ return false;
+ }
+ return true;
+}
+
+static bool
+load_table_index(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
+ uint32 *p_table_index, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 table_index;
+
+ read_leb_uint32(p, p_end, table_index);
+ if (!check_table_index(module, table_index, error_buf, error_buf_size)) {
+ return false;
+ }
+
+ *p_table_index = table_index;
+ *p_buf = p;
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+static bool
+load_elem_type(const uint8 **p_buf, const uint8 *buf_end, uint32 *p_elem_type,
+ bool elemkind_zero, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint8 elem_type;
+
+ CHECK_BUF(p, p_end, 1);
+ elem_type = read_uint8(p);
+ if ((elemkind_zero && elem_type != 0)
+ || (!elemkind_zero && elem_type != VALUE_TYPE_FUNCREF
+ && elem_type != VALUE_TYPE_EXTERNREF)) {
+ set_error_buf(error_buf, error_buf_size, "invalid reference type");
+ return false;
+ }
+
+ if (elemkind_zero)
+ *p_elem_type = VALUE_TYPE_FUNCREF;
+ else
+ *p_elem_type = elem_type;
+ *p_buf = p;
+ return true;
+fail:
+ return false;
+}
+#endif /* WASM_ENABLE_REF_TYPES != 0*/
+
+static bool
+load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
+ WASMModule *module, WASMTableSeg *table_segment,
+ bool use_init_expr, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 function_count, function_index = 0, i;
+ uint64 total_size;
+
+ read_leb_uint32(p, p_end, function_count);
+ table_segment->function_count = function_count;
+ total_size = sizeof(uint32) * (uint64)function_count;
+ if (total_size > 0
+ && !(table_segment->func_indexes = (uint32 *)loader_malloc(
+ total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < function_count; i++) {
+ InitializerExpression init_expr = { 0 };
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!use_init_expr) {
+ read_leb_uint32(p, p_end, function_index);
+ }
+ else {
+ if (!load_init_expr(&p, p_end, &init_expr, table_segment->elem_type,
+ error_buf, error_buf_size))
+ return false;
+
+ function_index = init_expr.u.ref_index;
+ }
+#else
+ read_leb_uint32(p, p_end, function_index);
+ (void)use_init_expr;
+#endif
+
+ /* since we are using -1 to indicate ref.null */
+ if (init_expr.init_expr_type != INIT_EXPR_TYPE_REFNULL_CONST
+ && !check_function_index(module, function_index, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+ table_segment->func_indexes[i] = function_index;
+ }
+
+ *p_buf = p;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 table_segment_count, i;
+ uint64 total_size;
+ WASMTableSeg *table_segment;
+
+ read_leb_uint32(p, p_end, table_segment_count);
+
+ if (table_segment_count) {
+ module->table_seg_count = table_segment_count;
+ total_size = sizeof(WASMTableSeg) * (uint64)table_segment_count;
+ if (!(module->table_segments =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ table_segment = module->table_segments;
+ for (i = 0; i < table_segment_count; i++, table_segment++) {
+ if (p >= p_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid value type or "
+ "invalid elements segment kind");
+ return false;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ read_leb_uint32(p, p_end, table_segment->mode);
+ /* last three bits */
+ table_segment->mode = table_segment->mode & 0x07;
+ switch (table_segment->mode) {
+ /* elemkind/elemtype + active */
+ case 0:
+ case 4:
+ table_segment->elem_type = VALUE_TYPE_FUNCREF;
+ table_segment->table_index = 0;
+
+ if (!check_table_index(module, table_segment->table_index,
+ error_buf, error_buf_size))
+ return false;
+ if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+ VALUE_TYPE_I32, error_buf,
+ error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ table_segment->mode == 0 ? false
+ : true,
+ error_buf, error_buf_size))
+ return false;
+ break;
+ /* elemkind + passive/declarative */
+ case 1:
+ case 3:
+ if (!load_elem_type(&p, p_end, &table_segment->elem_type,
+ true, error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ false, error_buf, error_buf_size))
+ return false;
+ break;
+ /* elemkind/elemtype + table_idx + active */
+ case 2:
+ case 6:
+ if (!load_table_index(&p, p_end, module,
+ &table_segment->table_index,
+ error_buf, error_buf_size))
+ return false;
+ if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+ VALUE_TYPE_I32, error_buf,
+ error_buf_size))
+ return false;
+ if (!load_elem_type(&p, p_end, &table_segment->elem_type,
+ table_segment->mode == 2 ? true : false,
+ error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ table_segment->mode == 2 ? false
+ : true,
+ error_buf, error_buf_size))
+ return false;
+ break;
+ case 5:
+ case 7:
+ if (!load_elem_type(&p, p_end, &table_segment->elem_type,
+ false, error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ true, error_buf, error_buf_size))
+ return false;
+ break;
+ default:
+ set_error_buf(error_buf, error_buf_size,
+ "unknown element segment kind");
+ return false;
+ }
+#else
+ /*
+ * like: 00 41 05 0b 04 00 01 00 01
+ * for: (elem 0 (offset (i32.const 5)) $f1 $f2 $f1 $f2)
+ */
+ if (!load_table_index(&p, p_end, module,
+ &table_segment->table_index, error_buf,
+ error_buf_size))
+ return false;
+ if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+ VALUE_TYPE_I32, error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment, false,
+ error_buf, error_buf_size))
+ return false;
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+ }
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load table segment section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 data_seg_count, i, mem_index, data_seg_len;
+ uint64 total_size;
+ WASMDataSeg *dataseg;
+ InitializerExpression init_expr;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ bool is_passive = false;
+ uint32 mem_flag;
+#endif
+
+ read_leb_uint32(p, p_end, data_seg_count);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if ((module->data_seg_count1 != 0)
+ && (data_seg_count != module->data_seg_count1)) {
+ set_error_buf(error_buf, error_buf_size,
+ "data count and data section have inconsistent lengths");
+ return false;
+ }
+#endif
+
+ if (data_seg_count) {
+ module->data_seg_count = data_seg_count;
+ total_size = sizeof(WASMDataSeg *) * (uint64)data_seg_count;
+ if (!(module->data_segments =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < data_seg_count; i++) {
+ read_leb_uint32(p, p_end, mem_index);
+#if WASM_ENABLE_BULK_MEMORY != 0
+ is_passive = false;
+ mem_flag = mem_index & 0x03;
+ switch (mem_flag) {
+ case 0x01:
+ is_passive = true;
+ break;
+ case 0x00:
+ /* no memory index, treat index as 0 */
+ mem_index = 0;
+ goto check_mem_index;
+ case 0x02:
+ /* read following memory index */
+ read_leb_uint32(p, p_end, mem_index);
+ check_mem_index:
+ if (mem_index
+ >= module->import_memory_count + module->memory_count) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "unknown memory %d", mem_index);
+ return false;
+ }
+ break;
+ case 0x03:
+ default:
+ set_error_buf(error_buf, error_buf_size, "unknown memory");
+ return false;
+ break;
+ }
+#else
+ if (mem_index
+ >= module->import_memory_count + module->memory_count) {
+ set_error_buf_v(error_buf, error_buf_size, "unknown memory %d",
+ mem_index);
+ return false;
+ }
+#endif /* WASM_ENABLE_BULK_MEMORY */
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if (!is_passive)
+#endif
+ if (!load_init_expr(&p, p_end, &init_expr, VALUE_TYPE_I32,
+ error_buf, error_buf_size))
+ return false;
+
+ read_leb_uint32(p, p_end, data_seg_len);
+
+ if (!(dataseg = module->data_segments[i] = loader_malloc(
+ sizeof(WASMDataSeg), error_buf, error_buf_size))) {
+ return false;
+ }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ dataseg->is_passive = is_passive;
+ if (!is_passive)
+#endif
+ {
+ bh_memcpy_s(&dataseg->base_offset,
+ sizeof(InitializerExpression), &init_expr,
+ sizeof(InitializerExpression));
+
+ dataseg->memory_index = mem_index;
+ }
+
+ dataseg->data_length = data_seg_len;
+ CHECK_BUF(p, p_end, data_seg_len);
+ dataseg->data = (uint8 *)p;
+ p += data_seg_len;
+ }
+ }
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load data segment section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+static bool
+load_datacount_section(const uint8 *buf, const uint8 *buf_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 data_seg_count1 = 0;
+
+ read_leb_uint32(p, p_end, data_seg_count1);
+ module->data_seg_count1 = data_seg_count1;
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load datacount section success.\n");
+ return true;
+fail:
+ return false;
+}
+#endif
+
+static bool
+load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func,
+ const uint8 *buf_func_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ const uint8 *p_func = buf_func;
+ uint32 func_count = 0, code_count;
+
+ /* code has been loaded in function section, so pass it here, just check
+ * whether function and code section have inconsistent lengths */
+ read_leb_uint32(p, p_end, code_count);
+
+ if (buf_func)
+ read_leb_uint32(p_func, buf_func_end, func_count);
+
+ if (func_count != code_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "function and code section have inconsistent lengths");
+ return false;
+ }
+
+ LOG_VERBOSE("Load code segment section success.\n");
+ (void)module;
+ return true;
+fail:
+ return false;
+}
+
+static bool
+load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ WASMType *type;
+ uint32 start_function;
+
+ read_leb_uint32(p, p_end, start_function);
+
+ if (start_function
+ >= module->function_count + module->import_function_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown function");
+ return false;
+ }
+
+ if (start_function < module->import_function_count)
+ type = module->import_functions[start_function].u.function.func_type;
+ else
+ type = module->functions[start_function - module->import_function_count]
+ ->func_type;
+ if (type->param_count != 0 || type->result_count != 0) {
+ set_error_buf(error_buf, error_buf_size, "invalid start function");
+ return false;
+ }
+
+ module->start_function = start_function;
+
+ if (p != p_end) {
+ set_error_buf(error_buf, error_buf_size, "section size mismatch");
+ return false;
+ }
+
+ LOG_VERBOSE("Load start section success.\n");
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+static bool
+handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 name_type, subsection_size;
+ uint32 previous_name_type = 0;
+ uint32 num_func_name;
+ uint32 func_index;
+ uint32 previous_func_index = ~0U;
+ uint32 func_name_len;
+ uint32 name_index;
+ int i = 0;
+
+ if (p >= p_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ return false;
+ }
+
+ while (p < p_end) {
+ read_leb_uint32(p, p_end, name_type);
+ if (i != 0) {
+ if (name_type == previous_name_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "duplicate sub-section");
+ return false;
+ }
+ if (name_type < previous_name_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "out-of-order sub-section");
+ return false;
+ }
+ }
+ previous_name_type = name_type;
+ read_leb_uint32(p, p_end, subsection_size);
+ CHECK_BUF(p, p_end, subsection_size);
+ switch (name_type) {
+ case SUB_SECTION_TYPE_FUNC:
+ if (subsection_size) {
+ read_leb_uint32(p, p_end, num_func_name);
+ for (name_index = 0; name_index < num_func_name;
+ name_index++) {
+ read_leb_uint32(p, p_end, func_index);
+ if (func_index == previous_func_index) {
+ set_error_buf(error_buf, error_buf_size,
+ "duplicate function name");
+ return false;
+ }
+ if (func_index < previous_func_index
+ && previous_func_index != ~0U) {
+ set_error_buf(error_buf, error_buf_size,
+ "out-of-order function index ");
+ return false;
+ }
+ previous_func_index = func_index;
+ read_leb_uint32(p, p_end, func_name_len);
+ CHECK_BUF(p, p_end, func_name_len);
+ /* Skip the import functions */
+ if (func_index >= module->import_function_count) {
+ func_index -= module->import_function_count;
+ if (func_index >= module->function_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "out-of-range function index");
+ return false;
+ }
+ if (!(module->functions[func_index]->field_name =
+ const_str_list_insert(
+ p, func_name_len, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ }
+ p += func_name_len;
+ }
+ }
+ break;
+ case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection
+ */
+ case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */
+ default:
+ p = p + subsection_size;
+ break;
+ }
+ i++;
+ }
+
+ return true;
+fail:
+ return false;
+}
+#endif
+
+static bool
+load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ char section_name[32];
+ uint32 name_len, buffer_len;
+
+ if (p >= p_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ return false;
+ }
+
+ read_leb_uint32(p, p_end, name_len);
+
+ if (name_len == 0 || p + name_len > p_end) {
+ set_error_buf(error_buf, error_buf_size, "unexpected end");
+ return false;
+ }
+
+ if (!check_utf8_str(p, name_len)) {
+ set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding");
+ return false;
+ }
+
+ buffer_len = sizeof(section_name);
+ memset(section_name, 0, buffer_len);
+ if (name_len < buffer_len) {
+ bh_memcpy_s(section_name, buffer_len, p, name_len);
+ }
+ else {
+ bh_memcpy_s(section_name, buffer_len, p, buffer_len - 4);
+ memset(section_name + buffer_len - 4, '.', 3);
+ }
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ if (memcmp(p, "name", 4) == 0) {
+ module->name_section_buf = buf;
+ module->name_section_buf_end = buf_end;
+ p += name_len;
+ handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf,
+ error_buf_size);
+ LOG_VERBOSE("Load custom name section success.");
+ return true;
+ }
+#endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ {
+ WASMCustomSection *section =
+ loader_malloc(sizeof(WASMCustomSection), error_buf, error_buf_size);
+
+ if (!section) {
+ return false;
+ }
+
+ section->name_addr = (char *)p;
+ section->name_len = name_len;
+ section->content_addr = (uint8 *)(p + name_len);
+ section->content_len = (uint32)(p_end - p - name_len);
+
+ section->next = module->custom_section_list;
+ module->custom_section_list = section;
+ LOG_VERBOSE("Load custom section [%s] success.", section_name);
+ return true;
+ }
+#endif
+
+ LOG_VERBOSE("Ignore custom section [%s].", section_name);
+
+ (void)is_load_from_file_buf;
+ (void)module;
+ return true;
+fail:
+ return false;
+}
+
+static void
+calculate_global_data_offset(WASMModule *module)
+{
+ uint32 i, data_offset;
+
+ data_offset = 0;
+ for (i = 0; i < module->import_global_count; i++) {
+ WASMGlobalImport *import_global =
+ &((module->import_globals + i)->u.global);
+#if WASM_ENABLE_FAST_JIT != 0
+ import_global->data_offset = data_offset;
+#endif
+ data_offset += wasm_value_type_size(import_global->type);
+ }
+
+ for (i = 0; i < module->global_count; i++) {
+ WASMGlobal *global = module->globals + i;
+#if WASM_ENABLE_FAST_JIT != 0
+ global->data_offset = data_offset;
+#endif
+ data_offset += wasm_value_type_size(global->type);
+ }
+
+ module->global_data_size = data_offset;
+}
+
+#if WASM_ENABLE_FAST_JIT != 0
+static bool
+init_fast_jit_functions(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+#if WASM_ENABLE_LAZY_JIT != 0
+ JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+#endif
+ uint32 i;
+
+ if (!module->function_count)
+ return true;
+
+ if (!(module->fast_jit_func_ptrs =
+ loader_malloc(sizeof(void *) * module->function_count, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+#if WASM_ENABLE_LAZY_JIT != 0
+ for (i = 0; i < module->function_count; i++) {
+ module->fast_jit_func_ptrs[i] =
+ jit_globals->compile_fast_jit_and_then_call;
+ }
+#endif
+
+ for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) {
+ if (os_mutex_init(&module->fast_jit_thread_locks[i]) != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "init fast jit thread lock failed");
+ return false;
+ }
+ module->fast_jit_thread_locks_inited[i] = true;
+ }
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 */
+
+#if WASM_ENABLE_JIT != 0
+static bool
+init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
+ AOTCompOption option = { 0 };
+ char *aot_last_error;
+ uint64 size;
+
+ if (module->function_count == 0)
+ return true;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LLVM_JIT != 0
+ if (os_mutex_init(&module->tierup_wait_lock) != 0) {
+ set_error_buf(error_buf, error_buf_size, "init jit tierup lock failed");
+ return false;
+ }
+ if (os_cond_init(&module->tierup_wait_cond) != 0) {
+ set_error_buf(error_buf, error_buf_size, "init jit tierup cond failed");
+ os_mutex_destroy(&module->tierup_wait_lock);
+ return false;
+ }
+ module->tierup_wait_lock_inited = true;
+#endif
+
+ size = sizeof(void *) * (uint64)module->function_count
+ + sizeof(bool) * (uint64)module->function_count;
+ if (!(module->func_ptrs = loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+ module->func_ptrs_compiled =
+ (bool *)((uint8 *)module->func_ptrs
+ + sizeof(void *) * module->function_count);
+
+ module->comp_data = aot_create_comp_data(module);
+ if (!module->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 false;
+ }
+
+ option.is_jit_mode = true;
+
+ llvm_jit_options = wasm_runtime_get_llvm_jit_options();
+ option.opt_level = llvm_jit_options.opt_level;
+ option.size_level = llvm_jit_options.size_level;
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ option.enable_bulk_memory = true;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ option.enable_thread_mgr = true;
+#endif
+#if WASM_ENABLE_TAIL_CALL != 0
+ option.enable_tail_call = true;
+#endif
+#if WASM_ENABLE_SIMD != 0
+ option.enable_simd = true;
+#endif
+#if WASM_ENABLE_REF_TYPES != 0
+ option.enable_ref_types = true;
+#endif
+ option.enable_aux_stack_check = true;
+#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+ option.enable_aux_stack_frame = true;
+#endif
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ option.enable_stack_estimation = true;
+#endif
+
+ module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
+ if (!module->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);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ char *aot_last_error;
+ uint32 i;
+
+ if (module->function_count == 0)
+ return true;
+
+ if (!aot_compile_wasm(module->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);
+ return false;
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ if (module->orcjit_stop_compiling)
+ return false;
+#endif
+
+ bh_print_time("Begin to lookup llvm jit functions");
+
+ for (i = 0; i < module->function_count; i++) {
+ LLVMOrcJITTargetAddress func_addr = 0;
+ LLVMErrorRef error;
+ char func_name[48];
+
+ snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
+ error = LLVMOrcLLLazyJITLookup(module->comp_ctx->orc_jit, &func_addr,
+ func_name);
+ if (error != LLVMErrorSuccess) {
+ char *err_msg = LLVMGetErrorMessage(error);
+ set_error_buf_v(error_buf, error_buf_size,
+ "failed to compile llvm jit function: %s", err_msg);
+ LLVMDisposeErrorMessage(err_msg);
+ return false;
+ }
+
+ /**
+ * No need to lock the func_ptr[func_idx] here as it is basic
+ * data type, the load/store for it can be finished by one cpu
+ * instruction, and there can be only one cpu instruction
+ * loading/storing at the same time.
+ */
+ module->func_ptrs[i] = (void *)func_addr;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
+
+ if (module->orcjit_stop_compiling)
+ return false;
+#endif
+ }
+
+ bh_print_time("End lookup llvm jit functions");
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_JIT != 0 */
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+static void *
+init_llvm_jit_functions_stage2_callback(void *arg)
+{
+ WASMModule *module = (WASMModule *)arg;
+ char error_buf[128];
+ uint32 error_buf_size = (uint32)sizeof(error_buf);
+
+ if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) {
+ module->orcjit_stop_compiling = true;
+ return NULL;
+ }
+
+ os_mutex_lock(&module->tierup_wait_lock);
+ module->llvm_jit_inited = true;
+ os_cond_broadcast(&module->tierup_wait_cond);
+ os_mutex_unlock(&module->tierup_wait_lock);
+
+ return NULL;
+}
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+/* The callback function to compile jit functions */
+static void *
+orcjit_thread_callback(void *arg)
+{
+ OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
+#if WASM_ENABLE_JIT != 0
+ AOTCompContext *comp_ctx = thread_arg->comp_ctx;
+#endif
+ WASMModule *module = thread_arg->module;
+ uint32 group_idx = thread_arg->group_idx;
+ uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+ uint32 func_count = module->function_count;
+ uint32 i;
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /* Compile fast jit funcitons of this group */
+ for (i = group_idx; i < func_count; i += group_stride) {
+ if (!jit_compiler_compile(module, i + module->import_function_count)) {
+ os_printf("failed to compile fast jit function %u\n", i);
+ break;
+ }
+
+ if (module->orcjit_stop_compiling) {
+ return NULL;
+ }
+ }
+#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ os_mutex_lock(&module->tierup_wait_lock);
+ module->fast_jit_ready_groups++;
+ os_mutex_unlock(&module->tierup_wait_lock);
+#endif
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ /* For JIT tier-up, set each llvm jit func to call_to_fast_jit */
+ for (i = group_idx; i < func_count;
+ i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
+ uint32 j;
+
+ for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+ if (i + j * group_stride < func_count) {
+ if (!jit_compiler_set_call_to_fast_jit(
+ module,
+ i + j * group_stride + module->import_function_count)) {
+ os_printf(
+ "failed to compile call_to_fast_jit for func %u\n",
+ i + j * group_stride + module->import_function_count);
+ module->orcjit_stop_compiling = true;
+ return NULL;
+ }
+ }
+ if (module->orcjit_stop_compiling) {
+ return NULL;
+ }
+ }
+ }
+
+ /* Wait until init_llvm_jit_functions_stage2 finishes and all
+ fast jit functions are compiled */
+ os_mutex_lock(&module->tierup_wait_lock);
+ while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation
+ && module->fast_jit_ready_groups >= group_stride)) {
+ os_cond_reltimedwait(&module->tierup_wait_cond,
+ &module->tierup_wait_lock, 10000);
+ if (module->orcjit_stop_compiling) {
+ /* init_llvm_jit_functions_stage2 failed */
+ os_mutex_unlock(&module->tierup_wait_lock);
+ return NULL;
+ }
+ }
+ os_mutex_unlock(&module->tierup_wait_lock);
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ /* Compile llvm jit functions of this group */
+ for (i = group_idx; i < func_count;
+ i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
+ LLVMOrcJITTargetAddress func_addr = 0;
+ LLVMErrorRef error;
+ char func_name[48];
+ typedef void (*F)(void);
+ union {
+ F f;
+ void *v;
+ } u;
+ uint32 j;
+
+ snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i,
+ "_wrapper");
+ LOG_DEBUG("compile llvm jit func %s", func_name);
+ error =
+ LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name);
+ if (error != LLVMErrorSuccess) {
+ char *err_msg = LLVMGetErrorMessage(error);
+ os_printf("failed to compile llvm jit function %u: %s", i, err_msg);
+ LLVMDisposeErrorMessage(err_msg);
+ break;
+ }
+
+ /* Call the jit wrapper function to trigger its compilation, so as
+ to compile the actual jit functions, since we add the latter to
+ function list in the PartitionFunction callback */
+ u.v = (void *)func_addr;
+ u.f();
+
+ for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+ if (i + j * group_stride < func_count) {
+ module->func_ptrs_compiled[i + j * group_stride] = true;
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX,
+ i + j * group_stride);
+ error = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr,
+ func_name);
+ if (error != LLVMErrorSuccess) {
+ char *err_msg = LLVMGetErrorMessage(error);
+ os_printf("failed to compile llvm jit function %u: %s", i,
+ err_msg);
+ LLVMDisposeErrorMessage(err_msg);
+ /* Ignore current llvm jit func, as its func ptr is
+ previous set to call_to_fast_jit, which also works */
+ continue;
+ }
+
+ jit_compiler_set_llvm_jit_func_ptr(
+ module,
+ i + j * group_stride + module->import_function_count,
+ (void *)func_addr);
+
+ /* Try to switch to call this llvm jit funtion instead of
+ fast jit function from fast jit jitted code */
+ jit_compiler_set_call_to_llvm_jit(
+ module,
+ i + j * group_stride + module->import_function_count);
+#endif
+ }
+ }
+
+ if (module->orcjit_stop_compiling) {
+ break;
+ }
+ }
+#endif
+
+ return NULL;
+}
+
+static void
+orcjit_stop_compile_threads(WASMModule *module)
+{
+ uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args)
+ / sizeof(OrcJitThreadArg));
+
+ module->orcjit_stop_compiling = true;
+ for (i = 0; i < thread_num; i++) {
+ if (module->orcjit_threads[i])
+ os_thread_join(module->orcjit_threads[i], NULL);
+ }
+}
+
+static bool
+compile_jit_functions(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 thread_num =
+ (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg));
+ uint32 i, j;
+
+ bh_print_time("Begin to compile jit functions");
+
+ /* Create threads to compile the jit functions */
+ for (i = 0; i < thread_num && i < module->function_count; i++) {
+#if WASM_ENABLE_JIT != 0
+ module->orcjit_thread_args[i].comp_ctx = module->comp_ctx;
+#endif
+ module->orcjit_thread_args[i].module = module;
+ module->orcjit_thread_args[i].group_idx = i;
+
+ if (os_thread_create(&module->orcjit_threads[i], orcjit_thread_callback,
+ (void *)&module->orcjit_thread_args[i],
+ APP_THREAD_STACK_SIZE_DEFAULT)
+ != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "create orcjit compile thread failed");
+ /* Terminate the threads created */
+ module->orcjit_stop_compiling = true;
+ for (j = 0; j < i; j++) {
+ os_thread_join(module->orcjit_threads[j], NULL);
+ }
+ return false;
+ }
+ }
+
+#if WASM_ENABLE_LAZY_JIT == 0
+ /* Wait until all jit functions are compiled for eager mode */
+ for (i = 0; i < thread_num; i++) {
+ if (module->orcjit_threads[i])
+ os_thread_join(module->orcjit_threads[i], NULL);
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /* Ensure all the fast-jit functions are compiled */
+ for (i = 0; i < module->function_count; i++) {
+ if (!jit_compiler_is_compiled(module,
+ i + module->import_function_count)) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to compile fast jit function");
+ return false;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ /* Ensure all the llvm-jit functions are compiled */
+ for (i = 0; i < module->function_count; i++) {
+ if (!module->func_ptrs_compiled[i]) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to compile llvm jit function");
+ return false;
+ }
+ }
+#endif
+#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
+
+ bh_print_time("End compile jit functions");
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
+
+static bool
+wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
+ uint32 cur_func_idx, char *error_buf,
+ uint32 error_buf_size);
+
+#if WASM_ENABLE_FAST_INTERP != 0 && WASM_ENABLE_LABELS_AS_VALUES != 0
+void **
+wasm_interp_get_handle_table();
+
+static void **handle_table;
+#endif
+
+static bool
+load_from_sections(WASMModule *module, WASMSection *sections,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMExport *export;
+ WASMSection *section = sections;
+ const uint8 *buf, *buf_end, *buf_code = NULL, *buf_code_end = NULL,
+ *buf_func = NULL, *buf_func_end = NULL;
+ WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL;
+ WASMGlobal *aux_stack_top_global = NULL, *global;
+ uint32 aux_data_end = (uint32)-1, aux_heap_base = (uint32)-1;
+ uint32 aux_stack_top = (uint32)-1, global_index, func_index, i;
+ uint32 aux_data_end_global_index = (uint32)-1;
+ uint32 aux_heap_base_global_index = (uint32)-1;
+ WASMType *func_type;
+
+ /* Find code and function sections if have */
+ while (section) {
+ if (section->section_type == SECTION_TYPE_CODE) {
+ buf_code = section->section_body;
+ buf_code_end = buf_code + section->section_body_size;
+#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0
+ module->buf_code = (uint8 *)buf_code;
+ module->buf_code_size = section->section_body_size;
+#endif
+ }
+ else if (section->section_type == SECTION_TYPE_FUNC) {
+ buf_func = section->section_body;
+ buf_func_end = buf_func + section->section_body_size;
+ }
+ section = section->next;
+ }
+
+ section = sections;
+ while (section) {
+ buf = section->section_body;
+ buf_end = buf + section->section_body_size;
+ switch (section->section_type) {
+ case SECTION_TYPE_USER:
+ /* unsupported user section, ignore it. */
+ if (!load_user_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_TYPE:
+ if (!load_type_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_IMPORT:
+ if (!load_import_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_FUNC:
+ if (!load_function_section(buf, buf_end, buf_code, buf_code_end,
+ module, error_buf, error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_TABLE:
+ if (!load_table_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_MEMORY:
+ if (!load_memory_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_GLOBAL:
+ if (!load_global_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_EXPORT:
+ if (!load_export_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_START:
+ if (!load_start_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_ELEM:
+ if (!load_table_segment_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_CODE:
+ if (!load_code_section(buf, buf_end, buf_func, buf_func_end,
+ module, error_buf, error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_DATA:
+ if (!load_data_segment_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case SECTION_TYPE_DATACOUNT:
+ if (!load_datacount_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+#endif
+ default:
+ set_error_buf(error_buf, error_buf_size, "invalid section id");
+ return false;
+ }
+
+ section = section->next;
+ }
+
+ module->aux_data_end_global_index = (uint32)-1;
+ module->aux_heap_base_global_index = (uint32)-1;
+ module->aux_stack_top_global_index = (uint32)-1;
+
+ /* Resolve auxiliary data/stack/heap info and reset memory info */
+ export = module->exports;
+ for (i = 0; i < module->export_count; i++, export ++) {
+ if (export->kind == EXPORT_KIND_GLOBAL) {
+ if (!strcmp(export->name, "__heap_base")) {
+ global_index = export->index - module->import_global_count;
+ global = module->globals + global_index;
+ if (global->type == VALUE_TYPE_I32 && !global->is_mutable
+ && global->init_expr.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST) {
+ aux_heap_base_global = global;
+ aux_heap_base = global->init_expr.u.i32;
+ aux_heap_base_global_index = export->index;
+ LOG_VERBOSE("Found aux __heap_base global, value: %d",
+ aux_heap_base);
+ }
+ }
+ else if (!strcmp(export->name, "__data_end")) {
+ global_index = export->index - module->import_global_count;
+ global = module->globals + global_index;
+ if (global->type == VALUE_TYPE_I32 && !global->is_mutable
+ && global->init_expr.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST) {
+ aux_data_end_global = global;
+ aux_data_end = global->init_expr.u.i32;
+ aux_data_end_global_index = export->index;
+ LOG_VERBOSE("Found aux __data_end global, value: %d",
+ aux_data_end);
+
+ aux_data_end = align_uint(aux_data_end, 16);
+ }
+ }
+
+ /* For module compiled with -pthread option, the global is:
+ [0] stack_top <-- 0
+ [1] tls_pointer
+ [2] tls_size
+ [3] data_end <-- 3
+ [4] global_base
+ [5] heap_base <-- 5
+ [6] dso_handle
+
+ For module compiled without -pthread option:
+ [0] stack_top <-- 0
+ [1] data_end <-- 1
+ [2] global_base
+ [3] heap_base <-- 3
+ [4] dso_handle
+ */
+ if (aux_data_end_global && aux_heap_base_global
+ && aux_data_end <= aux_heap_base) {
+ module->aux_data_end_global_index = aux_data_end_global_index;
+ module->aux_data_end = aux_data_end;
+ module->aux_heap_base_global_index = aux_heap_base_global_index;
+ module->aux_heap_base = aux_heap_base;
+
+ /* Resolve aux stack top global */
+ for (global_index = 0; global_index < module->global_count;
+ global_index++) {
+ global = module->globals + global_index;
+ if (global->is_mutable /* heap_base and data_end is
+ not mutable */
+ && global->type == VALUE_TYPE_I32
+ && global->init_expr.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST
+ && (uint32)global->init_expr.u.i32 <= aux_heap_base) {
+ aux_stack_top_global = global;
+ aux_stack_top = (uint32)global->init_expr.u.i32;
+ module->aux_stack_top_global_index =
+ module->import_global_count + global_index;
+ module->aux_stack_bottom = aux_stack_top;
+ module->aux_stack_size =
+ aux_stack_top > aux_data_end
+ ? aux_stack_top - aux_data_end
+ : aux_stack_top;
+ LOG_VERBOSE("Found aux stack top global, value: %d, "
+ "global index: %d, stack size: %d",
+ aux_stack_top, global_index,
+ module->aux_stack_size);
+ break;
+ }
+ }
+ if (!aux_stack_top_global) {
+ /* Auxiliary stack global isn't found, it must be unused
+ in the wasm app, as if it is used, the global must be
+ defined. Here we set it to __heap_base global and set
+ its size to 0. */
+ aux_stack_top_global = aux_heap_base_global;
+ aux_stack_top = aux_heap_base;
+ module->aux_stack_top_global_index =
+ module->aux_heap_base_global_index;
+ module->aux_stack_bottom = aux_stack_top;
+ module->aux_stack_size = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ module->malloc_function = (uint32)-1;
+ module->free_function = (uint32)-1;
+ module->retain_function = (uint32)-1;
+
+ /* Resolve malloc/free function exported by wasm module */
+ export = module->exports;
+ for (i = 0; i < module->export_count; i++, export ++) {
+ if (export->kind == EXPORT_KIND_FUNC) {
+ if (!strcmp(export->name, "malloc")
+ && export->index >= module->import_function_count) {
+ func_index = export->index - module->import_function_count;
+ func_type = module->functions[func_index]->func_type;
+ if (func_type->param_count == 1 && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32) {
+ bh_assert(module->malloc_function == (uint32)-1);
+ module->malloc_function = export->index;
+ LOG_VERBOSE("Found malloc function, name: %s, index: %u",
+ export->name, export->index);
+ }
+ }
+ else if (!strcmp(export->name, "__new")
+ && export->index >= module->import_function_count) {
+ /* __new && __pin for AssemblyScript */
+ func_index = export->index - module->import_function_count;
+ func_type = module->functions[func_index]->func_type;
+ if (func_type->param_count == 2 && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32
+ && func_type->types[2] == VALUE_TYPE_I32) {
+ uint32 j;
+ WASMExport *export_tmp;
+
+ bh_assert(module->malloc_function == (uint32)-1);
+ module->malloc_function = export->index;
+ LOG_VERBOSE("Found malloc function, name: %s, index: %u",
+ export->name, export->index);
+
+ /* resolve retain function.
+ If not found, reset malloc function index */
+ export_tmp = module->exports;
+ for (j = 0; j < module->export_count; j++, export_tmp++) {
+ if ((export_tmp->kind == EXPORT_KIND_FUNC)
+ && (!strcmp(export_tmp->name, "__retain")
+ || (!strcmp(export_tmp->name, "__pin")))
+ && (export_tmp->index
+ >= module->import_function_count)) {
+ func_index = export_tmp->index
+ - module->import_function_count;
+ func_type =
+ module->functions[func_index]->func_type;
+ if (func_type->param_count == 1
+ && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32) {
+ bh_assert(module->retain_function
+ == (uint32)-1);
+ module->retain_function = export_tmp->index;
+ LOG_VERBOSE("Found retain function, name: %s, "
+ "index: %u",
+ export_tmp->name,
+ export_tmp->index);
+ break;
+ }
+ }
+ }
+ if (j == module->export_count) {
+ module->malloc_function = (uint32)-1;
+ LOG_VERBOSE("Can't find retain function,"
+ "reset malloc function index to -1");
+ }
+ }
+ }
+ else if (((!strcmp(export->name, "free"))
+ || (!strcmp(export->name, "__release"))
+ || (!strcmp(export->name, "__unpin")))
+ && export->index >= module->import_function_count) {
+ func_index = export->index - module->import_function_count;
+ func_type = module->functions[func_index]->func_type;
+ if (func_type->param_count == 1 && func_type->result_count == 0
+ && func_type->types[0] == VALUE_TYPE_I32) {
+ bh_assert(module->free_function == (uint32)-1);
+ module->free_function = export->index;
+ LOG_VERBOSE("Found free function, name: %s, index: %u",
+ export->name, export->index);
+ }
+ }
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0 && WASM_ENABLE_LABELS_AS_VALUES != 0
+ handle_table = wasm_interp_get_handle_table();
+#endif
+
+ for (i = 0; i < module->function_count; i++) {
+ WASMFunction *func = module->functions[i];
+ if (!wasm_loader_prepare_bytecode(module, func, i, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+
+ if (i == module->function_count - 1
+ && func->code + func->code_size != buf_code_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "code section size mismatch");
+ return false;
+ }
+ }
+
+ if (!module->possible_memory_grow) {
+ WASMMemoryImport *memory_import;
+ WASMMemory *memory;
+
+ if (aux_data_end_global && aux_heap_base_global
+ && aux_stack_top_global) {
+ uint64 init_memory_size;
+ uint32 shrunk_memory_size = align_uint(aux_heap_base, 8);
+
+ if (module->import_memory_count) {
+ memory_import = &module->import_memories[0].u.memory;
+ init_memory_size = (uint64)memory_import->num_bytes_per_page
+ * memory_import->init_page_count;
+ if (shrunk_memory_size <= init_memory_size) {
+ /* Reset memory info to decrease memory usage */
+ memory_import->num_bytes_per_page = shrunk_memory_size;
+ memory_import->init_page_count = 1;
+ LOG_VERBOSE("Shrink import memory size to %d",
+ shrunk_memory_size);
+ }
+ }
+ if (module->memory_count) {
+ memory = &module->memories[0];
+ init_memory_size = (uint64)memory->num_bytes_per_page
+ * memory->init_page_count;
+ if (shrunk_memory_size <= init_memory_size) {
+ /* Reset memory info to decrease memory usage */
+ memory->num_bytes_per_page = shrunk_memory_size;
+ memory->init_page_count = 1;
+ LOG_VERBOSE("Shrink memory size to %d", shrunk_memory_size);
+ }
+ }
+ }
+
+#if WASM_ENABLE_MULTI_MODULE == 0
+ if (module->import_memory_count) {
+ memory_import = &module->import_memories[0].u.memory;
+ if (memory_import->init_page_count < DEFAULT_MAX_PAGES)
+ memory_import->num_bytes_per_page *=
+ memory_import->init_page_count;
+ else
+ memory_import->num_bytes_per_page = UINT32_MAX;
+
+ if (memory_import->init_page_count > 0)
+ memory_import->init_page_count = memory_import->max_page_count =
+ 1;
+ else
+ memory_import->init_page_count = memory_import->max_page_count =
+ 0;
+ }
+ if (module->memory_count) {
+ memory = &module->memories[0];
+ if (memory->init_page_count < DEFAULT_MAX_PAGES)
+ memory->num_bytes_per_page *= memory->init_page_count;
+ else
+ memory->num_bytes_per_page = UINT32_MAX;
+
+ if (memory->init_page_count > 0)
+ memory->init_page_count = memory->max_page_count = 1;
+ else
+ memory->init_page_count = memory->max_page_count = 0;
+ }
+#endif
+ }
+
+ calculate_global_data_offset(module);
+
+#if WASM_ENABLE_FAST_JIT != 0
+ if (!init_fast_jit_functions(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ if (!init_llvm_jit_functions_stage1(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0)
+ if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#else
+ /* Run aot_compile_wasm in a backend thread, so as not to block the main
+ thread fast jit execution, since applying llvm optimizations in
+ aot_compile_wasm may cost a lot of time.
+ Create thread with enough native stack to apply llvm optimizations */
+ if (os_thread_create(&module->llvm_jit_init_thread,
+ init_llvm_jit_functions_stage2_callback,
+ (void *)module, APP_THREAD_STACK_SIZE_DEFAULT * 8)
+ != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "create orcjit compile thread failed");
+ return false;
+ }
+#endif
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ /* Create threads to compile the jit functions */
+ if (!compile_jit_functions(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#endif
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module);
+#endif
+ return true;
+}
+
+static WASMModule *
+create_module(char *error_buf, uint32 error_buf_size)
+{
+ WASMModule *module =
+ loader_malloc(sizeof(WASMModule), error_buf, error_buf_size);
+ bh_list_status ret;
+
+ if (!module) {
+ return NULL;
+ }
+
+ module->module_type = Wasm_Module_Bytecode;
+
+ /* Set start_function to -1, means no start function */
+ module->start_function = (uint32)-1;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ module->br_table_cache_list = &module->br_table_cache_list_head;
+ ret = bh_list_init(module->br_table_cache_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ module->import_module_list = &module->import_module_list_head;
+ ret = bh_list_init(module->import_module_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ ret = bh_list_init(&module->fast_opcode_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0 \
+ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0)
+ if (os_mutex_init(&module->instance_list_lock) != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "init instance list lock failed");
+ wasm_runtime_free(module);
+ return NULL;
+ }
+#endif
+
+ (void)ret;
+ return module;
+}
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+static bool
+record_fast_op(WASMModule *module, uint8 *pos, uint8 orig_op, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMFastOPCodeNode *fast_op =
+ loader_malloc(sizeof(WASMFastOPCodeNode), error_buf, error_buf_size);
+ if (fast_op) {
+ fast_op->offset = pos - module->load_addr;
+ fast_op->orig_op = orig_op;
+ bh_list_insert(&module->fast_opcode_list, fast_op);
+ }
+ return fast_op ? true : false;
+}
+#endif
+
+WASMModule *
+wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModule *module = create_module(error_buf, error_buf_size);
+ if (!module)
+ return NULL;
+
+ if (!load_from_sections(module, section_list, false, error_buf,
+ error_buf_size)) {
+ wasm_loader_unload(module);
+ return NULL;
+ }
+
+ LOG_VERBOSE("Load module from sections success.\n");
+ return module;
+}
+
+static void
+destroy_sections(WASMSection *section_list)
+{
+ WASMSection *section = section_list, *next;
+ while (section) {
+ next = section->next;
+ wasm_runtime_free(section);
+ section = next;
+ }
+}
+
+/* clang-format off */
+static uint8 section_ids[] = {
+ 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,
+#if WASM_ENABLE_BULK_MEMORY != 0
+ SECTION_TYPE_DATACOUNT,
+#endif
+ SECTION_TYPE_CODE,
+ SECTION_TYPE_DATA
+};
+/* clang-format on */
+
+static uint8
+get_section_index(uint8 section_type)
+{
+ uint8 max_id = sizeof(section_ids) / sizeof(uint8);
+
+ for (uint8 i = 0; i < max_id; i++) {
+ if (section_type == section_ids[i])
+ return i;
+ }
+
+ return (uint8)-1;
+}
+
+static bool
+create_sections(const uint8 *buf, uint32 size, WASMSection **p_section_list,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMSection *section_list_end = NULL, *section;
+ const uint8 *p = buf, *p_end = buf + size /*, *section_body*/;
+ uint8 section_type, section_index, last_section_index = (uint8)-1;
+ uint32 section_size;
+
+ bh_assert(!*p_section_list);
+
+ p += 8;
+ while (p < p_end) {
+ CHECK_BUF(p, p_end, 1);
+ section_type = read_uint8(p);
+ section_index = get_section_index(section_type);
+ if (section_index != (uint8)-1) {
+ if (section_type != SECTION_TYPE_USER) {
+ /* Custom sections may be inserted at any place,
+ while other sections must occur at most once
+ and in prescribed order. */
+ if (last_section_index != (uint8)-1
+ && (section_index <= last_section_index)) {
+ set_error_buf(error_buf, error_buf_size,
+ "unexpected content after last section or "
+ "junk after last section");
+ return false;
+ }
+ last_section_index = section_index;
+ }
+ read_leb_uint32(p, p_end, section_size);
+ CHECK_BUF1(p, p_end, section_size);
+
+ if (!(section = loader_malloc(sizeof(WASMSection), error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+ section->section_type = section_type;
+ section->section_body = (uint8 *)p;
+ section->section_body_size = section_size;
+
+ if (!section_list_end)
+ *p_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, "invalid section id");
+ return false;
+ }
+ }
+
+ return true;
+fail:
+ return false;
+}
+
+static void
+exchange32(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 union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+static bool
+load(const uint8 *buf, uint32 size, WASMModule *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;
+ WASMSection *section_list = NULL;
+
+ CHECK_BUF1(p, p_end, sizeof(uint32));
+ magic_number = read_uint32(p);
+ if (!is_little_endian())
+ exchange32((uint8 *)&magic_number);
+
+ if (magic_number != WASM_MAGIC_NUMBER) {
+ set_error_buf(error_buf, error_buf_size, "magic header not detected");
+ return false;
+ }
+
+ CHECK_BUF1(p, p_end, sizeof(uint32));
+ version = read_uint32(p);
+ if (!is_little_endian())
+ exchange32((uint8 *)&version);
+
+ if (version != WASM_CURRENT_VERSION) {
+ set_error_buf(error_buf, error_buf_size, "unknown binary version");
+ return false;
+ }
+
+ if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
+ || !load_from_sections(module, section_list, true, error_buf,
+ error_buf_size)) {
+ destroy_sections(section_list);
+ return false;
+ }
+
+ destroy_sections(section_list);
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_LIBC_WASI != 0
+/**
+ * refer to
+ * https://github.com/WebAssembly/WASI/blob/main/design/application-abi.md
+ */
+static bool
+check_wasi_abi_compatibility(const WASMModule *module,
+#if WASM_ENABLE_MULTI_MODULE != 0
+ bool main_module,
+#endif
+ char *error_buf, uint32 error_buf_size)
+{
+ /**
+ * be careful with:
+ * wasi compatiable modules(command/reactor) which don't import any wasi
+ * APIs. Usually, a command has to import a "prox_exit" at least, but a
+ * reactor can depend on nothing. At the same time, each has its own entry
+ * point.
+ *
+ * observations:
+ * - clang always injects `_start` into a command
+ * - clang always injects `_initialize` into a reactor
+ * - `iwasm -f` allows to run a function in the reactor
+ *
+ * strong assumptions:
+ * - no one will define either `_start` or `_initialize` on purpose
+ * - `_start` should always be `void _start(void)`
+ * - `_initialize` should always be `void _initialize(void)`
+ *
+ */
+
+ /* clang-format off */
+ /**
+ *
+ * | | import_wasi_api True | | import_wasi_api False | |
+ * | ----------- | -------------------- | ---------------- | --------------------- | ---------------- |
+ * | | \_initialize() Y | \_initialize() N | \_initialize() Y | \_initialize() N |
+ * | \_start() Y | N | COMMANDER | N | COMMANDER |
+ * | \_start() N | REACTOR | N | REACTOR | OTHERS |
+ */
+ /* clang-format on */
+
+ WASMExport *initialize = NULL, *memory = NULL, *start = NULL;
+
+ /* (func (export "_start") (...) */
+ start = wasm_loader_find_export(module, "", "_start", EXPORT_KIND_FUNC,
+ error_buf, error_buf_size);
+ if (start) {
+ WASMType *func_type =
+ module->functions[start->index - module->import_function_count]
+ ->func_type;
+ if (func_type->param_count || func_type->result_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "the signature of builtin _start function is wrong");
+ return false;
+ }
+ }
+
+ /* (func (export "_initialize") (...) */
+ initialize = wasm_loader_find_export(
+ module, "", "_initialize", EXPORT_KIND_FUNC, error_buf, error_buf_size);
+ if (initialize) {
+ WASMType *func_type =
+ module->functions[initialize->index - module->import_function_count]
+ ->func_type;
+ if (func_type->param_count || func_type->result_count) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "the signature of builtin _initialize function is wrong");
+ return false;
+ }
+ }
+
+ /* filter out non-wasi compatiable modules */
+ if (!module->import_wasi_api && !start && !initialize) {
+ return true;
+ }
+
+ /* should have one at least */
+ if (module->import_wasi_api && !start && !initialize) {
+ LOG_WARNING("warning: a module with WASI apis should be either "
+ "a command or a reactor");
+ }
+
+ /*
+ * there is at least one of `_start` and `_initialize` in below cases.
+ * according to the assumption, they should be all wasi compatiable
+ */
+
+ /* always can not have both at the same time */
+ if (start && initialize) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "neither a command nor a reactor can both have _start function "
+ "and _initialize function at the same time");
+ return false;
+ }
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /* filter out commands (with `_start`) cases */
+ if (start && !main_module) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "a command (with _start function) can not be a sub-module");
+ return false;
+ }
+#endif
+
+ /*
+ * it is ok a reactor acts as a main module,
+ * so skip the check about (with `_initialize`)
+ */
+
+ memory = wasm_loader_find_export(module, "", "memory", EXPORT_KIND_MEMORY,
+ error_buf, error_buf_size);
+ if (!memory
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+ /*
+ * with wasi-threads, it's still an open question if a memory
+ * should be exported.
+ *
+ * https://github.com/WebAssembly/wasi-threads/issues/22
+ * https://github.com/WebAssembly/WASI/issues/502
+ *
+ * Note: this code assumes the number of memories is at most 1.
+ */
+ && module->import_memory_count == 0
+#endif
+ ) {
+ set_error_buf(error_buf, error_buf_size,
+ "a module with WASI apis must export memory by default");
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+WASMModule *
+wasm_loader_load(uint8 *buf, uint32 size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+ bool main_module,
+#endif
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMModule *module = create_module(error_buf, error_buf_size);
+ if (!module) {
+ return NULL;
+ }
+
+#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_FAST_JIT != 0
+ module->load_addr = (uint8 *)buf;
+ module->load_size = size;
+#endif
+
+ if (!load(buf, size, module, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ /* Check the WASI application ABI */
+ if (!check_wasi_abi_compatibility(module,
+#if WASM_ENABLE_MULTI_MODULE != 0
+ main_module,
+#endif
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+#endif
+
+ LOG_VERBOSE("Load module success.\n");
+ return module;
+
+fail:
+ wasm_loader_unload(module);
+ return NULL;
+}
+
+void
+wasm_loader_unload(WASMModule *module)
+{
+ uint32 i;
+
+ if (!module)
+ return;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ module->orcjit_stop_compiling = true;
+ if (module->llvm_jit_init_thread)
+ os_thread_join(module->llvm_jit_init_thread, NULL);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ /* Stop Fast/LLVM JIT compilation firstly to avoid accessing
+ module internal data after they were freed */
+ orcjit_stop_compile_threads(module);
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ if (module->func_ptrs)
+ wasm_runtime_free(module->func_ptrs);
+ if (module->comp_ctx)
+ aot_destroy_comp_context(module->comp_ctx);
+ if (module->comp_data)
+ aot_destroy_comp_data(module->comp_data);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ if (module->tierup_wait_lock_inited) {
+ os_mutex_destroy(&module->tierup_wait_lock);
+ os_cond_destroy(&module->tierup_wait_cond);
+ }
+#endif
+
+ if (module->types) {
+ for (i = 0; i < module->type_count; i++) {
+ if (module->types[i])
+ destroy_wasm_type(module->types[i]);
+ }
+ wasm_runtime_free(module->types);
+ }
+
+ if (module->imports)
+ wasm_runtime_free(module->imports);
+
+ if (module->functions) {
+ for (i = 0; i < module->function_count; i++) {
+ if (module->functions[i]) {
+ if (module->functions[i]->local_offsets)
+ wasm_runtime_free(module->functions[i]->local_offsets);
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (module->functions[i]->code_compiled)
+ wasm_runtime_free(module->functions[i]->code_compiled);
+ if (module->functions[i]->consts)
+ wasm_runtime_free(module->functions[i]->consts);
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+ if (module->functions[i]->fast_jit_jitted_code) {
+ jit_code_cache_free(
+ module->functions[i]->fast_jit_jitted_code);
+ }
+#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ if (module->functions[i]->call_to_fast_jit_from_llvm_jit) {
+ jit_code_cache_free(
+ module->functions[i]->call_to_fast_jit_from_llvm_jit);
+ }
+#endif
+#endif
+ wasm_runtime_free(module->functions[i]);
+ }
+ }
+ wasm_runtime_free(module->functions);
+ }
+
+ if (module->tables)
+ wasm_runtime_free(module->tables);
+
+ if (module->memories)
+ wasm_runtime_free(module->memories);
+
+ if (module->globals)
+ wasm_runtime_free(module->globals);
+
+ if (module->exports)
+ wasm_runtime_free(module->exports);
+
+ if (module->table_segments) {
+ for (i = 0; i < module->table_seg_count; i++) {
+ if (module->table_segments[i].func_indexes)
+ wasm_runtime_free(module->table_segments[i].func_indexes);
+ }
+ wasm_runtime_free(module->table_segments);
+ }
+
+ if (module->data_segments) {
+ for (i = 0; i < module->data_seg_count; i++) {
+ if (module->data_segments[i])
+ wasm_runtime_free(module->data_segments[i]);
+ }
+ wasm_runtime_free(module->data_segments);
+ }
+
+ if (module->const_str_list) {
+ StringNode *node = module->const_str_list, *node_next;
+ while (node) {
+ node_next = node->next;
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ if (module->br_table_cache_list) {
+ BrTableCache *node = bh_list_first_elem(module->br_table_cache_list);
+ BrTableCache *node_next;
+ while (node) {
+ node_next = bh_list_elem_next(node);
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /* just release the sub module list */
+ if (module->import_module_list) {
+ WASMRegisteredModule *node =
+ bh_list_first_elem(module->import_module_list);
+ while (node) {
+ WASMRegisteredModule *next = bh_list_elem_next(node);
+ bh_list_remove(module->import_module_list, node);
+ /*
+ * unload(sub_module) will be trigged during runtime_destroy().
+ * every module in the global module list will be unloaded one by
+ * one. so don't worry.
+ */
+ wasm_runtime_free(node);
+ /*
+ * the module file reading buffer will be released
+ * in runtime_destroy()
+ */
+ node = next;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ WASMFastOPCodeNode *fast_opcode =
+ bh_list_first_elem(&module->fast_opcode_list);
+ while (fast_opcode) {
+ WASMFastOPCodeNode *next = bh_list_elem_next(fast_opcode);
+ wasm_runtime_free(fast_opcode);
+ fast_opcode = next;
+ }
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0 \
+ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0)
+ os_mutex_destroy(&module->instance_list_lock);
+#endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+ wasm_runtime_destroy_custom_sections(module->custom_section_list);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0
+ if (module->fast_jit_func_ptrs) {
+ wasm_runtime_free(module->fast_jit_func_ptrs);
+ }
+
+ for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) {
+ if (module->fast_jit_thread_locks_inited[i]) {
+ os_mutex_destroy(&module->fast_jit_thread_locks[i]);
+ }
+ }
+#endif
+
+ wasm_runtime_free(module);
+}
+
+bool
+wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
+ const uint8 *start_addr, const uint8 *code_end_addr,
+ uint8 label_type, uint8 **p_else_addr,
+ uint8 **p_end_addr)
+{
+ const uint8 *p = start_addr, *p_end = code_end_addr;
+ uint8 *else_addr = NULL;
+ char error_buf[128];
+ uint32 block_nested_depth = 1, count, i, j, t;
+ uint32 error_buf_size = sizeof(error_buf);
+ uint8 opcode, u8;
+ BlockAddr block_stack[16] = { { 0 } }, *block;
+
+ i = ((uintptr_t)start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
+ block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i;
+
+ for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) {
+ if (block[j].start_addr == start_addr) {
+ /* Cache hit */
+ *p_else_addr = block[j].else_addr;
+ *p_end_addr = block[j].end_addr;
+ return true;
+ }
+ }
+
+ /* Cache unhit */
+ block_stack[0].start_addr = start_addr;
+
+ while (p < code_end_addr) {
+ opcode = *p++;
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ op_break_retry:
+#endif
+ switch (opcode) {
+ case WASM_OP_UNREACHABLE:
+ case WASM_OP_NOP:
+ break;
+
+ case WASM_OP_BLOCK:
+ case WASM_OP_LOOP:
+ case WASM_OP_IF:
+ /* block result type: 0x40/0x7F/0x7E/0x7D/0x7C */
+ u8 = read_uint8(p);
+ if (block_nested_depth
+ < sizeof(block_stack) / sizeof(BlockAddr)) {
+ block_stack[block_nested_depth].start_addr = p;
+ block_stack[block_nested_depth].else_addr = NULL;
+ }
+ block_nested_depth++;
+ break;
+
+ case EXT_OP_BLOCK:
+ case EXT_OP_LOOP:
+ case EXT_OP_IF:
+ /* block type */
+ skip_leb_uint32(p, p_end);
+ if (block_nested_depth
+ < sizeof(block_stack) / sizeof(BlockAddr)) {
+ block_stack[block_nested_depth].start_addr = p;
+ block_stack[block_nested_depth].else_addr = NULL;
+ }
+ block_nested_depth++;
+ break;
+
+ case WASM_OP_ELSE:
+ if (label_type == LABEL_TYPE_IF && block_nested_depth == 1)
+ else_addr = (uint8 *)(p - 1);
+ if (block_nested_depth - 1
+ < sizeof(block_stack) / sizeof(BlockAddr))
+ block_stack[block_nested_depth - 1].else_addr =
+ (uint8 *)(p - 1);
+ break;
+
+ case WASM_OP_END:
+ if (block_nested_depth == 1) {
+ if (label_type == LABEL_TYPE_IF)
+ *p_else_addr = else_addr;
+ *p_end_addr = (uint8 *)(p - 1);
+
+ block_stack[0].end_addr = (uint8 *)(p - 1);
+ for (t = 0; t < sizeof(block_stack) / sizeof(BlockAddr);
+ t++) {
+ start_addr = block_stack[t].start_addr;
+ if (start_addr) {
+ i = ((uintptr_t)start_addr)
+ & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
+ block =
+ block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i;
+ for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++)
+ if (!block[j].start_addr)
+ break;
+
+ if (j == BLOCK_ADDR_CONFLICT_SIZE) {
+ memmove(block + 1, block,
+ (BLOCK_ADDR_CONFLICT_SIZE - 1)
+ * sizeof(BlockAddr));
+ j = 0;
+ }
+ block[j].start_addr = block_stack[t].start_addr;
+ block[j].else_addr = block_stack[t].else_addr;
+ block[j].end_addr = block_stack[t].end_addr;
+ }
+ else
+ break;
+ }
+ return true;
+ }
+ else {
+ block_nested_depth--;
+ if (block_nested_depth
+ < sizeof(block_stack) / sizeof(BlockAddr))
+ block_stack[block_nested_depth].end_addr =
+ (uint8 *)(p - 1);
+ }
+ break;
+
+ case WASM_OP_BR:
+ case WASM_OP_BR_IF:
+ skip_leb_uint32(p, p_end); /* labelidx */
+ break;
+
+ case WASM_OP_BR_TABLE:
+ read_leb_uint32(p, p_end, count); /* lable num */
+#if WASM_ENABLE_FAST_INTERP != 0
+ for (i = 0; i <= count; i++) /* lableidxs */
+ skip_leb_uint32(p, p_end);
+#else
+ p += count + 1;
+ while (*p == WASM_OP_NOP)
+ p++;
+#endif
+ break;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ case EXT_OP_BR_TABLE_CACHE:
+ read_leb_uint32(p, p_end, count); /* lable num */
+ while (*p == WASM_OP_NOP)
+ p++;
+ break;
+#endif
+
+ case WASM_OP_RETURN:
+ break;
+
+ case WASM_OP_CALL:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL:
+#endif
+ skip_leb_uint32(p, p_end); /* funcidx */
+ break;
+
+ case WASM_OP_CALL_INDIRECT:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL_INDIRECT:
+#endif
+ skip_leb_uint32(p, p_end); /* typeidx */
+ CHECK_BUF(p, p_end, 1);
+ u8 = read_uint8(p); /* 0x00 */
+ break;
+
+ case WASM_OP_DROP:
+ case WASM_OP_SELECT:
+ case WASM_OP_DROP_64:
+ case WASM_OP_SELECT_64:
+ break;
+
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_SELECT_T:
+ skip_leb_uint32(p, p_end); /* vec length */
+ CHECK_BUF(p, p_end, 1);
+ u8 = read_uint8(p); /* typeidx */
+ break;
+ case WASM_OP_TABLE_GET:
+ case WASM_OP_TABLE_SET:
+ skip_leb_uint32(p, p_end); /* table index */
+ break;
+ case WASM_OP_REF_NULL:
+ CHECK_BUF(p, p_end, 1);
+ u8 = read_uint8(p); /* type */
+ break;
+ case WASM_OP_REF_IS_NULL:
+ break;
+ case WASM_OP_REF_FUNC:
+ skip_leb_uint32(p, p_end); /* func index */
+ break;
+#endif /* WASM_ENABLE_REF_TYPES */
+ case WASM_OP_GET_LOCAL:
+ case WASM_OP_SET_LOCAL:
+ case WASM_OP_TEE_LOCAL:
+ case WASM_OP_GET_GLOBAL:
+ case WASM_OP_SET_GLOBAL:
+ case WASM_OP_GET_GLOBAL_64:
+ case WASM_OP_SET_GLOBAL_64:
+ case WASM_OP_SET_GLOBAL_AUX_STACK:
+ skip_leb_uint32(p, p_end); /* local index */
+ break;
+
+ case EXT_OP_GET_LOCAL_FAST:
+ case EXT_OP_SET_LOCAL_FAST:
+ case EXT_OP_TEE_LOCAL_FAST:
+ CHECK_BUF(p, p_end, 1);
+ p++;
+ break;
+
+ case WASM_OP_I32_LOAD:
+ case WASM_OP_I64_LOAD:
+ case WASM_OP_F32_LOAD:
+ case WASM_OP_F64_LOAD:
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ case WASM_OP_I64_LOAD8_S:
+ case WASM_OP_I64_LOAD8_U:
+ case WASM_OP_I64_LOAD16_S:
+ case WASM_OP_I64_LOAD16_U:
+ case WASM_OP_I64_LOAD32_S:
+ case WASM_OP_I64_LOAD32_U:
+ case WASM_OP_I32_STORE:
+ case WASM_OP_I64_STORE:
+ case WASM_OP_F32_STORE:
+ case WASM_OP_F64_STORE:
+ case WASM_OP_I32_STORE8:
+ case WASM_OP_I32_STORE16:
+ case WASM_OP_I64_STORE8:
+ case WASM_OP_I64_STORE16:
+ case WASM_OP_I64_STORE32:
+ skip_leb_uint32(p, p_end); /* align */
+ skip_leb_uint32(p, p_end); /* offset */
+ break;
+
+ case WASM_OP_MEMORY_SIZE:
+ case WASM_OP_MEMORY_GROW:
+ skip_leb_uint32(p, p_end); /* 0x00 */
+ break;
+
+ case WASM_OP_I32_CONST:
+ skip_leb_int32(p, p_end);
+ break;
+ case WASM_OP_I64_CONST:
+ skip_leb_int64(p, p_end);
+ break;
+ case WASM_OP_F32_CONST:
+ p += sizeof(float32);
+ break;
+ case WASM_OP_F64_CONST:
+ p += sizeof(float64);
+ 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:
+ 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:
+ 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:
+ 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:
+ case WASM_OP_I32_CLZ:
+ case WASM_OP_I32_CTZ:
+ case WASM_OP_I32_POPCNT:
+ 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:
+ case WASM_OP_I32_AND:
+ case WASM_OP_I32_OR:
+ case WASM_OP_I32_XOR:
+ 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:
+ case WASM_OP_I64_CLZ:
+ case WASM_OP_I64_CTZ:
+ case WASM_OP_I64_POPCNT:
+ 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:
+ case WASM_OP_I64_AND:
+ case WASM_OP_I64_OR:
+ case WASM_OP_I64_XOR:
+ 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:
+ 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:
+ 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:
+ case WASM_OP_F32_COPYSIGN:
+ 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:
+ 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:
+ case WASM_OP_F64_COPYSIGN:
+ case WASM_OP_I32_WRAP_I64:
+ case WASM_OP_I32_TRUNC_S_F32:
+ case WASM_OP_I32_TRUNC_U_F32:
+ case WASM_OP_I32_TRUNC_S_F64:
+ case WASM_OP_I32_TRUNC_U_F64:
+ case WASM_OP_I64_EXTEND_S_I32:
+ case WASM_OP_I64_EXTEND_U_I32:
+ case WASM_OP_I64_TRUNC_S_F32:
+ case WASM_OP_I64_TRUNC_U_F32:
+ case WASM_OP_I64_TRUNC_S_F64:
+ case WASM_OP_I64_TRUNC_U_F64:
+ case WASM_OP_F32_CONVERT_S_I32:
+ case WASM_OP_F32_CONVERT_U_I32:
+ case WASM_OP_F32_CONVERT_S_I64:
+ case WASM_OP_F32_CONVERT_U_I64:
+ case WASM_OP_F32_DEMOTE_F64:
+ case WASM_OP_F64_CONVERT_S_I32:
+ case WASM_OP_F64_CONVERT_U_I32:
+ case WASM_OP_F64_CONVERT_S_I64:
+ case WASM_OP_F64_CONVERT_U_I64:
+ case WASM_OP_F64_PROMOTE_F32:
+ case WASM_OP_I32_REINTERPRET_F32:
+ case WASM_OP_I64_REINTERPRET_F64:
+ case WASM_OP_F32_REINTERPRET_I32:
+ case WASM_OP_F64_REINTERPRET_I64:
+ case WASM_OP_I32_EXTEND8_S:
+ case WASM_OP_I32_EXTEND16_S:
+ case WASM_OP_I64_EXTEND8_S:
+ case WASM_OP_I64_EXTEND16_S:
+ case WASM_OP_I64_EXTEND32_S:
+ break;
+ case WASM_OP_MISC_PREFIX:
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(p, p_end, opcode1);
+
+ switch (opcode1) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ skip_leb_uint32(p, p_end);
+ /* skip memory idx */
+ p++;
+ break;
+ case WASM_OP_DATA_DROP:
+ skip_leb_uint32(p, p_end);
+ break;
+ case WASM_OP_MEMORY_COPY:
+ /* skip two memory idx */
+ p += 2;
+ break;
+ case WASM_OP_MEMORY_FILL:
+ /* skip memory idx */
+ p++;
+ break;
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ case WASM_OP_TABLE_COPY:
+ /* tableidx */
+ skip_leb_uint32(p, p_end);
+ /* elemidx */
+ skip_leb_uint32(p, p_end);
+ break;
+ case WASM_OP_ELEM_DROP:
+ /* elemidx */
+ skip_leb_uint32(p, p_end);
+ break;
+ case WASM_OP_TABLE_SIZE:
+ case WASM_OP_TABLE_GROW:
+ case WASM_OP_TABLE_FILL:
+ skip_leb_uint32(p, p_end); /* table idx */
+ break;
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ return false;
+ }
+ break;
+ }
+
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ case WASM_OP_SIMD_PREFIX:
+ {
+ /* TODO: shall we ceate a table to be friendly to branch
+ * prediction */
+ opcode = read_uint8(p);
+ /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h
+ */
+ switch (opcode) {
+ case SIMD_v128_load:
+ case SIMD_v128_load8x8_s:
+ case SIMD_v128_load8x8_u:
+ case SIMD_v128_load16x4_s:
+ case SIMD_v128_load16x4_u:
+ case SIMD_v128_load32x2_s:
+ case SIMD_v128_load32x2_u:
+ case SIMD_v128_load8_splat:
+ case SIMD_v128_load16_splat:
+ case SIMD_v128_load32_splat:
+ case SIMD_v128_load64_splat:
+ case SIMD_v128_store:
+ /* memarg align */
+ skip_leb_uint32(p, p_end);
+ /* memarg offset*/
+ skip_leb_uint32(p, p_end);
+ break;
+
+ case SIMD_v128_const:
+ case SIMD_v8x16_shuffle:
+ /* immByte[16] immLaneId[16] */
+ CHECK_BUF1(p, p_end, 16);
+ p += 16;
+ break;
+
+ case SIMD_i8x16_extract_lane_s:
+ case SIMD_i8x16_extract_lane_u:
+ case SIMD_i8x16_replace_lane:
+ case SIMD_i16x8_extract_lane_s:
+ case SIMD_i16x8_extract_lane_u:
+ case SIMD_i16x8_replace_lane:
+ case SIMD_i32x4_extract_lane:
+ case SIMD_i32x4_replace_lane:
+ case SIMD_i64x2_extract_lane:
+ case SIMD_i64x2_replace_lane:
+ case SIMD_f32x4_extract_lane:
+ case SIMD_f32x4_replace_lane:
+ case SIMD_f64x2_extract_lane:
+ case SIMD_f64x2_replace_lane:
+ /* ImmLaneId */
+ CHECK_BUF(p, p_end, 1);
+ p++;
+ break;
+
+ case SIMD_v128_load8_lane:
+ case SIMD_v128_load16_lane:
+ case SIMD_v128_load32_lane:
+ case SIMD_v128_load64_lane:
+ case SIMD_v128_store8_lane:
+ case SIMD_v128_store16_lane:
+ case SIMD_v128_store32_lane:
+ case SIMD_v128_store64_lane:
+ /* memarg align */
+ skip_leb_uint32(p, p_end);
+ /* memarg offset*/
+ skip_leb_uint32(p, p_end);
+ /* ImmLaneId */
+ CHECK_BUF(p, p_end, 1);
+ p++;
+ break;
+
+ case SIMD_v128_load32_zero:
+ case SIMD_v128_load64_zero:
+ /* memarg align */
+ skip_leb_uint32(p, p_end);
+ /* memarg offset*/
+ skip_leb_uint32(p, p_end);
+ break;
+
+ default:
+ /*
+ * since latest SIMD specific used almost every value
+ * from 0x00 to 0xff, the default branch will present
+ * all opcodes without imm
+ * https://github.com/WebAssembly/simd/blob/main/proposals/simd/NewOpcodes.md
+ */
+ break;
+ }
+ break;
+ }
+#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
+#endif /* end of WASM_ENABLE_SIMD */
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case WASM_OP_ATOMIC_PREFIX:
+ {
+ /* atomic_op (1 u8) + memarg (2 u32_leb) */
+ opcode = read_uint8(p);
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ skip_leb_uint32(p, p_end); /* align */
+ skip_leb_uint32(p, p_end); /* offset */
+ }
+ else {
+ /* atomic.fence doesn't have memarg */
+ p++;
+ }
+ break;
+ }
+#endif
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ case DEBUG_OP_BREAK:
+ {
+ WASMDebugInstance *debug_instance =
+ wasm_exec_env_get_instance(exec_env);
+ char orignal_opcode[1];
+ uint64 size = 1;
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ uint64 offset = (p - 1) >= module_inst->module->load_addr
+ ? (p - 1) - module_inst->module->load_addr
+ : ~0;
+ if (debug_instance) {
+ if (wasm_debug_instance_get_obj_mem(debug_instance, offset,
+ orignal_opcode, &size)
+ && size == 1) {
+ LOG_VERBOSE("WASM loader find OP_BREAK , recover it "
+ "with %02x: ",
+ orignal_opcode[0]);
+ opcode = orignal_opcode[0];
+ goto op_break_retry;
+ }
+ }
+ break;
+ }
+#endif
+
+ default:
+ return false;
+ }
+ }
+
+ (void)u8;
+ (void)exec_env;
+ return false;
+fail:
+ return false;
+}
+
+#define REF_ANY VALUE_TYPE_ANY
+#define REF_I32 VALUE_TYPE_I32
+#define REF_F32 VALUE_TYPE_F32
+#define REF_I64_1 VALUE_TYPE_I64
+#define REF_I64_2 VALUE_TYPE_I64
+#define REF_F64_1 VALUE_TYPE_F64
+#define REF_F64_2 VALUE_TYPE_F64
+#define REF_V128_1 VALUE_TYPE_V128
+#define REF_V128_2 VALUE_TYPE_V128
+#define REF_V128_3 VALUE_TYPE_V128
+#define REF_V128_4 VALUE_TYPE_V128
+#define REF_FUNCREF VALUE_TYPE_FUNCREF
+#define REF_EXTERNREF VALUE_TYPE_EXTERNREF
+
+#if WASM_ENABLE_FAST_INTERP != 0
+
+#if WASM_DEBUG_PREPROCESSOR != 0
+#define LOG_OP(...) os_printf(__VA_ARGS__)
+#else
+#define LOG_OP(...) (void)0
+#endif
+
+#define PATCH_ELSE 0
+#define PATCH_END 1
+typedef struct BranchBlockPatch {
+ struct BranchBlockPatch *next;
+ uint8 patch_type;
+ uint8 *code_compiled;
+} BranchBlockPatch;
+#endif
+
+typedef struct BranchBlock {
+ uint8 label_type;
+ BlockType block_type;
+ uint8 *start_addr;
+ uint8 *else_addr;
+ uint8 *end_addr;
+ uint32 stack_cell_num;
+#if WASM_ENABLE_FAST_INTERP != 0
+ uint16 dynamic_offset;
+ uint8 *code_compiled;
+ BranchBlockPatch *patch_list;
+ /* This is used to save params frame_offset of of if block */
+ int16 *param_frame_offsets;
+#endif
+
+ /* Indicate the operand stack is in polymorphic state.
+ * If the opcode is one of unreachable/br/br_table/return, stack is marked
+ * to polymorphic state until the block's 'end' opcode is processed.
+ * If stack is in polymorphic state and stack is empty, instruction can
+ * pop any type of value directly without decreasing stack top pointer
+ * and stack cell num. */
+ bool is_stack_polymorphic;
+} BranchBlock;
+
+typedef struct WASMLoaderContext {
+ /* frame ref stack */
+ uint8 *frame_ref;
+ uint8 *frame_ref_bottom;
+ uint8 *frame_ref_boundary;
+ uint32 frame_ref_size;
+ uint32 stack_cell_num;
+ uint32 max_stack_cell_num;
+
+ /* frame csp stack */
+ BranchBlock *frame_csp;
+ BranchBlock *frame_csp_bottom;
+ BranchBlock *frame_csp_boundary;
+ uint32 frame_csp_size;
+ uint32 csp_num;
+ uint32 max_csp_num;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* frame offset stack */
+ int16 *frame_offset;
+ int16 *frame_offset_bottom;
+ int16 *frame_offset_boundary;
+ uint32 frame_offset_size;
+ int16 dynamic_offset;
+ int16 start_dynamic_offset;
+ int16 max_dynamic_offset;
+
+ /* preserved local offset */
+ int16 preserved_local_offset;
+
+ /* const buffer */
+ uint8 *const_buf;
+ uint16 num_const;
+ uint16 const_cell_num;
+ uint32 const_buf_size;
+
+ /* processed code */
+ uint8 *p_code_compiled;
+ uint8 *p_code_compiled_end;
+ uint32 code_compiled_size;
+ /* If the last opcode will be dropped, the peak memory usage will be larger
+ * than the final code_compiled_size, we record the peak size to ensure
+ * there will not be invalid memory access during second traverse */
+ uint32 code_compiled_peak_size;
+#endif
+} WASMLoaderContext;
+
+typedef struct Const {
+ WASMValue value;
+ uint16 slot_index;
+ uint8 value_type;
+} Const;
+
+static void *
+memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 *mem_new;
+ bh_assert(size_new > size_old);
+ if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
+ bh_memcpy_s(mem_new, size_new, mem_old, size_old);
+ memset(mem_new + size_old, 0, size_new - size_old);
+ wasm_runtime_free(mem_old);
+ }
+ return mem_new;
+}
+
+#define MEM_REALLOC(mem, size_old, size_new) \
+ do { \
+ void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \
+ error_buf_size); \
+ if (!mem_new) \
+ goto fail; \
+ mem = mem_new; \
+ } while (0)
+
+#define CHECK_CSP_PUSH() \
+ do { \
+ if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
+ MEM_REALLOC( \
+ ctx->frame_csp_bottom, ctx->frame_csp_size, \
+ (uint32)(ctx->frame_csp_size + 8 * sizeof(BranchBlock))); \
+ ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \
+ ctx->frame_csp_boundary = \
+ ctx->frame_csp_bottom \
+ + ctx->frame_csp_size / sizeof(BranchBlock); \
+ ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \
+ } \
+ } while (0)
+
+#define CHECK_CSP_POP() \
+ do { \
+ if (ctx->csp_num < 1) { \
+ set_error_buf(error_buf, error_buf_size, \
+ "type mismatch: " \
+ "expect data but block stack was empty"); \
+ goto fail; \
+ } \
+ } while (0)
+
+#if WASM_ENABLE_FAST_INTERP != 0
+static bool
+check_offset_push(WASMLoaderContext *ctx, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 cell_num = (uint32)(ctx->frame_offset - ctx->frame_offset_bottom);
+ if (ctx->frame_offset >= ctx->frame_offset_boundary) {
+ MEM_REALLOC(ctx->frame_offset_bottom, ctx->frame_offset_size,
+ ctx->frame_offset_size + 16);
+ ctx->frame_offset_size += 16;
+ ctx->frame_offset_boundary =
+ ctx->frame_offset_bottom + ctx->frame_offset_size / sizeof(int16);
+ ctx->frame_offset = ctx->frame_offset_bottom + cell_num;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_offset_pop(WASMLoaderContext *ctx, uint32 cells)
+{
+ if (ctx->frame_offset - cells < ctx->frame_offset_bottom)
+ return false;
+ return true;
+}
+
+static void
+free_label_patch_list(BranchBlock *frame_csp)
+{
+ BranchBlockPatch *label_patch = frame_csp->patch_list;
+ BranchBlockPatch *next;
+ while (label_patch != NULL) {
+ next = label_patch->next;
+ wasm_runtime_free(label_patch);
+ label_patch = next;
+ }
+ frame_csp->patch_list = NULL;
+}
+
+static void
+free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
+{
+ BranchBlock *tmp_csp = frame_csp;
+
+ for (uint32 i = 0; i < csp_num; i++) {
+ free_label_patch_list(tmp_csp);
+ tmp_csp++;
+ }
+}
+
+#endif /* end of WASM_ENABLE_FAST_INTERP */
+
+static bool
+check_stack_push(WASMLoaderContext *ctx, char *error_buf, uint32 error_buf_size)
+{
+ if (ctx->frame_ref >= ctx->frame_ref_boundary) {
+ MEM_REALLOC(ctx->frame_ref_bottom, ctx->frame_ref_size,
+ ctx->frame_ref_size + 16);
+ ctx->frame_ref_size += 16;
+ ctx->frame_ref_boundary = ctx->frame_ref_bottom + ctx->frame_ref_size;
+ ctx->frame_ref = ctx->frame_ref_bottom + ctx->stack_cell_num;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type,
+ char *error_buf, uint32 error_buf_size)
+{
+ if ((is_32bit_type(type) && stack_cell_num < 1)
+ || (is_64bit_type(type) && stack_cell_num < 2)
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ || (type == VALUE_TYPE_V128 && stack_cell_num < 4)
+#endif
+#endif
+ ) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch: expect data but stack was empty");
+ return false;
+ }
+
+ if ((is_32bit_type(type) && *(frame_ref - 1) != type)
+ || (is_64bit_type(type)
+ && (*(frame_ref - 2) != type || *(frame_ref - 1) != type))
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ || (type == VALUE_TYPE_V128
+ && (*(frame_ref - 4) != REF_V128_1 || *(frame_ref - 3) != REF_V128_2
+ || *(frame_ref - 2) != REF_V128_3
+ || *(frame_ref - 1) != REF_V128_4))
+#endif
+#endif
+ ) {
+ set_error_buf_v(error_buf, error_buf_size, "%s%s%s",
+ "type mismatch: expect ", type2str(type),
+ " but got other");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+check_stack_pop(WASMLoaderContext *ctx, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ int32 block_stack_cell_num =
+ (int32)(ctx->stack_cell_num - (ctx->frame_csp - 1)->stack_cell_num);
+
+ if (block_stack_cell_num > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
+ /* the stack top is a value of any type, return success */
+ return true;
+ }
+
+ if (!check_stack_top_values(ctx->frame_ref, block_stack_cell_num, type,
+ error_buf, error_buf_size))
+ return false;
+
+ return true;
+}
+
+static void
+wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
+{
+ if (ctx) {
+ if (ctx->frame_ref_bottom)
+ wasm_runtime_free(ctx->frame_ref_bottom);
+ if (ctx->frame_csp_bottom) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
+#endif
+ wasm_runtime_free(ctx->frame_csp_bottom);
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (ctx->frame_offset_bottom)
+ wasm_runtime_free(ctx->frame_offset_bottom);
+ if (ctx->const_buf)
+ wasm_runtime_free(ctx->const_buf);
+#endif
+ wasm_runtime_free(ctx);
+ }
+}
+
+static WASMLoaderContext *
+wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size)
+{
+ WASMLoaderContext *loader_ctx =
+ loader_malloc(sizeof(WASMLoaderContext), error_buf, error_buf_size);
+ if (!loader_ctx)
+ return NULL;
+
+ loader_ctx->frame_ref_size = 32;
+ if (!(loader_ctx->frame_ref_bottom = loader_ctx->frame_ref = loader_malloc(
+ loader_ctx->frame_ref_size, error_buf, error_buf_size)))
+ goto fail;
+ loader_ctx->frame_ref_boundary = loader_ctx->frame_ref_bottom + 32;
+
+ loader_ctx->frame_csp_size = sizeof(BranchBlock) * 8;
+ if (!(loader_ctx->frame_csp_bottom = loader_ctx->frame_csp = loader_malloc(
+ loader_ctx->frame_csp_size, error_buf, error_buf_size)))
+ goto fail;
+ loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ loader_ctx->frame_offset_size = sizeof(int16) * 32;
+ if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset =
+ loader_malloc(loader_ctx->frame_offset_size, error_buf,
+ error_buf_size)))
+ goto fail;
+ loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32;
+
+ loader_ctx->num_const = 0;
+ loader_ctx->const_buf_size = sizeof(Const) * 8;
+ if (!(loader_ctx->const_buf = loader_malloc(loader_ctx->const_buf_size,
+ error_buf, error_buf_size)))
+ goto fail;
+
+ if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) {
+ set_error_buf(error_buf, error_buf_size,
+ "fast interpreter offset overflow");
+ goto fail;
+ }
+
+ loader_ctx->start_dynamic_offset = loader_ctx->dynamic_offset =
+ loader_ctx->max_dynamic_offset =
+ func->param_cell_num + func->local_cell_num;
+#endif
+ return loader_ctx;
+
+fail:
+ wasm_loader_ctx_destroy(loader_ctx);
+ return NULL;
+}
+
+static bool
+wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ if (!check_stack_push(ctx, error_buf, error_buf_size))
+ return false;
+
+ *ctx->frame_ref++ = type;
+ ctx->stack_cell_num++;
+ if (is_32bit_type(type) || type == VALUE_TYPE_ANY)
+ goto check_stack_and_return;
+
+ if (!check_stack_push(ctx, error_buf, error_buf_size))
+ return false;
+
+ *ctx->frame_ref++ = type;
+ ctx->stack_cell_num++;
+
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ if (type == VALUE_TYPE_V128) {
+ if (!check_stack_push(ctx, error_buf, error_buf_size))
+ return false;
+ *ctx->frame_ref++ = type;
+ ctx->stack_cell_num++;
+ if (!check_stack_push(ctx, error_buf, error_buf_size))
+ return false;
+ *ctx->frame_ref++ = type;
+ ctx->stack_cell_num++;
+ }
+#endif
+#endif
+
+check_stack_and_return:
+ if (ctx->stack_cell_num > ctx->max_stack_cell_num) {
+ ctx->max_stack_cell_num = ctx->stack_cell_num;
+ if (ctx->max_stack_cell_num > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "operand stack depth limit exceeded");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ BranchBlock *cur_block = ctx->frame_csp - 1;
+ int32 available_stack_cell =
+ (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
+
+ /* Directly return success if current block is in stack
+ * polymorphic state while stack is empty. */
+ if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
+ return true;
+
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ if (!check_stack_pop(ctx, type, error_buf, error_buf_size))
+ return false;
+
+ ctx->frame_ref--;
+ ctx->stack_cell_num--;
+
+ if (is_32bit_type(type) || *ctx->frame_ref == VALUE_TYPE_ANY)
+ return true;
+
+ ctx->frame_ref--;
+ ctx->stack_cell_num--;
+
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ if (type == VALUE_TYPE_V128) {
+ ctx->frame_ref -= 2;
+ ctx->stack_cell_num -= 2;
+ }
+#endif
+#endif
+ return true;
+}
+
+static bool
+wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
+ uint8 type_push, uint8 type_pop, char *error_buf,
+ uint32 error_buf_size)
+{
+ for (int i = 0; i < pop_cnt; i++) {
+ if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf,
+ error_buf_size))
+ return false;
+ }
+ if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size))
+ return false;
+ return true;
+}
+
+static bool
+wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type,
+ BlockType block_type, uint8 *start_addr,
+ char *error_buf, uint32 error_buf_size)
+{
+ CHECK_CSP_PUSH();
+ memset(ctx->frame_csp, 0, sizeof(BranchBlock));
+ ctx->frame_csp->label_type = label_type;
+ ctx->frame_csp->block_type = block_type;
+ ctx->frame_csp->start_addr = start_addr;
+ ctx->frame_csp->stack_cell_num = ctx->stack_cell_num;
+#if WASM_ENABLE_FAST_INTERP != 0
+ ctx->frame_csp->dynamic_offset = ctx->dynamic_offset;
+ ctx->frame_csp->patch_list = NULL;
+#endif
+ ctx->frame_csp++;
+ ctx->csp_num++;
+ if (ctx->csp_num > ctx->max_csp_num) {
+ ctx->max_csp_num = ctx->csp_num;
+ if (ctx->max_csp_num > UINT16_MAX) {
+ set_error_buf(error_buf, error_buf_size,
+ "label stack depth limit exceeded");
+ return false;
+ }
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf,
+ uint32 error_buf_size)
+{
+ CHECK_CSP_POP();
+#if WASM_ENABLE_FAST_INTERP != 0
+ if ((ctx->frame_csp - 1)->param_frame_offsets)
+ wasm_runtime_free((ctx->frame_csp - 1)->param_frame_offsets);
+#endif
+ ctx->frame_csp--;
+ ctx->csp_num--;
+
+ return true;
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_FAST_INTERP != 0
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define emit_label(opcode) \
+ do { \
+ wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \
+ LOG_OP("\nemit_op [%02x]\t", opcode); \
+ } while (0)
+#define skip_label() \
+ do { \
+ wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \
+ LOG_OP("\ndelete last op\n"); \
+ } while (0)
+#else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#define emit_label(opcode) \
+ do { \
+ int32 offset = \
+ (int32)((uint8 *)handle_table[opcode] - (uint8 *)handle_table[0]); \
+ if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \
+ set_error_buf(error_buf, error_buf_size, \
+ "pre-compiled label offset out of range"); \
+ goto fail; \
+ } \
+ wasm_loader_emit_int16(loader_ctx, offset); \
+ LOG_OP("\nemit_op [%02x]\t", opcode); \
+ } while (0)
+#define skip_label() \
+ do { \
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \
+ LOG_OP("\ndelete last op\n"); \
+ } while (0)
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#define emit_label(opcode) \
+ do { \
+ wasm_loader_emit_uint8(loader_ctx, opcode); \
+ LOG_OP("\nemit_op [%02x]\t", opcode); \
+ } while (0)
+#define skip_label() \
+ do { \
+ wasm_loader_emit_backspace(loader_ctx, sizeof(uint8)); \
+ LOG_OP("\ndelete last op\n"); \
+ } while (0)
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+
+#define emit_empty_label_addr_and_frame_ip(type) \
+ do { \
+ if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \
+ loader_ctx->p_code_compiled, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ /* label address, to be patched */ \
+ wasm_loader_emit_ptr(loader_ctx, NULL); \
+ } while (0)
+
+#define emit_br_info(frame_csp) \
+ do { \
+ if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define LAST_OP_OUTPUT_I32() \
+ (last_op >= WASM_OP_I32_EQZ && last_op <= WASM_OP_I32_ROTR) \
+ || (last_op == WASM_OP_I32_LOAD || last_op == WASM_OP_F32_LOAD) \
+ || (last_op >= WASM_OP_I32_LOAD8_S && last_op <= WASM_OP_I32_LOAD16_U) \
+ || (last_op >= WASM_OP_F32_ABS && last_op <= WASM_OP_F32_COPYSIGN) \
+ || (last_op >= WASM_OP_I32_WRAP_I64 \
+ && last_op <= WASM_OP_I32_TRUNC_U_F64) \
+ || (last_op >= WASM_OP_F32_CONVERT_S_I32 \
+ && last_op <= WASM_OP_F32_DEMOTE_F64) \
+ || (last_op == WASM_OP_I32_REINTERPRET_F32) \
+ || (last_op == WASM_OP_F32_REINTERPRET_I32) \
+ || (last_op == EXT_OP_COPY_STACK_TOP)
+
+#define LAST_OP_OUTPUT_I64() \
+ (last_op >= WASM_OP_I64_CLZ && last_op <= WASM_OP_I64_ROTR) \
+ || (last_op >= WASM_OP_F64_ABS && last_op <= WASM_OP_F64_COPYSIGN) \
+ || (last_op == WASM_OP_I64_LOAD || last_op == WASM_OP_F64_LOAD) \
+ || (last_op >= WASM_OP_I64_LOAD8_S && last_op <= WASM_OP_I64_LOAD32_U) \
+ || (last_op >= WASM_OP_I64_EXTEND_S_I32 \
+ && last_op <= WASM_OP_I64_TRUNC_U_F64) \
+ || (last_op >= WASM_OP_F64_CONVERT_S_I32 \
+ && last_op <= WASM_OP_F64_PROMOTE_F32) \
+ || (last_op == WASM_OP_I64_REINTERPRET_F64) \
+ || (last_op == WASM_OP_F64_REINTERPRET_I64) \
+ || (last_op == EXT_OP_COPY_STACK_TOP_I64)
+
+#define GET_CONST_OFFSET(type, val) \
+ do { \
+ if (!(wasm_loader_get_const_offset(loader_ctx, type, &val, \
+ &operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define GET_CONST_F32_OFFSET(type, fval) \
+ do { \
+ if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \
+ &operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define GET_CONST_F64_OFFSET(type, fval) \
+ do { \
+ if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \
+ &operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define emit_operand(ctx, offset) \
+ do { \
+ wasm_loader_emit_int16(ctx, offset); \
+ LOG_OP("%d\t", offset); \
+ } while (0)
+
+#define emit_byte(ctx, byte) \
+ do { \
+ wasm_loader_emit_uint8(ctx, byte); \
+ LOG_OP("%d\t", byte); \
+ } while (0)
+
+#define emit_uint32(ctx, value) \
+ do { \
+ wasm_loader_emit_uint32(ctx, value); \
+ LOG_OP("%d\t", value); \
+ } while (0)
+
+#define emit_uint64(ctx, value) \
+ do { \
+ wasm_loader_emit_const(ctx, &value, false); \
+ LOG_OP("%lld\t", value); \
+ } while (0)
+
+#define emit_float32(ctx, value) \
+ do { \
+ wasm_loader_emit_const(ctx, &value, true); \
+ LOG_OP("%f\t", value); \
+ } while (0)
+
+#define emit_float64(ctx, value) \
+ do { \
+ wasm_loader_emit_const(ctx, &value, false); \
+ LOG_OP("%f\t", value); \
+ } while (0)
+
+static bool
+wasm_loader_ctx_reinit(WASMLoaderContext *ctx)
+{
+ if (!(ctx->p_code_compiled =
+ loader_malloc(ctx->code_compiled_peak_size, NULL, 0)))
+ return false;
+ ctx->p_code_compiled_end =
+ ctx->p_code_compiled + ctx->code_compiled_peak_size;
+
+ /* clean up frame ref */
+ memset(ctx->frame_ref_bottom, 0, ctx->frame_ref_size);
+ ctx->frame_ref = ctx->frame_ref_bottom;
+ ctx->stack_cell_num = 0;
+
+ /* clean up frame csp */
+ memset(ctx->frame_csp_bottom, 0, ctx->frame_csp_size);
+ ctx->frame_csp = ctx->frame_csp_bottom;
+ ctx->csp_num = 0;
+ ctx->max_csp_num = 0;
+
+ /* clean up frame offset */
+ memset(ctx->frame_offset_bottom, 0, ctx->frame_offset_size);
+ ctx->frame_offset = ctx->frame_offset_bottom;
+ ctx->dynamic_offset = ctx->start_dynamic_offset;
+
+ /* init preserved local offsets */
+ ctx->preserved_local_offset = ctx->max_dynamic_offset;
+
+ /* const buf is reserved */
+ return true;
+}
+
+static void
+increase_compiled_code_space(WASMLoaderContext *ctx, int32 size)
+{
+ ctx->code_compiled_size += size;
+ if (ctx->code_compiled_size >= ctx->code_compiled_peak_size) {
+ ctx->code_compiled_peak_size = ctx->code_compiled_size;
+ }
+}
+
+static void
+wasm_loader_emit_const(WASMLoaderContext *ctx, void *value, bool is_32_bit)
+{
+ uint32 size = is_32_bit ? sizeof(uint32) : sizeof(uint64);
+
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ bh_memcpy_s(ctx->p_code_compiled,
+ (uint32)(ctx->p_code_compiled_end - ctx->p_code_compiled),
+ value, size);
+ ctx->p_code_compiled += size;
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, size);
+ }
+}
+
+static void
+wasm_loader_emit_uint32(WASMLoaderContext *ctx, uint32 value)
+{
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ STORE_U32(ctx->p_code_compiled, value);
+ ctx->p_code_compiled += sizeof(uint32);
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, sizeof(uint32));
+ }
+}
+
+static void
+wasm_loader_emit_int16(WASMLoaderContext *ctx, int16 value)
+{
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ STORE_U16(ctx->p_code_compiled, (uint16)value);
+ ctx->p_code_compiled += sizeof(int16);
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, sizeof(uint16));
+ }
+}
+
+static void
+wasm_loader_emit_uint8(WASMLoaderContext *ctx, uint8 value)
+{
+ if (ctx->p_code_compiled) {
+ *(ctx->p_code_compiled) = value;
+ ctx->p_code_compiled += sizeof(uint8);
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ ctx->p_code_compiled++;
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ }
+ else {
+ increase_compiled_code_space(ctx, sizeof(uint8));
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ increase_compiled_code_space(ctx, sizeof(uint8));
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ }
+}
+
+static void
+wasm_loader_emit_ptr(WASMLoaderContext *ctx, void *value)
+{
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ STORE_PTR(ctx->p_code_compiled, value);
+ ctx->p_code_compiled += sizeof(void *);
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, sizeof(void *));
+ }
+}
+
+static void
+wasm_loader_emit_backspace(WASMLoaderContext *ctx, uint32 size)
+{
+ if (ctx->p_code_compiled) {
+ ctx->p_code_compiled -= size;
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ if (size == sizeof(uint8)) {
+ ctx->p_code_compiled--;
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+ }
+#endif
+ }
+ else {
+ ctx->code_compiled_size -= size;
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ if (size == sizeof(uint8)) {
+ ctx->code_compiled_size--;
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+ }
+#endif
+ }
+}
+
+static bool
+preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
+ uint32 local_index, uint32 local_type,
+ bool *preserved, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 i = 0;
+ int16 preserved_offset = (int16)local_index;
+
+ *preserved = false;
+ while (i < loader_ctx->stack_cell_num) {
+ uint8 cur_type = loader_ctx->frame_ref_bottom[i];
+
+ /* move previous local into dynamic space before a set/tee_local opcode
+ */
+ if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) {
+ if (!(*preserved)) {
+ *preserved = true;
+ skip_label();
+ preserved_offset = loader_ctx->preserved_local_offset;
+ if (loader_ctx->p_code_compiled) {
+ bh_assert(preserved_offset != (int16)local_index);
+ }
+ if (is_32bit_type(local_type)) {
+ /* Only increase preserve offset in the second traversal */
+ if (loader_ctx->p_code_compiled)
+ loader_ctx->preserved_local_offset++;
+ emit_label(EXT_OP_COPY_STACK_TOP);
+ }
+ else {
+ if (loader_ctx->p_code_compiled)
+ loader_ctx->preserved_local_offset += 2;
+ emit_label(EXT_OP_COPY_STACK_TOP_I64);
+ }
+ emit_operand(loader_ctx, local_index);
+ emit_operand(loader_ctx, preserved_offset);
+ emit_label(opcode);
+ }
+ loader_ctx->frame_offset_bottom[i] = preserved_offset;
+ }
+
+ if (is_32bit_type(cur_type))
+ i++;
+ else
+ i += 2;
+ }
+
+ (void)error_buf;
+ (void)error_buf_size;
+ return true;
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+fail:
+ return false;
+#endif
+#endif
+}
+
+static bool
+preserve_local_for_block(WASMLoaderContext *loader_ctx, uint8 opcode,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint32 i = 0;
+ bool preserve_local;
+
+ /* preserve locals before blocks to ensure that "tee/set_local" inside
+ blocks will not influence the value of these locals */
+ while (i < loader_ctx->stack_cell_num) {
+ int16 cur_offset = loader_ctx->frame_offset_bottom[i];
+ uint8 cur_type = loader_ctx->frame_ref_bottom[i];
+
+ if ((cur_offset < loader_ctx->start_dynamic_offset)
+ && (cur_offset >= 0)) {
+ if (!(preserve_referenced_local(loader_ctx, opcode, cur_offset,
+ cur_type, &preserve_local,
+ error_buf, error_buf_size)))
+ return false;
+ }
+
+ if (is_32bit_type(cur_type)) {
+ i++;
+ }
+ else {
+ i += 2;
+ }
+ }
+
+ return true;
+}
+
+static bool
+add_label_patch_to_list(BranchBlock *frame_csp, uint8 patch_type,
+ uint8 *p_code_compiled, char *error_buf,
+ uint32 error_buf_size)
+{
+ BranchBlockPatch *patch =
+ loader_malloc(sizeof(BranchBlockPatch), error_buf, error_buf_size);
+ if (!patch) {
+ return false;
+ }
+ patch->patch_type = patch_type;
+ patch->code_compiled = p_code_compiled;
+ if (!frame_csp->patch_list) {
+ frame_csp->patch_list = patch;
+ patch->next = NULL;
+ }
+ else {
+ patch->next = frame_csp->patch_list;
+ frame_csp->patch_list = patch;
+ }
+ return true;
+}
+
+static void
+apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type)
+{
+ BranchBlock *frame_csp = ctx->frame_csp - depth;
+ BranchBlockPatch *node = frame_csp->patch_list;
+ BranchBlockPatch *node_prev = NULL, *node_next;
+
+ if (!ctx->p_code_compiled)
+ return;
+
+ while (node) {
+ node_next = node->next;
+ if (node->patch_type == patch_type) {
+ STORE_PTR(node->code_compiled, ctx->p_code_compiled);
+ if (node_prev == NULL) {
+ frame_csp->patch_list = node_next;
+ }
+ else {
+ node_prev->next = node_next;
+ }
+ wasm_runtime_free(node);
+ }
+ else {
+ node_prev = node;
+ }
+ node = node_next;
+ }
+}
+
+static bool
+wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
+ char *error_buf, uint32 error_buf_size)
+{
+ /* br info layout:
+ * a) arity of target block
+ * b) total cell num of arity values
+ * c) each arity value's cell num
+ * d) each arity value's src frame offset
+ * e) each arity values's dst dynamic offset
+ * f) branch target address
+ *
+ * Note: b-e are omitted when arity is 0 so that
+ * interpreter can recover the br info quickly.
+ */
+ BlockType *block_type = &frame_csp->block_type;
+ uint8 *types = NULL, cell;
+ uint32 arity = 0;
+ int32 i;
+ int16 *frame_offset = ctx->frame_offset;
+ uint16 dynamic_offset;
+
+ /* Note: loop's arity is different from if and block. loop's arity is
+ * its parameter count while if and block arity is result count.
+ */
+ if (frame_csp->label_type == LABEL_TYPE_LOOP)
+ arity = block_type_get_param_types(block_type, &types);
+ else
+ arity = block_type_get_result_types(block_type, &types);
+
+ /* Part a */
+ emit_uint32(ctx, arity);
+
+ if (arity) {
+ /* Part b */
+ emit_uint32(ctx, wasm_get_cell_num(types, arity));
+ /* Part c */
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ cell = (uint8)wasm_value_type_cell_num(types[i]);
+ emit_byte(ctx, cell);
+ }
+ /* Part d */
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ cell = (uint8)wasm_value_type_cell_num(types[i]);
+ frame_offset -= cell;
+ emit_operand(ctx, *(int16 *)(frame_offset));
+ }
+ /* Part e */
+ dynamic_offset =
+ frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ cell = (uint8)wasm_value_type_cell_num(types[i]);
+ dynamic_offset -= cell;
+ emit_operand(ctx, dynamic_offset);
+ }
+ }
+
+ /* Part f */
+ if (frame_csp->label_type == LABEL_TYPE_LOOP) {
+ wasm_loader_emit_ptr(ctx, frame_csp->code_compiled);
+ }
+ else {
+ if (!add_label_patch_to_list(frame_csp, PATCH_END, ctx->p_code_compiled,
+ error_buf, error_buf_size))
+ return false;
+ /* label address, to be patched */
+ wasm_loader_emit_ptr(ctx, NULL);
+ }
+
+ return true;
+}
+
+static bool
+wasm_loader_push_frame_offset(WASMLoaderContext *ctx, uint8 type,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ /* only check memory overflow in first traverse */
+ if (ctx->p_code_compiled == NULL) {
+ if (!check_offset_push(ctx, error_buf, error_buf_size))
+ return false;
+ }
+
+ if (disable_emit)
+ *(ctx->frame_offset)++ = operand_offset;
+ else {
+ emit_operand(ctx, ctx->dynamic_offset);
+ *(ctx->frame_offset)++ = ctx->dynamic_offset;
+ ctx->dynamic_offset++;
+ if (ctx->dynamic_offset > ctx->max_dynamic_offset) {
+ ctx->max_dynamic_offset = ctx->dynamic_offset;
+ if (ctx->max_dynamic_offset >= INT16_MAX) {
+ goto fail;
+ }
+ }
+ }
+
+ if (is_32bit_type(type))
+ return true;
+
+ if (ctx->p_code_compiled == NULL) {
+ if (!check_offset_push(ctx, error_buf, error_buf_size))
+ return false;
+ }
+
+ ctx->frame_offset++;
+ if (!disable_emit) {
+ ctx->dynamic_offset++;
+ if (ctx->dynamic_offset > ctx->max_dynamic_offset) {
+ ctx->max_dynamic_offset = ctx->dynamic_offset;
+ if (ctx->max_dynamic_offset >= INT16_MAX) {
+ goto fail;
+ }
+ }
+ }
+ return true;
+
+fail:
+ set_error_buf(error_buf, error_buf_size,
+ "fast interpreter offset overflow");
+ return false;
+}
+
+/* This function should be in front of wasm_loader_pop_frame_ref
+ as they both use ctx->stack_cell_num, and ctx->stack_cell_num
+ will be modified by wasm_loader_pop_frame_ref */
+static bool
+wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
+ char *error_buf, uint32 error_buf_size)
+{
+ /* if ctx->frame_csp equals ctx->frame_csp_bottom,
+ then current block is the function block */
+ uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
+ BranchBlock *cur_block = ctx->frame_csp - depth;
+ int32 available_stack_cell =
+ (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
+
+ /* Directly return success if current block is in stack
+ * polymorphic state while stack is empty. */
+ if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
+ return true;
+
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ if (is_32bit_type(type)) {
+ /* Check the offset stack bottom to ensure the frame offset
+ stack will not go underflow. But we don't thrown error
+ and return true here, because the error msg should be
+ given in wasm_loader_pop_frame_ref */
+ if (!check_offset_pop(ctx, 1))
+ return true;
+
+ ctx->frame_offset -= 1;
+ if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+ && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
+ ctx->dynamic_offset -= 1;
+ }
+ else {
+ if (!check_offset_pop(ctx, 2))
+ return true;
+
+ ctx->frame_offset -= 2;
+ if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+ && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
+ ctx->dynamic_offset -= 2;
+ }
+ emit_operand(ctx, *(ctx->frame_offset));
+
+ (void)error_buf;
+ (void)error_buf_size;
+ return true;
+}
+
+static bool
+wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
+ uint8 type_push, uint8 type_pop,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint8 i;
+
+ for (i = 0; i < pop_cnt; i++) {
+ if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf,
+ error_buf_size))
+ return false;
+ }
+ if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit,
+ operand_offset, error_buf,
+ error_buf_size))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (!(wasm_loader_push_frame_offset(ctx, type, disable_emit, operand_offset,
+ error_buf, error_buf_size)))
+ return false;
+ if (!(wasm_loader_push_frame_ref(ctx, type, error_buf, error_buf_size)))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
+ char *error_buf, uint32 error_buf_size)
+{
+ /* put wasm_loader_pop_frame_offset in front of wasm_loader_pop_frame_ref */
+ if (!wasm_loader_pop_frame_offset(ctx, type, error_buf, error_buf_size))
+ return false;
+ if (!wasm_loader_pop_frame_ref(ctx, type, error_buf, error_buf_size))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
+ uint8 type_push, uint8 type_pop,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop,
+ disable_emit, operand_offset,
+ error_buf, error_buf_size))
+ return false;
+ if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop,
+ error_buf, error_buf_size))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
+ int16 *offset, char *error_buf,
+ uint32 error_buf_size)
+{
+ int8 bytes_to_increase;
+ int16 operand_offset = 0;
+ Const *c;
+
+ /* Search existing constant */
+ for (c = (Const *)ctx->const_buf;
+ (uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) {
+ /* TODO: handle v128 type? */
+ if ((type == c->value_type)
+ && ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64)
+ || (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32)
+#if WASM_ENABLE_REF_TYPES != 0
+ || (type == VALUE_TYPE_FUNCREF
+ && *(int32 *)value == c->value.i32)
+ || (type == VALUE_TYPE_EXTERNREF
+ && *(int32 *)value == c->value.i32)
+#endif
+ || (type == VALUE_TYPE_F64
+ && (0 == memcmp(value, &(c->value.f64), sizeof(float64))))
+ || (type == VALUE_TYPE_F32
+ && (0
+ == memcmp(value, &(c->value.f32), sizeof(float32)))))) {
+ operand_offset = c->slot_index;
+ break;
+ }
+ if (is_32bit_type(c->value_type))
+ operand_offset += 1;
+ else
+ operand_offset += 2;
+ }
+
+ if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) {
+ /* New constant, append to the const buffer */
+ if ((type == VALUE_TYPE_F64) || (type == VALUE_TYPE_I64)) {
+ bytes_to_increase = 2;
+ }
+ else {
+ bytes_to_increase = 1;
+ }
+
+ /* The max cell num of const buffer is 32768 since the valid index range
+ * is -32768 ~ -1. Return an invalid index 0 to indicate the buffer is
+ * full */
+ if (ctx->const_cell_num > INT16_MAX - bytes_to_increase + 1) {
+ *offset = 0;
+ return true;
+ }
+
+ if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) {
+ MEM_REALLOC(ctx->const_buf, ctx->const_buf_size,
+ ctx->const_buf_size + 4 * sizeof(Const));
+ ctx->const_buf_size += 4 * sizeof(Const);
+ c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const));
+ }
+ c->value_type = type;
+ switch (type) {
+ case VALUE_TYPE_F64:
+ bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value,
+ sizeof(float64));
+ ctx->const_cell_num += 2;
+ /* The const buf will be reversed, we use the second cell */
+ /* of the i64/f64 const so the finnal offset is corrent */
+ operand_offset++;
+ break;
+ case VALUE_TYPE_I64:
+ c->value.i64 = *(int64 *)value;
+ ctx->const_cell_num += 2;
+ operand_offset++;
+ break;
+ case VALUE_TYPE_F32:
+ bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value,
+ sizeof(float32));
+ ctx->const_cell_num++;
+ break;
+ case VALUE_TYPE_I32:
+ c->value.i32 = *(int32 *)value;
+ ctx->const_cell_num++;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+ c->value.i32 = *(int32 *)value;
+ ctx->const_cell_num++;
+ break;
+#endif
+ default:
+ break;
+ }
+ c->slot_index = operand_offset;
+ ctx->num_const++;
+ LOG_OP("#### new const [%d]: %ld\n", ctx->num_const,
+ (int64)c->value.i64);
+ }
+ /* use negetive index for const */
+ operand_offset = -(operand_offset + 1);
+ *offset = operand_offset;
+ return true;
+fail:
+ return false;
+}
+
+/*
+ PUSH(POP)_XXX = push(pop) frame_ref + push(pop) frame_offset
+ -- Mostly used for the binary / compare operation
+ PUSH(POP)_OFFSET_TYPE only push(pop) the frame_offset stack
+ -- Mostly used in block / control instructions
+
+ The POP will always emit the offset on the top of the frame_offset stack
+ PUSH can be used in two ways:
+ 1. directly PUSH:
+ PUSH_XXX();
+ will allocate a dynamic space and emit
+ 2. silent PUSH:
+ operand_offset = xxx; disable_emit = true;
+ PUSH_XXX();
+ only push the frame_offset stack, no emit
+*/
+
+#define TEMPLATE_PUSH(Type) \
+ do { \
+ if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_##Type, \
+ disable_emit, operand_offset, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define TEMPLATE_POP(Type) \
+ do { \
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_##Type, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_OFFSET_TYPE(type) \
+ do { \
+ if (!(wasm_loader_push_frame_offset(loader_ctx, type, disable_emit, \
+ operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_OFFSET_TYPE(type) \
+ do { \
+ if (!(wasm_loader_pop_frame_offset(loader_ctx, type, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref_offset( \
+ loader_ctx, 1, type_push, type_pop, disable_emit, \
+ operand_offset, error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+/* type of POPs should be the same */
+#define POP2_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref_offset( \
+ loader_ctx, 2, type_push, type_pop, disable_emit, \
+ operand_offset, error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#else /* WASM_ENABLE_FAST_INTERP */
+
+#define TEMPLATE_PUSH(Type) \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_##Type, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define TEMPLATE_POP(Type) \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_##Type, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \
+ type_pop, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+/* type of POPs should be the same */
+#define POP2_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2, type_push, \
+ type_pop, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+#endif /* WASM_ENABLE_FAST_INTERP */
+
+#define PUSH_I32() TEMPLATE_PUSH(I32)
+#define PUSH_F32() TEMPLATE_PUSH(F32)
+#define PUSH_I64() TEMPLATE_PUSH(I64)
+#define PUSH_F64() TEMPLATE_PUSH(F64)
+#define PUSH_V128() TEMPLATE_PUSH(V128)
+#define PUSH_FUNCREF() TEMPLATE_PUSH(FUNCREF)
+#define PUSH_EXTERNREF() TEMPLATE_PUSH(EXTERNREF)
+
+#define POP_I32() TEMPLATE_POP(I32)
+#define POP_F32() TEMPLATE_POP(F32)
+#define POP_I64() TEMPLATE_POP(I64)
+#define POP_F64() TEMPLATE_POP(F64)
+#define POP_V128() TEMPLATE_POP(V128)
+#define POP_FUNCREF() TEMPLATE_POP(FUNCREF)
+#define POP_EXTERNREF() TEMPLATE_POP(EXTERNREF)
+
+#if WASM_ENABLE_FAST_INTERP != 0
+
+static bool
+reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode,
+ bool disable_emit, char *error_buf, uint32 error_buf_size)
+{
+ int16 operand_offset = 0;
+ BranchBlock *block = (opcode == WASM_OP_ELSE) ? loader_ctx->frame_csp - 1
+ : loader_ctx->frame_csp;
+ BlockType *block_type = &block->block_type;
+ uint8 *return_types = NULL;
+ uint32 return_count = 0, value_count = 0, total_cel_num = 0;
+ int32 i = 0;
+ int16 dynamic_offset, dynamic_offset_org, *frame_offset = NULL,
+ *frame_offset_org = NULL;
+
+ return_count = block_type_get_result_types(block_type, &return_types);
+
+ /* If there is only one return value, use EXT_OP_COPY_STACK_TOP/_I64 instead
+ * of EXT_OP_COPY_STACK_VALUES for interpreter performance. */
+ if (return_count == 1) {
+ uint8 cell = (uint8)wasm_value_type_cell_num(return_types[0]);
+ if (cell <= 2 /* V128 isn't supported whose cell num is 4 */
+ && block->dynamic_offset != *(loader_ctx->frame_offset - cell)) {
+ /* insert op_copy before else opcode */
+ if (opcode == WASM_OP_ELSE)
+ skip_label();
+ emit_label(cell == 1 ? EXT_OP_COPY_STACK_TOP
+ : EXT_OP_COPY_STACK_TOP_I64);
+ emit_operand(loader_ctx, *(loader_ctx->frame_offset - cell));
+ emit_operand(loader_ctx, block->dynamic_offset);
+
+ if (opcode == WASM_OP_ELSE) {
+ *(loader_ctx->frame_offset - cell) = block->dynamic_offset;
+ }
+ else {
+ loader_ctx->frame_offset -= cell;
+ loader_ctx->dynamic_offset = block->dynamic_offset;
+ PUSH_OFFSET_TYPE(return_types[0]);
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ }
+ if (opcode == WASM_OP_ELSE)
+ emit_label(opcode);
+ }
+ return true;
+ }
+
+ /* Copy stack top values to block's results which are in dynamic space.
+ * The instruction format:
+ * Part a: values count
+ * Part b: all values total cell num
+ * Part c: each value's cell_num, src offset and dst offset
+ * Part d: each value's src offset and dst offset
+ * Part e: each value's dst offset
+ */
+ frame_offset = frame_offset_org = loader_ctx->frame_offset;
+ dynamic_offset = dynamic_offset_org =
+ block->dynamic_offset + wasm_get_cell_num(return_types, return_count);
+
+ /* First traversal to get the count of values needed to be copied. */
+ for (i = (int32)return_count - 1; i >= 0; i--) {
+ uint8 cells = (uint8)wasm_value_type_cell_num(return_types[i]);
+
+ frame_offset -= cells;
+ dynamic_offset -= cells;
+ if (dynamic_offset != *frame_offset) {
+ value_count++;
+ total_cel_num += cells;
+ }
+ }
+
+ if (value_count) {
+ uint32 j = 0;
+ uint8 *emit_data = NULL, *cells = NULL;
+ int16 *src_offsets = NULL;
+ uint16 *dst_offsets = NULL;
+ uint64 size =
+ (uint64)value_count
+ * (sizeof(*cells) + sizeof(*src_offsets) + sizeof(*dst_offsets));
+
+ /* Allocate memory for the emit data */
+ if (!(emit_data = loader_malloc(size, error_buf, error_buf_size)))
+ return false;
+
+ cells = emit_data;
+ src_offsets = (int16 *)(cells + value_count);
+ dst_offsets = (uint16 *)(src_offsets + value_count);
+
+ /* insert op_copy before else opcode */
+ if (opcode == WASM_OP_ELSE)
+ skip_label();
+ emit_label(EXT_OP_COPY_STACK_VALUES);
+ /* Part a) */
+ emit_uint32(loader_ctx, value_count);
+ /* Part b) */
+ emit_uint32(loader_ctx, total_cel_num);
+
+ /* Second traversal to get each value's cell num, src offset and dst
+ * offset. */
+ frame_offset = frame_offset_org;
+ dynamic_offset = dynamic_offset_org;
+ for (i = (int32)return_count - 1, j = 0; i >= 0; i--) {
+ uint8 cell = (uint8)wasm_value_type_cell_num(return_types[i]);
+ frame_offset -= cell;
+ dynamic_offset -= cell;
+ if (dynamic_offset != *frame_offset) {
+ /* cell num */
+ cells[j] = cell;
+ /* src offset */
+ src_offsets[j] = *frame_offset;
+ /* dst offset */
+ dst_offsets[j] = dynamic_offset;
+ j++;
+ }
+ if (opcode == WASM_OP_ELSE) {
+ *frame_offset = dynamic_offset;
+ }
+ else {
+ loader_ctx->frame_offset = frame_offset;
+ loader_ctx->dynamic_offset = dynamic_offset;
+ PUSH_OFFSET_TYPE(return_types[i]);
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ loader_ctx->frame_offset = frame_offset_org;
+ loader_ctx->dynamic_offset = dynamic_offset_org;
+ }
+ }
+
+ bh_assert(j == value_count);
+
+ /* Emit the cells, src_offsets and dst_offsets */
+ for (j = 0; j < value_count; j++)
+ emit_byte(loader_ctx, cells[j]);
+ for (j = 0; j < value_count; j++)
+ emit_operand(loader_ctx, src_offsets[j]);
+ for (j = 0; j < value_count; j++)
+ emit_operand(loader_ctx, dst_offsets[j]);
+
+ if (opcode == WASM_OP_ELSE)
+ emit_label(opcode);
+
+ wasm_runtime_free(emit_data);
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+#endif /* WASM_ENABLE_FAST_INTERP */
+
+#define RESERVE_BLOCK_RET() \
+ do { \
+ if (!reserve_block_ret(loader_ctx, opcode, disable_emit, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_TYPE(type) \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, type, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_TYPE(type) \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, type, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_CSP(label_type, block_type, _start_addr) \
+ do { \
+ if (!wasm_loader_push_frame_csp(loader_ctx, label_type, block_type, \
+ _start_addr, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define POP_CSP() \
+ do { \
+ if (!wasm_loader_pop_frame_csp(loader_ctx, error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \
+ do { \
+ read_leb_uint32(p, p_end, local_idx); \
+ if (local_idx >= param_count + local_count) { \
+ set_error_buf(error_buf, error_buf_size, "unknown local"); \
+ goto fail; \
+ } \
+ local_type = local_idx < param_count \
+ ? param_types[local_idx] \
+ : local_types[local_idx - param_count]; \
+ local_offset = local_offsets[local_idx]; \
+ } while (0)
+
+#define CHECK_BR(depth) \
+ do { \
+ if (!wasm_loader_check_br(loader_ctx, depth, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+static bool
+check_memory(WASMModule *module, char *error_buf, uint32 error_buf_size)
+{
+ if (module->memory_count == 0 && module->import_memory_count == 0) {
+ set_error_buf(error_buf, error_buf_size, "unknown memory");
+ return false;
+ }
+ return true;
+}
+
+#define CHECK_MEMORY() \
+ do { \
+ if (!check_memory(module, error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+static bool
+check_memory_access_align(uint8 opcode, uint32 align, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 mem_access_aligns[] = {
+ 2, 3, 2, 3, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, /* loads */
+ 2, 3, 2, 3, 0, 1, 0, 1, 2 /* stores */
+ };
+ bh_assert(opcode >= WASM_OP_I32_LOAD && opcode <= WASM_OP_I64_STORE32);
+ if (align > mem_access_aligns[opcode - WASM_OP_I32_LOAD]) {
+ set_error_buf(error_buf, error_buf_size,
+ "alignment must not be larger than natural");
+ return false;
+ }
+ return true;
+}
+
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+static bool
+check_simd_memory_access_align(uint8 opcode, uint32 align, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 mem_access_aligns[] = {
+ 4, /* load */
+ 3, 3, 3, 3, 3, 3, /* load and extend */
+ 0, 1, 2, 3, /* load and splat */
+ 4, /* store */
+ };
+
+ uint8 mem_access_aligns_load_lane[] = {
+ 0, 1, 2, 3, /* load lane */
+ 0, 1, 2, 3, /* store lane */
+ 2, 3 /* store zero */
+ };
+
+ if (!((opcode <= SIMD_v128_store)
+ || (SIMD_v128_load8_lane <= opcode
+ && opcode <= SIMD_v128_load64_zero))) {
+ set_error_buf(error_buf, error_buf_size,
+ "the opcode doesn't include memarg");
+ return false;
+ }
+
+ if ((opcode <= SIMD_v128_store
+ && align > mem_access_aligns[opcode - SIMD_v128_load])
+ || (SIMD_v128_load8_lane <= opcode && opcode <= SIMD_v128_load64_zero
+ && align > mem_access_aligns_load_lane[opcode
+ - SIMD_v128_load8_lane])) {
+ set_error_buf(error_buf, error_buf_size,
+ "alignment must not be larger than natural");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+check_simd_access_lane(uint8 opcode, uint8 lane, char *error_buf,
+ uint32 error_buf_size)
+{
+ switch (opcode) {
+ case SIMD_i8x16_extract_lane_s:
+ case SIMD_i8x16_extract_lane_u:
+ case SIMD_i8x16_replace_lane:
+ if (lane >= 16) {
+ goto fail;
+ }
+ break;
+ case SIMD_i16x8_extract_lane_s:
+ case SIMD_i16x8_extract_lane_u:
+ case SIMD_i16x8_replace_lane:
+ if (lane >= 8) {
+ goto fail;
+ }
+ break;
+ case SIMD_i32x4_extract_lane:
+ case SIMD_i32x4_replace_lane:
+ case SIMD_f32x4_extract_lane:
+ case SIMD_f32x4_replace_lane:
+ if (lane >= 4) {
+ goto fail;
+ }
+ break;
+ case SIMD_i64x2_extract_lane:
+ case SIMD_i64x2_replace_lane:
+ case SIMD_f64x2_extract_lane:
+ case SIMD_f64x2_replace_lane:
+ if (lane >= 2) {
+ goto fail;
+ }
+ break;
+
+ case SIMD_v128_load8_lane:
+ case SIMD_v128_load16_lane:
+ case SIMD_v128_load32_lane:
+ case SIMD_v128_load64_lane:
+ case SIMD_v128_store8_lane:
+ case SIMD_v128_store16_lane:
+ case SIMD_v128_store32_lane:
+ case SIMD_v128_store64_lane:
+ case SIMD_v128_load32_zero:
+ case SIMD_v128_load64_zero:
+ {
+ uint8 max_lanes[] = { 16, 8, 4, 2, 16, 8, 4, 2, 4, 2 };
+ if (lane >= max_lanes[opcode - SIMD_v128_load8_lane]) {
+ goto fail;
+ }
+ break;
+ }
+ default:
+ goto fail;
+ }
+
+ return true;
+fail:
+ set_error_buf(error_buf, error_buf_size, "invalid lane index");
+ return false;
+}
+
+static bool
+check_simd_shuffle_mask(V128 mask, char *error_buf, uint32 error_buf_size)
+{
+ uint8 i;
+ for (i = 0; i != 16; ++i) {
+ if (mask.i8x16[i] < 0 || mask.i8x16[i] >= 32) {
+ set_error_buf(error_buf, error_buf_size, "invalid lane index");
+ return false;
+ }
+ }
+ return true;
+}
+#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
+#endif /* end of WASM_ENABLE_SIMD */
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+static bool
+check_memory_align_equal(uint8 opcode, uint32 align, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 wait_notify_aligns[] = { 2, 2, 3 };
+ uint8 mem_access_aligns[] = {
+ 2, 3, 0, 1, 0, 1, 2,
+ };
+ uint8 expect;
+
+ bh_assert((opcode <= WASM_OP_ATOMIC_WAIT64)
+ || (opcode >= WASM_OP_ATOMIC_I32_LOAD
+ && opcode <= WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U));
+ if (opcode <= WASM_OP_ATOMIC_WAIT64) {
+ expect = wait_notify_aligns[opcode - WASM_OP_ATOMIC_NOTIFY];
+ }
+ else {
+ /* 7 opcodes in every group */
+ expect = mem_access_aligns[(opcode - WASM_OP_ATOMIC_I32_LOAD) % 7];
+ }
+ if (align != expect) {
+ set_error_buf(error_buf, error_buf_size,
+ "alignment isn't equal to natural");
+ return false;
+ }
+ return true;
+}
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
+
+static bool
+wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
+ char *error_buf, uint32 error_buf_size)
+{
+ BranchBlock *target_block, *cur_block;
+ BlockType *target_block_type;
+ uint8 *types = NULL, *frame_ref;
+ uint32 arity = 0;
+ int32 i, available_stack_cell;
+ uint16 cell_num;
+
+ if (loader_ctx->csp_num < depth + 1) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown label, "
+ "unexpected end of section or function");
+ return false;
+ }
+
+ cur_block = loader_ctx->frame_csp - 1;
+ target_block = loader_ctx->frame_csp - (depth + 1);
+ target_block_type = &target_block->block_type;
+ frame_ref = loader_ctx->frame_ref;
+
+ /* Note: loop's arity is different from if and block. loop's arity is
+ * its parameter count while if and block arity is result count.
+ */
+ if (target_block->label_type == LABEL_TYPE_LOOP)
+ arity = block_type_get_param_types(target_block_type, &types);
+ else
+ arity = block_type_get_result_types(target_block_type, &types);
+
+ /* If the stack is in polymorphic state, just clear the stack
+ * and then re-push the values to make the stack top values
+ * match block type. */
+ if (cur_block->is_stack_polymorphic) {
+ for (i = (int32)arity - 1; i >= 0; i--) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(types[i]);
+#endif
+ POP_TYPE(types[i]);
+ }
+ for (i = 0; i < (int32)arity; i++) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ bool disable_emit = true;
+ int16 operand_offset = 0;
+ PUSH_OFFSET_TYPE(types[i]);
+#endif
+ PUSH_TYPE(types[i]);
+ }
+ return true;
+ }
+
+ available_stack_cell =
+ (int32)(loader_ctx->stack_cell_num - cur_block->stack_cell_num);
+
+ /* Check stack top values match target block type */
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ if (!check_stack_top_values(frame_ref, available_stack_cell, types[i],
+ error_buf, error_buf_size))
+ return false;
+ cell_num = wasm_value_type_cell_num(types[i]);
+ frame_ref -= cell_num;
+ available_stack_cell -= cell_num;
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+
+static BranchBlock *
+check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint8 *p = *p_buf, *p_end = buf_end;
+ BranchBlock *frame_csp_tmp;
+ uint32 depth;
+
+ read_leb_uint32(p, p_end, depth);
+ CHECK_BR(depth);
+ frame_csp_tmp = loader_ctx->frame_csp - depth - 1;
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_br_info(frame_csp_tmp);
+#endif
+
+ *p_buf = p;
+ return frame_csp_tmp;
+fail:
+ return NULL;
+}
+
+static bool
+check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block,
+ char *error_buf, uint32 error_buf_size)
+{
+ BlockType *block_type = &block->block_type;
+ uint8 *return_types = NULL;
+ uint32 return_count = 0;
+ int32 available_stack_cell, return_cell_num, i;
+ uint8 *frame_ref = NULL;
+
+ available_stack_cell =
+ (int32)(loader_ctx->stack_cell_num - block->stack_cell_num);
+
+ return_count = block_type_get_result_types(block_type, &return_types);
+ return_cell_num =
+ return_count > 0 ? wasm_get_cell_num(return_types, return_count) : 0;
+
+ /* If the stack is in polymorphic state, just clear the stack
+ * and then re-push the values to make the stack top values
+ * match block type. */
+ if (block->is_stack_polymorphic) {
+ for (i = (int32)return_count - 1; i >= 0; i--) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(return_types[i]);
+#endif
+ POP_TYPE(return_types[i]);
+ }
+
+ /* Check stack is empty */
+ if (loader_ctx->stack_cell_num != block->stack_cell_num) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "type mismatch: stack size does not match block type");
+ goto fail;
+ }
+
+ for (i = 0; i < (int32)return_count; i++) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ bool disable_emit = true;
+ int16 operand_offset = 0;
+ PUSH_OFFSET_TYPE(return_types[i]);
+#endif
+ PUSH_TYPE(return_types[i]);
+ }
+ return true;
+ }
+
+ /* Check stack cell num equals return cell num */
+ if (available_stack_cell != return_cell_num) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch: stack size does not match block type");
+ goto fail;
+ }
+
+ /* Check stack values match return types */
+ frame_ref = loader_ctx->frame_ref;
+ for (i = (int32)return_count - 1; i >= 0; i--) {
+ if (!check_stack_top_values(frame_ref, available_stack_cell,
+ return_types[i], error_buf, error_buf_size))
+ return false;
+ frame_ref -= wasm_value_type_cell_num(return_types[i]);
+ available_stack_cell -= wasm_value_type_cell_num(return_types[i]);
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_FAST_INTERP != 0
+/* Copy parameters to dynamic space.
+ * 1) POP original parameter out;
+ * 2) Push and copy original values to dynamic space.
+ * The copy instruction format:
+ * Part a: param count
+ * Part b: all param total cell num
+ * Part c: each param's cell_num, src offset and dst offset
+ * Part d: each param's src offset
+ * Part e: each param's dst offset
+ */
+static bool
+copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
+ char *error_buf, uint32 error_buf_size)
+{
+ int16 *frame_offset = NULL;
+ uint8 *cells = NULL, cell;
+ int16 *src_offsets = NULL;
+ uint8 *emit_data = NULL;
+ uint32 i;
+ BranchBlock *block = loader_ctx->frame_csp - 1;
+ BlockType *block_type = &block->block_type;
+ WASMType *wasm_type = block_type->u.type;
+ uint32 param_count = block_type->u.type->param_count;
+ int16 condition_offset = 0;
+ bool disable_emit = false;
+ int16 operand_offset = 0;
+
+ uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
+
+ /* For if block, we also need copy the condition operand offset. */
+ if (is_if_block)
+ size += sizeof(*cells) + sizeof(*src_offsets);
+
+ /* Allocate memory for the emit data */
+ if (!(emit_data = loader_malloc(size, error_buf, error_buf_size)))
+ return false;
+
+ cells = emit_data;
+ src_offsets = (int16 *)(cells + param_count);
+
+ if (is_if_block)
+ condition_offset = *loader_ctx->frame_offset;
+
+ /* POP original parameter out */
+ for (i = 0; i < param_count; i++) {
+ POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]);
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ }
+ frame_offset = loader_ctx->frame_offset;
+
+ /* Get each param's cell num and src offset */
+ for (i = 0; i < param_count; i++) {
+ cell = (uint8)wasm_value_type_cell_num(wasm_type->types[i]);
+ cells[i] = cell;
+ src_offsets[i] = *frame_offset;
+ frame_offset += cell;
+ }
+
+ /* emit copy instruction */
+ emit_label(EXT_OP_COPY_STACK_VALUES);
+ /* Part a) */
+ emit_uint32(loader_ctx, is_if_block ? param_count + 1 : param_count);
+ /* Part b) */
+ emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1
+ : wasm_type->param_cell_num);
+ /* Part c) */
+ for (i = 0; i < param_count; i++)
+ emit_byte(loader_ctx, cells[i]);
+ if (is_if_block)
+ emit_byte(loader_ctx, 1);
+
+ /* Part d) */
+ for (i = 0; i < param_count; i++)
+ emit_operand(loader_ctx, src_offsets[i]);
+ if (is_if_block)
+ emit_operand(loader_ctx, condition_offset);
+
+ /* Part e) */
+ /* Push to dynamic space. The push will emit the dst offset. */
+ for (i = 0; i < param_count; i++)
+ PUSH_OFFSET_TYPE(wasm_type->types[i]);
+ if (is_if_block)
+ PUSH_OFFSET_TYPE(VALUE_TYPE_I32);
+
+ /* Free the emit data */
+ wasm_runtime_free(emit_data);
+
+ return true;
+
+fail:
+ return false;
+}
+#endif
+
+/* reset the stack to the state of before entering the last block */
+#if WASM_ENABLE_FAST_INTERP != 0
+#define RESET_STACK() \
+ do { \
+ loader_ctx->stack_cell_num = \
+ (loader_ctx->frame_csp - 1)->stack_cell_num; \
+ loader_ctx->frame_ref = \
+ loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \
+ loader_ctx->frame_offset = \
+ loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; \
+ } while (0)
+#else
+#define RESET_STACK() \
+ do { \
+ loader_ctx->stack_cell_num = \
+ (loader_ctx->frame_csp - 1)->stack_cell_num; \
+ loader_ctx->frame_ref = \
+ loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \
+ } while (0)
+#endif
+
+/* set current block's stack polymorphic state */
+#define SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(flag) \
+ do { \
+ BranchBlock *_cur_block = loader_ctx->frame_csp - 1; \
+ _cur_block->is_stack_polymorphic = flag; \
+ } while (0)
+
+#define BLOCK_HAS_PARAM(block_type) \
+ (!block_type.is_value_type && block_type.u.type->param_count > 0)
+
+#define PRESERVE_LOCAL_FOR_BLOCK() \
+ do { \
+ if (!(preserve_local_for_block(loader_ctx, opcode, error_buf, \
+ error_buf_size))) { \
+ goto fail; \
+ } \
+ } while (0)
+
+#if WASM_ENABLE_REF_TYPES != 0
+static bool
+get_table_elem_type(const WASMModule *module, uint32 table_idx,
+ uint8 *p_elem_type, char *error_buf, uint32 error_buf_size)
+{
+ if (!check_table_index(module, table_idx, error_buf, error_buf_size)) {
+ return false;
+ }
+
+ if (p_elem_type) {
+ if (table_idx < module->import_table_count)
+ *p_elem_type = module->import_tables[table_idx].u.table.elem_type;
+ else
+ *p_elem_type =
+ module->tables[module->import_table_count + table_idx]
+ .elem_type;
+ }
+ return true;
+}
+
+static bool
+get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx,
+ uint8 *p_elem_type, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (table_seg_idx >= module->table_seg_count) {
+ set_error_buf_v(error_buf, error_buf_size, "unknown elem segment %u",
+ table_seg_idx);
+ return false;
+ }
+
+ if (p_elem_type) {
+ *p_elem_type = module->table_segments[table_seg_idx].elem_type;
+ }
+ return true;
+}
+#endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+const uint8 *
+wasm_loader_get_custom_section(WASMModule *module, const char *name,
+ uint32 *len)
+{
+ WASMCustomSection *section = module->custom_section_list;
+
+ while (section) {
+ if ((section->name_len == strlen(name))
+ && (memcmp(section->name_addr, name, section->name_len) == 0)) {
+ if (len) {
+ *len = section->content_len;
+ }
+ return section->content_addr;
+ }
+
+ section = section->next;
+ }
+
+ return false;
+}
+#endif
+
+static bool
+wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
+ uint32 cur_func_idx, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org;
+ uint32 param_count, local_count, global_count;
+ uint8 *param_types, *local_types, local_type, global_type;
+ BlockType func_block_type;
+ uint16 *local_offsets, local_offset;
+ uint32 type_idx, func_idx, local_idx, global_idx, table_idx;
+ uint32 table_seg_idx, data_seg_idx, count, align, mem_offset, i;
+ int32 i32_const = 0;
+ int64 i64_const;
+ uint8 opcode;
+ bool return_value = false;
+ WASMLoaderContext *loader_ctx;
+ BranchBlock *frame_csp_tmp;
+#if WASM_ENABLE_FAST_INTERP != 0
+ uint8 *func_const_end, *func_const = NULL;
+ int16 operand_offset = 0;
+ uint8 last_op = 0;
+ bool disable_emit, preserve_local = false;
+ float32 f32_const;
+ float64 f64_const;
+
+ LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n",
+ func->param_cell_num, func->local_cell_num, func->ret_cell_num);
+#endif
+
+ global_count = module->import_global_count + module->global_count;
+
+ param_count = func->func_type->param_count;
+ param_types = func->func_type->types;
+
+ func_block_type.is_value_type = false;
+ func_block_type.u.type = func->func_type;
+
+ local_count = func->local_count;
+ local_types = func->local_types;
+ local_offsets = func->local_offsets;
+
+ if (!(loader_ctx = wasm_loader_ctx_init(func, error_buf, error_buf_size))) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* For the first traverse, the initial value of preserved_local_offset has
+ * not been determined, we use the INT16_MAX to represent that a slot has
+ * been copied to preserve space. For second traverse, this field will be
+ * set to the appropriate value in wasm_loader_ctx_reinit.
+ * This is for Issue #1230,
+ * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1230, the
+ * drop opcodes need to know which slots are preserved, so those slots will
+ * not be treated as dynamically allocated slots */
+ loader_ctx->preserved_local_offset = INT16_MAX;
+
+re_scan:
+ if (loader_ctx->code_compiled_size > 0) {
+ if (!wasm_loader_ctx_reinit(loader_ctx)) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ goto fail;
+ }
+ p = func->code;
+ func->code_compiled = loader_ctx->p_code_compiled;
+ func->code_compiled_size = loader_ctx->code_compiled_size;
+ }
+#endif
+
+ PUSH_CSP(LABEL_TYPE_FUNCTION, func_block_type, p);
+
+ while (p < p_end) {
+ opcode = *p++;
+#if WASM_ENABLE_FAST_INTERP != 0
+ p_org = p;
+ disable_emit = false;
+ emit_label(opcode);
+#endif
+
+ switch (opcode) {
+ case WASM_OP_UNREACHABLE:
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ break;
+
+ case WASM_OP_NOP:
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+#endif
+ break;
+
+ case WASM_OP_IF:
+#if WASM_ENABLE_FAST_INTERP != 0
+ PRESERVE_LOCAL_FOR_BLOCK();
+#endif
+ POP_I32();
+ goto handle_op_block_and_loop;
+ case WASM_OP_BLOCK:
+ case WASM_OP_LOOP:
+#if WASM_ENABLE_FAST_INTERP != 0
+ PRESERVE_LOCAL_FOR_BLOCK();
+#endif
+ handle_op_block_and_loop:
+ {
+ uint8 value_type;
+ BlockType block_type;
+
+ p_org = p - 1;
+ value_type = read_uint8(p);
+ if (is_byte_a_type(value_type)) {
+ /* If the first byte is one of these special values:
+ * 0x40/0x7F/0x7E/0x7D/0x7C, take it as the type of
+ * the single return value. */
+ block_type.is_value_type = true;
+ block_type.u.value_type = value_type;
+ }
+ else {
+ uint32 type_index;
+ /* Resolve the leb128 encoded type index as block type */
+ p--;
+ read_leb_uint32(p, p_end, type_index);
+ if (type_index >= module->type_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown type");
+ goto fail;
+ }
+ block_type.is_value_type = false;
+ block_type.u.type = module->types[type_index];
+#if WASM_ENABLE_FAST_INTERP == 0
+ /* If block use type index as block type, change the opcode
+ * to new extended opcode so that interpreter can resolve
+ * the block quickly.
+ */
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!record_fast_op(module, p_org, *p_org, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#endif
+ *p_org = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
+#endif
+ }
+
+ /* Pop block parameters from stack */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ WASMType *wasm_type = block_type.u.type;
+ for (i = 0; i < block_type.u.type->param_count; i++)
+ POP_TYPE(
+ wasm_type->types[wasm_type->param_count - i - 1]);
+ }
+
+ PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK),
+ block_type, p);
+
+ /* Pass parameters to block */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ for (i = 0; i < block_type.u.type->param_count; i++)
+ PUSH_TYPE(block_type.u.type->types[i]);
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (opcode == WASM_OP_BLOCK) {
+ skip_label();
+ }
+ else if (opcode == WASM_OP_LOOP) {
+ skip_label();
+ if (BLOCK_HAS_PARAM(block_type)) {
+ /* Make sure params are in dynamic space */
+ if (!copy_params_to_dynamic_space(
+ loader_ctx, false, error_buf, error_buf_size))
+ goto fail;
+ }
+ (loader_ctx->frame_csp - 1)->code_compiled =
+ loader_ctx->p_code_compiled;
+ }
+ else if (opcode == WASM_OP_IF) {
+ /* If block has parameters, we should make sure they are in
+ * dynamic space. Otherwise, when else branch is missing,
+ * the later opcode may consume incorrect operand offset.
+ * Spec case:
+ * (func (export "params-id") (param i32) (result i32)
+ * (i32.const 1)
+ * (i32.const 2)
+ * (if (param i32 i32) (result i32 i32) (local.get 0)
+ * (then)) (i32.add)
+ * )
+ *
+ * So we should emit a copy instruction before the if.
+ *
+ * And we also need to save the parameter offsets and
+ * recover them before entering else branch.
+ *
+ */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ BranchBlock *block = loader_ctx->frame_csp - 1;
+ uint64 size;
+
+ /* skip the if condition operand offset */
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ /* skip the if label */
+ skip_label();
+ /* Emit a copy instruction */
+ if (!copy_params_to_dynamic_space(
+ loader_ctx, true, error_buf, error_buf_size))
+ goto fail;
+
+ /* Emit the if instruction */
+ emit_label(opcode);
+ /* Emit the new condition operand offset */
+ POP_OFFSET_TYPE(VALUE_TYPE_I32);
+
+ /* Save top param_count values of frame_offset stack, so
+ * that we can recover it before executing else branch
+ */
+ size = sizeof(int16)
+ * (uint64)block_type.u.type->param_cell_num;
+ if (!(block->param_frame_offsets = loader_malloc(
+ size, error_buf, error_buf_size)))
+ goto fail;
+ bh_memcpy_s(block->param_frame_offsets, (uint32)size,
+ loader_ctx->frame_offset
+ - size / sizeof(int16),
+ (uint32)size);
+ }
+
+ emit_empty_label_addr_and_frame_ip(PATCH_ELSE);
+ emit_empty_label_addr_and_frame_ip(PATCH_END);
+ }
+#endif
+ break;
+ }
+
+ case WASM_OP_ELSE:
+ {
+ BlockType block_type = (loader_ctx->frame_csp - 1)->block_type;
+
+ if (loader_ctx->csp_num < 2
+ || (loader_ctx->frame_csp - 1)->label_type
+ != LABEL_TYPE_IF) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "opcode else found without matched opcode if");
+ goto fail;
+ }
+
+ /* check whether if branch's stack matches its result type */
+ if (!check_block_stack(loader_ctx, loader_ctx->frame_csp - 1,
+ error_buf, error_buf_size))
+ goto fail;
+
+ (loader_ctx->frame_csp - 1)->else_addr = p - 1;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* if the result of if branch is in local or const area, add a
+ * copy op */
+ RESERVE_BLOCK_RET();
+
+ emit_empty_label_addr_and_frame_ip(PATCH_END);
+ apply_label_patch(loader_ctx, 1, PATCH_ELSE);
+#endif
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(false);
+
+ /* Pass parameters to if-false branch */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ for (i = 0; i < block_type.u.type->param_count; i++)
+ PUSH_TYPE(block_type.u.type->types[i]);
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Recover top param_count values of frame_offset stack */
+ if (BLOCK_HAS_PARAM((block_type))) {
+ uint32 size;
+ BranchBlock *block = loader_ctx->frame_csp - 1;
+ size = sizeof(int16) * block_type.u.type->param_cell_num;
+ bh_memcpy_s(loader_ctx->frame_offset, size,
+ block->param_frame_offsets, size);
+ loader_ctx->frame_offset += (size / sizeof(int16));
+ }
+#endif
+
+ break;
+ }
+
+ case WASM_OP_END:
+ {
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+
+ /* check whether block stack matches its result type */
+ if (!check_block_stack(loader_ctx, cur_block, error_buf,
+ error_buf_size))
+ goto fail;
+
+ /* if no else branch, and return types do not match param types,
+ * fail */
+ if (cur_block->label_type == LABEL_TYPE_IF
+ && !cur_block->else_addr) {
+ uint32 block_param_count = 0, block_ret_count = 0;
+ uint8 *block_param_types = NULL, *block_ret_types = NULL;
+ BlockType *cur_block_type = &cur_block->block_type;
+ if (cur_block_type->is_value_type) {
+ if (cur_block_type->u.value_type != VALUE_TYPE_VOID) {
+ block_ret_count = 1;
+ block_ret_types = &cur_block_type->u.value_type;
+ }
+ }
+ else {
+ block_param_count = cur_block_type->u.type->param_count;
+ block_ret_count = cur_block_type->u.type->result_count;
+ block_param_types = cur_block_type->u.type->types;
+ block_ret_types =
+ cur_block_type->u.type->types + block_param_count;
+ }
+ if (block_param_count != block_ret_count
+ || (block_param_count
+ && memcmp(block_param_types, block_ret_types,
+ block_param_count))) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch: else branch missing");
+ goto fail;
+ }
+ }
+
+ POP_CSP();
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ /* copy the result to the block return address */
+ RESERVE_BLOCK_RET();
+
+ apply_label_patch(loader_ctx, 0, PATCH_END);
+ free_label_patch_list(loader_ctx->frame_csp);
+ if (loader_ctx->frame_csp->label_type == LABEL_TYPE_FUNCTION) {
+ int32 idx;
+ uint8 ret_type;
+
+ emit_label(WASM_OP_RETURN);
+ for (idx = (int32)func->func_type->result_count - 1;
+ idx >= 0; idx--) {
+ ret_type = *(func->func_type->types
+ + func->func_type->param_count + idx);
+ POP_OFFSET_TYPE(ret_type);
+ }
+ }
+#endif
+ if (loader_ctx->csp_num > 0) {
+ loader_ctx->frame_csp->end_addr = p - 1;
+ }
+ else {
+ /* end of function block, function will return */
+ if (p < p_end) {
+ set_error_buf(error_buf, error_buf_size,
+ "section size mismatch");
+ goto fail;
+ }
+ }
+
+ break;
+ }
+
+ case WASM_OP_BR:
+ {
+ if (!(frame_csp_tmp = check_branch_block(
+ loader_ctx, &p, p_end, error_buf, error_buf_size)))
+ goto fail;
+
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ break;
+ }
+
+ case WASM_OP_BR_IF:
+ {
+ POP_I32();
+
+ if (!(frame_csp_tmp = check_branch_block(
+ loader_ctx, &p, p_end, error_buf, error_buf_size)))
+ goto fail;
+
+ break;
+ }
+
+ case WASM_OP_BR_TABLE:
+ {
+ uint8 *ret_types = NULL;
+ uint32 ret_count = 0;
+#if WASM_ENABLE_FAST_INTERP == 0
+ uint8 *p_depth_begin, *p_depth;
+ uint32 depth, j;
+ BrTableCache *br_table_cache = NULL;
+
+ p_org = p - 1;
+#endif
+
+ read_leb_uint32(p, p_end, count);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, count);
+#endif
+ POP_I32();
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ p_depth_begin = p_depth = p;
+#endif
+ for (i = 0; i <= count; i++) {
+ if (!(frame_csp_tmp =
+ check_branch_block(loader_ctx, &p, p_end,
+ error_buf, error_buf_size)))
+ goto fail;
+
+ if (i == 0) {
+ if (frame_csp_tmp->label_type != LABEL_TYPE_LOOP)
+ ret_count = block_type_get_result_types(
+ &frame_csp_tmp->block_type, &ret_types);
+ }
+ else {
+ uint8 *tmp_ret_types = NULL;
+ uint32 tmp_ret_count = 0;
+
+ /* Check whether all table items have the same return
+ * type */
+ if (frame_csp_tmp->label_type != LABEL_TYPE_LOOP)
+ tmp_ret_count = block_type_get_result_types(
+ &frame_csp_tmp->block_type, &tmp_ret_types);
+
+ if (ret_count != tmp_ret_count
+ || (ret_count
+ && 0
+ != memcmp(ret_types, tmp_ret_types,
+ ret_count))) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "type mismatch: br_table targets must "
+ "all use same result type");
+ goto fail;
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ depth = (uint32)(loader_ctx->frame_csp - 1 - frame_csp_tmp);
+ if (br_table_cache) {
+ br_table_cache->br_depths[i] = depth;
+ }
+ else {
+ if (depth > 255) {
+ /* The depth cannot be stored in one byte,
+ create br_table cache to store each depth */
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!record_fast_op(module, p_org, *p_org,
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+#endif
+ if (!(br_table_cache = loader_malloc(
+ offsetof(BrTableCache, br_depths)
+ + sizeof(uint32)
+ * (uint64)(count + 1),
+ error_buf, error_buf_size))) {
+ goto fail;
+ }
+ *p_org = EXT_OP_BR_TABLE_CACHE;
+ br_table_cache->br_table_op_addr = p_org;
+ br_table_cache->br_count = count;
+ /* Copy previous depths which are one byte */
+ for (j = 0; j < i; j++) {
+ br_table_cache->br_depths[j] = p_depth_begin[j];
+ }
+ br_table_cache->br_depths[i] = depth;
+ bh_list_insert(module->br_table_cache_list,
+ br_table_cache);
+ }
+ else {
+ /* The depth can be stored in one byte, use the
+ byte of the leb to store it */
+ *p_depth++ = (uint8)depth;
+ }
+ }
+#endif
+ }
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ /* Set the tailing bytes to nop */
+ if (br_table_cache)
+ p_depth = p_depth_begin;
+ while (p_depth < p)
+ *p_depth++ = WASM_OP_NOP;
+#endif
+
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ break;
+ }
+
+ case WASM_OP_RETURN:
+ {
+ int32 idx;
+ uint8 ret_type;
+ for (idx = (int32)func->func_type->result_count - 1; idx >= 0;
+ idx--) {
+ ret_type = *(func->func_type->types
+ + func->func_type->param_count + idx);
+ POP_TYPE(ret_type);
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* emit the offset after return opcode */
+ POP_OFFSET_TYPE(ret_type);
+#endif
+ }
+
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+
+ break;
+ }
+
+ case WASM_OP_CALL:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL:
+#endif
+ {
+ WASMType *func_type;
+ int32 idx;
+
+ read_leb_uint32(p, p_end, func_idx);
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* we need to emit func_idx before arguments */
+ emit_uint32(loader_ctx, func_idx);
+#endif
+
+ if (!check_function_index(module, func_idx, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ if (func_idx < module->import_function_count)
+ func_type =
+ module->import_functions[func_idx].u.function.func_type;
+ else
+ func_type = module
+ ->functions[func_idx
+ - module->import_function_count]
+ ->func_type;
+
+ if (func_type->param_count > 0) {
+ for (idx = (int32)(func_type->param_count - 1); idx >= 0;
+ idx--) {
+ POP_TYPE(func_type->types[idx]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(func_type->types[idx]);
+#endif
+ }
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ if (opcode == WASM_OP_CALL) {
+#endif
+ for (i = 0; i < func_type->result_count; i++) {
+ PUSH_TYPE(func_type->types[func_type->param_count + i]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Here we emit each return value's dynamic_offset. But
+ * in fact these offsets are continuous, so interpreter
+ * only need to get the first return value's offset.
+ */
+ PUSH_OFFSET_TYPE(
+ func_type->types[func_type->param_count + i]);
+#endif
+ }
+#if WASM_ENABLE_TAIL_CALL != 0
+ }
+ else {
+ uint8 type;
+ if (func_type->result_count
+ != func->func_type->result_count) {
+ set_error_buf_v(error_buf, error_buf_size, "%s%u%s",
+ "type mismatch: expect ",
+ func->func_type->result_count,
+ " return values but got other");
+ goto fail;
+ }
+ for (i = 0; i < func_type->result_count; i++) {
+ type = func->func_type
+ ->types[func->func_type->param_count + i];
+ if (func_type->types[func_type->param_count + i]
+ != type) {
+ set_error_buf_v(error_buf, error_buf_size, "%s%s%s",
+ "type mismatch: expect ",
+ type2str(type), " but got other");
+ goto fail;
+ }
+ }
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ }
+#endif
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_func_call = true;
+#endif
+ break;
+ }
+
+ /*
+ * if disable reference type: call_indirect typeidx, 0x00
+ * if enable reference type: call_indirect typeidx, tableidx
+ */
+ case WASM_OP_CALL_INDIRECT:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL_INDIRECT:
+#endif
+ {
+ int32 idx;
+ WASMType *func_type;
+
+ read_leb_uint32(p, p_end, type_idx);
+#if WASM_ENABLE_REF_TYPES != 0
+ read_leb_uint32(p, p_end, table_idx);
+#else
+ CHECK_BUF(p, p_end, 1);
+ table_idx = read_uint8(p);
+#endif
+ if (!check_table_index(module, table_idx, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* we need to emit before arguments */
+#if WASM_ENABLE_TAIL_CALL != 0
+ emit_byte(loader_ctx, opcode);
+#endif
+ emit_uint32(loader_ctx, type_idx);
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ /* skip elem idx */
+ POP_I32();
+
+ if (type_idx >= module->type_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown type");
+ goto fail;
+ }
+
+ func_type = module->types[type_idx];
+
+ if (func_type->param_count > 0) {
+ for (idx = (int32)(func_type->param_count - 1); idx >= 0;
+ idx--) {
+ POP_TYPE(func_type->types[idx]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(func_type->types[idx]);
+#endif
+ }
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ if (opcode == WASM_OP_CALL_INDIRECT) {
+#endif
+ for (i = 0; i < func_type->result_count; i++) {
+ PUSH_TYPE(func_type->types[func_type->param_count + i]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(
+ func_type->types[func_type->param_count + i]);
+#endif
+ }
+#if WASM_ENABLE_TAIL_CALL != 0
+ }
+ else {
+ uint8 type;
+ if (func_type->result_count
+ != func->func_type->result_count) {
+ set_error_buf_v(error_buf, error_buf_size, "%s%u%s",
+ "type mismatch: expect ",
+ func->func_type->result_count,
+ " return values but got other");
+ goto fail;
+ }
+ for (i = 0; i < func_type->result_count; i++) {
+ type = func->func_type
+ ->types[func->func_type->param_count + i];
+ if (func_type->types[func_type->param_count + i]
+ != type) {
+ set_error_buf_v(error_buf, error_buf_size, "%s%s%s",
+ "type mismatch: expect ",
+ type2str(type), " but got other");
+ goto fail;
+ }
+ }
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ }
+#endif
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_func_call = true;
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_call_indirect = true;
+#endif
+ break;
+ }
+
+ case WASM_OP_DROP:
+ {
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+ int32 available_stack_cell =
+ (int32)(loader_ctx->stack_cell_num
+ - cur_block->stack_cell_num);
+
+ if (available_stack_cell <= 0
+ && !cur_block->is_stack_polymorphic) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch, opcode drop was found "
+ "but stack was empty");
+ goto fail;
+ }
+
+ if (available_stack_cell > 0) {
+ if (is_32bit_type(*(loader_ctx->frame_ref - 1))) {
+ loader_ctx->frame_ref--;
+ loader_ctx->stack_cell_num--;
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ loader_ctx->frame_offset--;
+ if ((*(loader_ctx->frame_offset)
+ > loader_ctx->start_dynamic_offset)
+ && (*(loader_ctx->frame_offset)
+ < loader_ctx->max_dynamic_offset))
+ loader_ctx->dynamic_offset--;
+#endif
+ }
+ else if (is_64bit_type(*(loader_ctx->frame_ref - 1))) {
+ loader_ctx->frame_ref -= 2;
+ loader_ctx->stack_cell_num -= 2;
+#if WASM_ENABLE_FAST_INTERP == 0
+ *(p - 1) = WASM_OP_DROP_64;
+#endif
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ loader_ctx->frame_offset -= 2;
+ if ((*(loader_ctx->frame_offset)
+ > loader_ctx->start_dynamic_offset)
+ && (*(loader_ctx->frame_offset)
+ < loader_ctx->max_dynamic_offset))
+ loader_ctx->dynamic_offset -= 2;
+#endif
+ }
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ else if (*(loader_ctx->frame_ref - 1) == REF_V128_1) {
+ loader_ctx->frame_ref -= 4;
+ loader_ctx->stack_cell_num -= 4;
+ }
+#endif
+#endif
+ else {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch");
+ goto fail;
+ }
+ }
+ else {
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+#endif
+ }
+ break;
+ }
+
+ case WASM_OP_SELECT:
+ {
+ uint8 ref_type;
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+ int32 available_stack_cell;
+
+ POP_I32();
+
+ available_stack_cell = (int32)(loader_ctx->stack_cell_num
+ - cur_block->stack_cell_num);
+
+ if (available_stack_cell <= 0
+ && !cur_block->is_stack_polymorphic) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch or invalid result arity, "
+ "opcode select was found "
+ "but stack was empty");
+ goto fail;
+ }
+
+ if (available_stack_cell > 0) {
+ switch (*(loader_ctx->frame_ref - 1)) {
+ case REF_I32:
+ case REF_F32:
+ break;
+ case REF_I64_2:
+ case REF_F64_2:
+#if WASM_ENABLE_FAST_INTERP == 0
+ *(p - 1) = WASM_OP_SELECT_64;
+#endif
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (loader_ctx->p_code_compiled) {
+ uint8 opcode_tmp = WASM_OP_SELECT_64;
+ uint8 *p_code_compiled_tmp =
+ loader_ctx->p_code_compiled - 2;
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(void **)(p_code_compiled_tmp
+ - sizeof(void *)) =
+ handle_table[opcode_tmp];
+#else
+ int32 offset =
+ (int32)((uint8 *)handle_table[opcode_tmp]
+ - (uint8 *)handle_table[0]);
+ if (!(offset >= INT16_MIN
+ && offset < INT16_MAX)) {
+ set_error_buf(error_buf, error_buf_size,
+ "pre-compiled label offset "
+ "out of range");
+ goto fail;
+ }
+ *(int16 *)(p_code_compiled_tmp
+ - sizeof(int16)) = (int16)offset;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(p_code_compiled_tmp - 1) = opcode_tmp;
+#else
+ *(p_code_compiled_tmp - 2) = opcode_tmp;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+ }
+#endif /* end of WASM_ENABLE_FAST_INTERP */
+ break;
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ case REF_V128_4:
+ break;
+#endif /* (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
+#endif /* WASM_ENABLE_SIMD != 0 */
+ default:
+ {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch");
+ goto fail;
+ }
+ }
+
+ ref_type = *(loader_ctx->frame_ref - 1);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(ref_type);
+ POP_TYPE(ref_type);
+ POP_OFFSET_TYPE(ref_type);
+ POP_TYPE(ref_type);
+ PUSH_OFFSET_TYPE(ref_type);
+ PUSH_TYPE(ref_type);
+#else
+ POP2_AND_PUSH(ref_type, ref_type);
+#endif
+ }
+ else {
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(VALUE_TYPE_ANY);
+#endif
+ PUSH_TYPE(VALUE_TYPE_ANY);
+ }
+ break;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_SELECT_T:
+ {
+ uint8 vec_len, ref_type;
+
+ read_leb_uint32(p, p_end, vec_len);
+ if (!vec_len) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid result arity");
+ goto fail;
+ }
+
+ CHECK_BUF(p, p_end, 1);
+ ref_type = read_uint8(p);
+ if (!is_value_type(ref_type)) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown value type");
+ goto fail;
+ }
+
+ POP_I32();
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (loader_ctx->p_code_compiled) {
+ uint8 opcode_tmp = WASM_OP_SELECT;
+ uint8 *p_code_compiled_tmp =
+ loader_ctx->p_code_compiled - 2;
+
+ if (ref_type == VALUE_TYPE_V128) {
+#if (WASM_ENABLE_SIMD == 0) \
+ || ((WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0))
+ set_error_buf(error_buf, error_buf_size,
+ "SIMD v128 type isn't supported");
+ goto fail;
+#endif
+ }
+ else {
+ if (ref_type == VALUE_TYPE_F64
+ || ref_type == VALUE_TYPE_I64)
+ opcode_tmp = WASM_OP_SELECT_64;
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(void **)(p_code_compiled_tmp - sizeof(void *)) =
+ handle_table[opcode_tmp];
+#else
+ int32 offset = (int32)((uint8 *)handle_table[opcode_tmp]
+ - (uint8 *)handle_table[0]);
+ if (!(offset >= INT16_MIN && offset < INT16_MAX)) {
+ set_error_buf(
+ error_buf, error_buf_size,
+ "pre-compiled label offset out of range");
+ goto fail;
+ }
+ *(int16 *)(p_code_compiled_tmp - sizeof(int16)) =
+ (int16)offset;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(p_code_compiled_tmp - 1) = opcode_tmp;
+#else
+ *(p_code_compiled_tmp - 2) = opcode_tmp;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+ }
+ }
+#endif /* WASM_ENABLE_FAST_INTERP != 0 */
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(ref_type);
+ POP_TYPE(ref_type);
+ POP_OFFSET_TYPE(ref_type);
+ POP_TYPE(ref_type);
+ PUSH_OFFSET_TYPE(ref_type);
+ PUSH_TYPE(ref_type);
+#else
+ POP2_AND_PUSH(ref_type, ref_type);
+#endif /* WASM_ENABLE_FAST_INTERP != 0 */
+
+ (void)vec_len;
+ break;
+ }
+
+ /* table.get x. tables[x]. [i32] -> [t] */
+ /* table.set x. tables[x]. [i32 t] -> [] */
+ case WASM_OP_TABLE_GET:
+ case WASM_OP_TABLE_SET:
+ {
+ uint8 decl_ref_type;
+
+ read_leb_uint32(p, p_end, table_idx);
+ if (!get_table_elem_type(module, table_idx, &decl_ref_type,
+ error_buf, error_buf_size))
+ goto fail;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ if (opcode == WASM_OP_TABLE_GET) {
+ POP_I32();
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(decl_ref_type);
+#endif
+ PUSH_TYPE(decl_ref_type);
+ }
+ else {
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(decl_ref_type);
+#endif
+ POP_TYPE(decl_ref_type);
+ POP_I32();
+ }
+ break;
+ }
+ case WASM_OP_REF_NULL:
+ {
+ uint8 ref_type;
+
+ CHECK_BUF(p, p_end, 1);
+ ref_type = read_uint8(p);
+ if (ref_type != VALUE_TYPE_FUNCREF
+ && ref_type != VALUE_TYPE_EXTERNREF) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown value type");
+ goto fail;
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(ref_type);
+#endif
+ PUSH_TYPE(ref_type);
+ break;
+ }
+ case WASM_OP_REF_IS_NULL:
+ {
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx,
+ VALUE_TYPE_FUNCREF,
+ error_buf, error_buf_size)
+ && !wasm_loader_pop_frame_ref_offset(
+ loader_ctx, VALUE_TYPE_EXTERNREF, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#else
+ if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,
+ error_buf, error_buf_size)
+ && !wasm_loader_pop_frame_ref(loader_ctx,
+ VALUE_TYPE_EXTERNREF,
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+#endif
+ PUSH_I32();
+ break;
+ }
+ case WASM_OP_REF_FUNC:
+ {
+ read_leb_uint32(p, p_end, func_idx);
+
+ if (!check_function_index(module, func_idx, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ /* Refer to a forward-declared function */
+ if (func_idx >= cur_func_idx + module->import_function_count) {
+ WASMTableSeg *table_seg = module->table_segments;
+ bool func_declared = false;
+ uint32 j;
+
+ /* Check whether the function is declared in table segs */
+ for (i = 0; i < module->table_seg_count; i++, table_seg++) {
+ if (table_seg->elem_type == VALUE_TYPE_FUNCREF
+ && wasm_elem_is_declarative(table_seg->mode)) {
+ for (j = 0; j < table_seg->function_count; j++) {
+ if (table_seg->func_indexes[j] == func_idx) {
+ func_declared = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!func_declared) {
+ /* Check whether the function is exported */
+ for (i = 0; i < module->export_count; i++) {
+ if (module->exports[i].kind == EXPORT_KIND_FUNC
+ && module->exports[i].index == func_idx) {
+ func_declared = true;
+ break;
+ }
+ }
+ }
+
+ if (!func_declared) {
+ set_error_buf(error_buf, error_buf_size,
+ "undeclared function reference");
+ goto fail;
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, func_idx);
+#endif
+ PUSH_FUNCREF();
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+
+ case WASM_OP_GET_LOCAL:
+ {
+ p_org = p - 1;
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+ PUSH_TYPE(local_type);
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Get Local is optimized out */
+ skip_label();
+ disable_emit = true;
+ operand_offset = local_offset;
+ PUSH_OFFSET_TYPE(local_type);
+#else
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
+ && (WASM_ENABLE_FAST_JIT == 0) && (WASM_ENABLE_DEBUG_INTERP == 0)
+ if (local_offset < 0x80) {
+ *p_org++ = EXT_OP_GET_LOCAL_FAST;
+ if (is_32bit_type(local_type)) {
+ *p_org++ = (uint8)local_offset;
+ }
+ else {
+ *p_org++ = (uint8)(local_offset | 0x80);
+ }
+ while (p_org < p) {
+ *p_org++ = WASM_OP_NOP;
+ }
+ }
+#endif
+#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
+ break;
+ }
+
+ case WASM_OP_SET_LOCAL:
+ {
+ p_org = p - 1;
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+ POP_TYPE(local_type);
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (!(preserve_referenced_local(
+ loader_ctx, opcode, local_offset, local_type,
+ &preserve_local, error_buf, error_buf_size)))
+ goto fail;
+
+ if (local_offset < 256) {
+ skip_label();
+ if ((!preserve_local) && (LAST_OP_OUTPUT_I32())) {
+ if (loader_ctx->p_code_compiled)
+ STORE_U16(loader_ctx->p_code_compiled - 2,
+ local_offset);
+ loader_ctx->frame_offset--;
+ loader_ctx->dynamic_offset--;
+ }
+ else if ((!preserve_local) && (LAST_OP_OUTPUT_I64())) {
+ if (loader_ctx->p_code_compiled)
+ STORE_U16(loader_ctx->p_code_compiled - 2,
+ local_offset);
+ loader_ctx->frame_offset -= 2;
+ loader_ctx->dynamic_offset -= 2;
+ }
+ else {
+ if (is_32bit_type(local_type)) {
+ emit_label(EXT_OP_SET_LOCAL_FAST);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ else {
+ emit_label(EXT_OP_SET_LOCAL_FAST_I64);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ POP_OFFSET_TYPE(local_type);
+ }
+ }
+ else { /* local index larger than 255, reserve leb */
+ emit_uint32(loader_ctx, local_idx);
+ POP_OFFSET_TYPE(local_type);
+ }
+#else
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
+ && (WASM_ENABLE_FAST_JIT == 0) && (WASM_ENABLE_DEBUG_INTERP == 0)
+ if (local_offset < 0x80) {
+ *p_org++ = EXT_OP_SET_LOCAL_FAST;
+ if (is_32bit_type(local_type)) {
+ *p_org++ = (uint8)local_offset;
+ }
+ else {
+ *p_org++ = (uint8)(local_offset | 0x80);
+ }
+ while (p_org < p) {
+ *p_org++ = WASM_OP_NOP;
+ }
+ }
+#endif
+#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
+ break;
+ }
+
+ case WASM_OP_TEE_LOCAL:
+ {
+ p_org = p - 1;
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* If the stack is in polymorphic state, do fake pop and push on
+ offset stack to keep the depth of offset stack to be the
+ same with ref stack */
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+ if (cur_block->is_stack_polymorphic) {
+ POP_OFFSET_TYPE(local_type);
+ PUSH_OFFSET_TYPE(local_type);
+ }
+#endif
+ POP_TYPE(local_type);
+ PUSH_TYPE(local_type);
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (!(preserve_referenced_local(
+ loader_ctx, opcode, local_offset, local_type,
+ &preserve_local, error_buf, error_buf_size)))
+ goto fail;
+
+ if (local_offset < 256) {
+ skip_label();
+ if (is_32bit_type(local_type)) {
+ emit_label(EXT_OP_TEE_LOCAL_FAST);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ else {
+ emit_label(EXT_OP_TEE_LOCAL_FAST_I64);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ }
+ else { /* local index larger than 255, reserve leb */
+ emit_uint32(loader_ctx, local_idx);
+ }
+ emit_operand(loader_ctx,
+ *(loader_ctx->frame_offset
+ - wasm_value_type_cell_num(local_type)));
+#else
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
+ && (WASM_ENABLE_FAST_JIT == 0) && (WASM_ENABLE_DEBUG_INTERP == 0)
+ if (local_offset < 0x80) {
+ *p_org++ = EXT_OP_TEE_LOCAL_FAST;
+ if (is_32bit_type(local_type)) {
+ *p_org++ = (uint8)local_offset;
+ }
+ else {
+ *p_org++ = (uint8)(local_offset | 0x80);
+ }
+ while (p_org < p) {
+ *p_org++ = WASM_OP_NOP;
+ }
+ }
+#endif
+#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
+ break;
+ }
+
+ case WASM_OP_GET_GLOBAL:
+ {
+ p_org = p - 1;
+ read_leb_uint32(p, p_end, global_idx);
+ if (global_idx >= global_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown global");
+ goto fail;
+ }
+
+ global_type =
+ global_idx < module->import_global_count
+ ? module->import_globals[global_idx].u.global.type
+ : module
+ ->globals[global_idx
+ - module->import_global_count]
+ .type;
+
+ PUSH_TYPE(global_type);
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ if (global_type == VALUE_TYPE_I64
+ || global_type == VALUE_TYPE_F64) {
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!record_fast_op(module, p_org, *p_org, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#endif
+ *p_org = WASM_OP_GET_GLOBAL_64;
+ }
+#else /* else of WASM_ENABLE_FAST_INTERP */
+ if (global_type == VALUE_TYPE_I64
+ || global_type == VALUE_TYPE_F64) {
+ skip_label();
+ emit_label(WASM_OP_GET_GLOBAL_64);
+ }
+ emit_uint32(loader_ctx, global_idx);
+ PUSH_OFFSET_TYPE(global_type);
+#endif /* end of WASM_ENABLE_FAST_INTERP */
+ break;
+ }
+
+ case WASM_OP_SET_GLOBAL:
+ {
+ bool is_mutable = false;
+
+ p_org = p - 1;
+ read_leb_uint32(p, p_end, global_idx);
+ if (global_idx >= global_count) {
+ set_error_buf(error_buf, error_buf_size, "unknown global");
+ goto fail;
+ }
+
+ is_mutable =
+ global_idx < module->import_global_count
+ ? module->import_globals[global_idx].u.global.is_mutable
+ : module
+ ->globals[global_idx
+ - module->import_global_count]
+ .is_mutable;
+ if (!is_mutable) {
+ set_error_buf(error_buf, error_buf_size,
+ "global is immutable");
+ goto fail;
+ }
+
+ global_type =
+ global_idx < module->import_global_count
+ ? module->import_globals[global_idx].u.global.type
+ : module
+ ->globals[global_idx
+ - module->import_global_count]
+ .type;
+
+ POP_TYPE(global_type);
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ if (global_type == VALUE_TYPE_I64
+ || global_type == VALUE_TYPE_F64) {
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!record_fast_op(module, p_org, *p_org, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#endif
+ *p_org = WASM_OP_SET_GLOBAL_64;
+ }
+ else if (module->aux_stack_size > 0
+ && global_idx == module->aux_stack_top_global_index) {
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!record_fast_op(module, p_org, *p_org, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#endif
+ *p_org = WASM_OP_SET_GLOBAL_AUX_STACK;
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_set_global_aux_stack = true;
+#endif
+ }
+#else /* else of WASM_ENABLE_FAST_INTERP */
+ if (global_type == VALUE_TYPE_I64
+ || global_type == VALUE_TYPE_F64) {
+ skip_label();
+ emit_label(WASM_OP_SET_GLOBAL_64);
+ }
+ else if (module->aux_stack_size > 0
+ && global_idx == module->aux_stack_top_global_index) {
+ skip_label();
+ emit_label(WASM_OP_SET_GLOBAL_AUX_STACK);
+ }
+ emit_uint32(loader_ctx, global_idx);
+ POP_OFFSET_TYPE(global_type);
+#endif /* end of WASM_ENABLE_FAST_INTERP */
+ break;
+ }
+
+ /* load */
+ case WASM_OP_I32_LOAD:
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ case WASM_OP_I64_LOAD:
+ case WASM_OP_I64_LOAD8_S:
+ case WASM_OP_I64_LOAD8_U:
+ case WASM_OP_I64_LOAD16_S:
+ case WASM_OP_I64_LOAD16_U:
+ case WASM_OP_I64_LOAD32_S:
+ case WASM_OP_I64_LOAD32_U:
+ case WASM_OP_F32_LOAD:
+ case WASM_OP_F64_LOAD:
+ /* store */
+ case WASM_OP_I32_STORE:
+ case WASM_OP_I32_STORE8:
+ case WASM_OP_I32_STORE16:
+ case WASM_OP_I64_STORE:
+ case WASM_OP_I64_STORE8:
+ case WASM_OP_I64_STORE16:
+ case WASM_OP_I64_STORE32:
+ case WASM_OP_F32_STORE:
+ case WASM_OP_F64_STORE:
+ {
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* change F32/F64 into I32/I64 */
+ if (opcode == WASM_OP_F32_LOAD) {
+ skip_label();
+ emit_label(WASM_OP_I32_LOAD);
+ }
+ else if (opcode == WASM_OP_F64_LOAD) {
+ skip_label();
+ emit_label(WASM_OP_I64_LOAD);
+ }
+ else if (opcode == WASM_OP_F32_STORE) {
+ skip_label();
+ emit_label(WASM_OP_I32_STORE);
+ }
+ else if (opcode == WASM_OP_F64_STORE) {
+ skip_label();
+ emit_label(WASM_OP_I64_STORE);
+ }
+#endif
+ CHECK_MEMORY();
+ read_leb_uint32(p, p_end, align); /* align */
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+ if (!check_memory_access_align(opcode, align, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, mem_offset);
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ switch (opcode) {
+ /* load */
+ case WASM_OP_I32_LOAD:
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_I64_LOAD:
+ case WASM_OP_I64_LOAD8_S:
+ case WASM_OP_I64_LOAD8_U:
+ case WASM_OP_I64_LOAD16_S:
+ case WASM_OP_I64_LOAD16_U:
+ case WASM_OP_I64_LOAD32_S:
+ case WASM_OP_I64_LOAD32_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
+ break;
+ case WASM_OP_F32_LOAD:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
+ break;
+ case WASM_OP_F64_LOAD:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
+ break;
+ /* store */
+ case WASM_OP_I32_STORE:
+ case WASM_OP_I32_STORE8:
+ case WASM_OP_I32_STORE16:
+ POP_I32();
+ POP_I32();
+ break;
+ case WASM_OP_I64_STORE:
+ case WASM_OP_I64_STORE8:
+ case WASM_OP_I64_STORE16:
+ case WASM_OP_I64_STORE32:
+ POP_I64();
+ POP_I32();
+ break;
+ case WASM_OP_F32_STORE:
+ POP_F32();
+ POP_I32();
+ break;
+ case WASM_OP_F64_STORE:
+ POP_F64();
+ POP_I32();
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case WASM_OP_MEMORY_SIZE:
+ CHECK_MEMORY();
+ /* reserved byte 0x00 */
+ if (*p++ != 0x00) {
+ set_error_buf(error_buf, error_buf_size,
+ "zero byte expected");
+ goto fail;
+ }
+ PUSH_I32();
+
+ module->possible_memory_grow = true;
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+
+ case WASM_OP_MEMORY_GROW:
+ CHECK_MEMORY();
+ /* reserved byte 0x00 */
+ if (*p++ != 0x00) {
+ set_error_buf(error_buf, error_buf_size,
+ "zero byte expected");
+ goto fail;
+ }
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+
+ module->possible_memory_grow = true;
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_memory_grow = true;
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+
+ case WASM_OP_I32_CONST:
+ read_leb_int32(p, p_end, i32_const);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ GET_CONST_OFFSET(VALUE_TYPE_I32, i32_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_I32_CONST);
+ emit_uint32(loader_ctx, i32_const);
+ }
+#else
+ (void)i32_const;
+#endif
+ PUSH_I32();
+ break;
+
+ case WASM_OP_I64_CONST:
+ read_leb_int64(p, p_end, i64_const);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ GET_CONST_OFFSET(VALUE_TYPE_I64, i64_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_I64_CONST);
+ emit_uint64(loader_ctx, i64_const);
+ }
+#endif
+ PUSH_I64();
+ break;
+
+ case WASM_OP_F32_CONST:
+ p += sizeof(float32);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ bh_memcpy_s((uint8 *)&f32_const, sizeof(float32), p_org,
+ sizeof(float32));
+ GET_CONST_F32_OFFSET(VALUE_TYPE_F32, f32_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_F32_CONST);
+ emit_float32(loader_ctx, f32_const);
+ }
+#endif
+ PUSH_F32();
+ break;
+
+ case WASM_OP_F64_CONST:
+ p += sizeof(float64);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ /* Some MCU may require 8-byte align */
+ bh_memcpy_s((uint8 *)&f64_const, sizeof(float64), p_org,
+ sizeof(float64));
+ GET_CONST_F64_OFFSET(VALUE_TYPE_F64, f64_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_F64_CONST);
+ emit_float64(loader_ctx, f64_const);
+ }
+#endif
+ PUSH_F64();
+ break;
+
+ case WASM_OP_I32_EQZ:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_EQZ:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
+ break;
+
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I32_CLZ:
+ case WASM_OP_I32_CTZ:
+ case WASM_OP_I32_POPCNT:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ 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:
+ case WASM_OP_I32_AND:
+ case WASM_OP_I32_OR:
+ case WASM_OP_I32_XOR:
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_CLZ:
+ case WASM_OP_I64_CTZ:
+ case WASM_OP_I64_POPCNT:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
+ 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:
+ case WASM_OP_I64_AND:
+ case WASM_OP_I64_OR:
+ case WASM_OP_I64_XOR:
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
+ 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:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F32);
+ 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:
+ case WASM_OP_F32_COPYSIGN:
+ POP2_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F32);
+ 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:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F64);
+ 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:
+ case WASM_OP_F64_COPYSIGN:
+ POP2_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_I32_WRAP_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I32_TRUNC_S_F32:
+ case WASM_OP_I32_TRUNC_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I32_TRUNC_S_F64:
+ case WASM_OP_I32_TRUNC_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_EXTEND_S_I32:
+ case WASM_OP_I64_EXTEND_U_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_I64_TRUNC_S_F32:
+ case WASM_OP_I64_TRUNC_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_I64_TRUNC_S_F64:
+ case WASM_OP_I64_TRUNC_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_F32_CONVERT_S_I32:
+ case WASM_OP_F32_CONVERT_U_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F32_CONVERT_S_I64:
+ case WASM_OP_F32_CONVERT_U_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F32_DEMOTE_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F64_CONVERT_S_I32:
+ case WASM_OP_F64_CONVERT_U_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_F64_CONVERT_S_I64:
+ case WASM_OP_F64_CONVERT_U_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_F64_PROMOTE_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_I32_REINTERPRET_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_REINTERPRET_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_F32_REINTERPRET_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F64_REINTERPRET_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_I32_EXTEND8_S:
+ case WASM_OP_I32_EXTEND16_S:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_EXTEND8_S:
+ case WASM_OP_I64_EXTEND16_S:
+ case WASM_OP_I64_EXTEND32_S:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_MISC_PREFIX:
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(p, p_end, opcode1);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_byte(loader_ctx, ((uint8)opcode1));
+#endif
+ switch (opcode1) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ {
+ read_leb_uint32(p, p_end, data_seg_idx);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, data_seg_idx);
+#endif
+ if (module->import_memory_count == 0
+ && module->memory_count == 0)
+ goto fail_unknown_memory;
+
+ if (*p++ != 0x00)
+ goto fail_zero_byte_expected;
+
+ if (data_seg_idx >= module->data_seg_count) {
+ set_error_buf_v(error_buf, error_buf_size,
+ "unknown data segment %d",
+ data_seg_idx);
+ goto fail;
+ }
+
+ if (module->data_seg_count1 == 0)
+ goto fail_data_cnt_sec_require;
+
+ POP_I32();
+ POP_I32();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ case WASM_OP_DATA_DROP:
+ {
+ read_leb_uint32(p, p_end, data_seg_idx);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, data_seg_idx);
+#endif
+ if (data_seg_idx >= module->data_seg_count) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown data segment");
+ goto fail;
+ }
+
+ if (module->data_seg_count1 == 0)
+ goto fail_data_cnt_sec_require;
+
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ case WASM_OP_MEMORY_COPY:
+ {
+ /* both src and dst memory index should be 0 */
+ if (*(int16 *)p != 0x0000)
+ goto fail_zero_byte_expected;
+ p += 2;
+
+ if (module->import_memory_count == 0
+ && module->memory_count == 0)
+ goto fail_unknown_memory;
+
+ POP_I32();
+ POP_I32();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ case WASM_OP_MEMORY_FILL:
+ {
+ if (*p++ != 0x00) {
+ goto fail_zero_byte_expected;
+ }
+ if (module->import_memory_count == 0
+ && module->memory_count == 0) {
+ goto fail_unknown_memory;
+ }
+
+ POP_I32();
+ POP_I32();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ fail_zero_byte_expected:
+ set_error_buf(error_buf, error_buf_size,
+ "zero byte expected");
+ goto fail;
+
+ fail_unknown_memory:
+ set_error_buf(error_buf, error_buf_size,
+ "unknown memory 0");
+ goto fail;
+ fail_data_cnt_sec_require:
+ set_error_buf(error_buf, error_buf_size,
+ "data count section required");
+ goto fail;
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ {
+ uint8 seg_ref_type = 0, tbl_ref_type = 0;
+
+ read_leb_uint32(p, p_end, table_seg_idx);
+ read_leb_uint32(p, p_end, table_idx);
+
+ if (!get_table_elem_type(module, table_idx,
+ &tbl_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (!get_table_seg_elem_type(module, table_seg_idx,
+ &seg_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (seg_ref_type != tbl_ref_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch");
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_seg_idx);
+ emit_uint32(loader_ctx, table_idx);
+#endif
+ POP_I32();
+ POP_I32();
+ POP_I32();
+ break;
+ }
+ case WASM_OP_ELEM_DROP:
+ {
+ read_leb_uint32(p, p_end, table_seg_idx);
+ if (!get_table_seg_elem_type(module, table_seg_idx,
+ NULL, error_buf,
+ error_buf_size))
+ goto fail;
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_seg_idx);
+#endif
+ break;
+ }
+ case WASM_OP_TABLE_COPY:
+ {
+ uint8 src_ref_type, dst_ref_type;
+ uint32 src_tbl_idx, dst_tbl_idx;
+
+ read_leb_uint32(p, p_end, src_tbl_idx);
+ if (!get_table_elem_type(module, src_tbl_idx,
+ &src_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ read_leb_uint32(p, p_end, dst_tbl_idx);
+ if (!get_table_elem_type(module, dst_tbl_idx,
+ &dst_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (src_ref_type != dst_ref_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch");
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, src_tbl_idx);
+ emit_uint32(loader_ctx, dst_tbl_idx);
+#endif
+ POP_I32();
+ POP_I32();
+ POP_I32();
+ break;
+ }
+ case WASM_OP_TABLE_SIZE:
+ {
+ read_leb_uint32(p, p_end, table_idx);
+ /* TODO: shall we create a new function to check
+ table idx instead of using below function? */
+ if (!get_table_elem_type(module, table_idx, NULL,
+ error_buf, error_buf_size))
+ goto fail;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ PUSH_I32();
+ break;
+ }
+ case WASM_OP_TABLE_GROW:
+ case WASM_OP_TABLE_FILL:
+ {
+ uint8 decl_ref_type;
+
+ read_leb_uint32(p, p_end, table_idx);
+ if (!get_table_elem_type(module, table_idx,
+ &decl_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (opcode1 == WASM_OP_TABLE_GROW) {
+ if (table_idx < module->import_table_count) {
+ module->import_tables[table_idx]
+ .u.table.possible_grow = true;
+ }
+ else {
+ module
+ ->tables[table_idx
+ - module->import_table_count]
+ .possible_grow = true;
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ POP_I32();
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(decl_ref_type);
+#endif
+ POP_TYPE(decl_ref_type);
+ if (opcode1 == WASM_OP_TABLE_GROW)
+ PUSH_I32();
+ else
+ POP_I32();
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ set_error_buf_v(error_buf, error_buf_size,
+ "%s %02x %02x", "unsupported opcode",
+ 0xfc, opcode1);
+ goto fail;
+ }
+ break;
+ }
+
+#if WASM_ENABLE_SIMD != 0
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ case WASM_OP_SIMD_PREFIX:
+ {
+ opcode = read_uint8(p);
+ /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h
+ */
+ switch (opcode) {
+ /* memory instruction */
+ case SIMD_v128_load:
+ case SIMD_v128_load8x8_s:
+ case SIMD_v128_load8x8_u:
+ case SIMD_v128_load16x4_s:
+ case SIMD_v128_load16x4_u:
+ case SIMD_v128_load32x2_s:
+ case SIMD_v128_load32x2_u:
+ case SIMD_v128_load8_splat:
+ case SIMD_v128_load16_splat:
+ case SIMD_v128_load32_splat:
+ case SIMD_v128_load64_splat:
+ {
+ CHECK_MEMORY();
+
+ read_leb_uint32(p, p_end, align); /* align */
+ if (!check_simd_memory_access_align(
+ opcode, align, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_V128);
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+
+ case SIMD_v128_store:
+ {
+ CHECK_MEMORY();
+
+ read_leb_uint32(p, p_end, align); /* align */
+ if (!check_simd_memory_access_align(
+ opcode, align, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+
+ POP_V128();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+
+ /* basic operation */
+ case SIMD_v128_const:
+ {
+ CHECK_BUF1(p, p_end, 16);
+ p += 16;
+ PUSH_V128();
+ break;
+ }
+
+ case SIMD_v8x16_shuffle:
+ {
+ V128 mask;
+
+ CHECK_BUF1(p, p_end, 16);
+ mask = read_i8x16(p, error_buf, error_buf_size);
+ p += 16;
+ if (!check_simd_shuffle_mask(mask, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_v8x16_swizzle:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* splat operation */
+ case SIMD_i8x16_splat:
+ case SIMD_i16x8_splat:
+ case SIMD_i32x4_splat:
+ case SIMD_i64x2_splat:
+ case SIMD_f32x4_splat:
+ case SIMD_f64x2_splat:
+ {
+ uint8 pop_type[] = { VALUE_TYPE_I32, VALUE_TYPE_I32,
+ VALUE_TYPE_I32, VALUE_TYPE_I64,
+ VALUE_TYPE_F32, VALUE_TYPE_F64 };
+ POP_AND_PUSH(pop_type[opcode - SIMD_i8x16_splat],
+ VALUE_TYPE_V128);
+ break;
+ }
+
+ /* lane operation */
+ case SIMD_i8x16_extract_lane_s:
+ case SIMD_i8x16_extract_lane_u:
+ case SIMD_i8x16_replace_lane:
+ case SIMD_i16x8_extract_lane_s:
+ case SIMD_i16x8_extract_lane_u:
+ case SIMD_i16x8_replace_lane:
+ case SIMD_i32x4_extract_lane:
+ case SIMD_i32x4_replace_lane:
+ case SIMD_i64x2_extract_lane:
+ case SIMD_i64x2_replace_lane:
+ case SIMD_f32x4_extract_lane:
+ case SIMD_f32x4_replace_lane:
+ case SIMD_f64x2_extract_lane:
+ case SIMD_f64x2_replace_lane:
+ {
+ uint8 lane;
+ /* clang-format off */
+ uint8 replace[] = {
+ /*i8x16*/ 0x0, 0x0, VALUE_TYPE_I32,
+ /*i16x8*/ 0x0, 0x0, VALUE_TYPE_I32,
+ /*i32x4*/ 0x0, VALUE_TYPE_I32,
+ /*i64x2*/ 0x0, VALUE_TYPE_I64,
+ /*f32x4*/ 0x0, VALUE_TYPE_F32,
+ /*f64x2*/ 0x0, VALUE_TYPE_F64,
+ };
+ uint8 push_type[] = {
+ /*i8x16*/ VALUE_TYPE_I32, VALUE_TYPE_I32,
+ VALUE_TYPE_V128,
+ /*i16x8*/ VALUE_TYPE_I32, VALUE_TYPE_I32,
+ VALUE_TYPE_V128,
+ /*i32x4*/ VALUE_TYPE_I32, VALUE_TYPE_V128,
+ /*i64x2*/ VALUE_TYPE_I64, VALUE_TYPE_V128,
+ /*f32x4*/ VALUE_TYPE_F32, VALUE_TYPE_V128,
+ /*f64x2*/ VALUE_TYPE_F64, VALUE_TYPE_V128,
+ };
+ /* clang-format on */
+
+ CHECK_BUF(p, p_end, 1);
+ lane = read_uint8(p);
+ if (!check_simd_access_lane(opcode, lane, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ if (replace[opcode - SIMD_i8x16_extract_lane_s]) {
+ if (!(wasm_loader_pop_frame_ref(
+ loader_ctx,
+ replace[opcode - SIMD_i8x16_extract_lane_s],
+ error_buf, error_buf_size)))
+ goto fail;
+ }
+
+ POP_AND_PUSH(
+ VALUE_TYPE_V128,
+ push_type[opcode - SIMD_i8x16_extract_lane_s]);
+ break;
+ }
+
+ /* i8x16 compare operation */
+ case SIMD_i8x16_eq:
+ case SIMD_i8x16_ne:
+ case SIMD_i8x16_lt_s:
+ case SIMD_i8x16_lt_u:
+ case SIMD_i8x16_gt_s:
+ case SIMD_i8x16_gt_u:
+ case SIMD_i8x16_le_s:
+ case SIMD_i8x16_le_u:
+ case SIMD_i8x16_ge_s:
+ case SIMD_i8x16_ge_u:
+ /* i16x8 compare operation */
+ case SIMD_i16x8_eq:
+ case SIMD_i16x8_ne:
+ case SIMD_i16x8_lt_s:
+ case SIMD_i16x8_lt_u:
+ case SIMD_i16x8_gt_s:
+ case SIMD_i16x8_gt_u:
+ case SIMD_i16x8_le_s:
+ case SIMD_i16x8_le_u:
+ case SIMD_i16x8_ge_s:
+ case SIMD_i16x8_ge_u:
+ /* i32x4 compare operation */
+ case SIMD_i32x4_eq:
+ case SIMD_i32x4_ne:
+ case SIMD_i32x4_lt_s:
+ case SIMD_i32x4_lt_u:
+ case SIMD_i32x4_gt_s:
+ case SIMD_i32x4_gt_u:
+ case SIMD_i32x4_le_s:
+ case SIMD_i32x4_le_u:
+ case SIMD_i32x4_ge_s:
+ case SIMD_i32x4_ge_u:
+ /* f32x4 compare operation */
+ case SIMD_f32x4_eq:
+ case SIMD_f32x4_ne:
+ case SIMD_f32x4_lt:
+ case SIMD_f32x4_gt:
+ case SIMD_f32x4_le:
+ case SIMD_f32x4_ge:
+ /* f64x2 compare operation */
+ case SIMD_f64x2_eq:
+ case SIMD_f64x2_ne:
+ case SIMD_f64x2_lt:
+ case SIMD_f64x2_gt:
+ case SIMD_f64x2_le:
+ case SIMD_f64x2_ge:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* v128 operation */
+ case SIMD_v128_not:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_v128_and:
+ case SIMD_v128_andnot:
+ case SIMD_v128_or:
+ case SIMD_v128_xor:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_v128_bitselect:
+ {
+ POP_V128();
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_v128_any_true:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32);
+ break;
+ }
+
+ /* Load Lane Operation */
+ case SIMD_v128_load8_lane:
+ case SIMD_v128_load16_lane:
+ case SIMD_v128_load32_lane:
+ case SIMD_v128_load64_lane:
+ case SIMD_v128_store8_lane:
+ case SIMD_v128_store16_lane:
+ case SIMD_v128_store32_lane:
+ case SIMD_v128_store64_lane:
+ {
+ uint8 lane;
+
+ CHECK_MEMORY();
+
+ read_leb_uint32(p, p_end, align); /* align */
+ if (!check_simd_memory_access_align(
+ opcode, align, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+
+ CHECK_BUF(p, p_end, 1);
+ lane = read_uint8(p);
+ if (!check_simd_access_lane(opcode, lane, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ POP_V128();
+ POP_I32();
+ if (opcode < SIMD_v128_store8_lane) {
+ PUSH_V128();
+ }
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+
+ case SIMD_v128_load32_zero:
+ case SIMD_v128_load64_zero:
+ {
+ CHECK_MEMORY();
+
+ read_leb_uint32(p, p_end, align); /* align */
+ if (!check_simd_memory_access_align(
+ opcode, align, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_V128);
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+
+ /* Float conversion */
+ case SIMD_f32x4_demote_f64x2_zero:
+ case SIMD_f64x2_promote_low_f32x4_zero:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* i8x16 Operation */
+ case SIMD_i8x16_abs:
+ case SIMD_i8x16_neg:
+ case SIMD_i8x16_popcnt:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i8x16_all_true:
+ case SIMD_i8x16_bitmask:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32);
+ break;
+ }
+
+ case SIMD_i8x16_narrow_i16x8_s:
+ case SIMD_i8x16_narrow_i16x8_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_f32x4_ceil:
+ case SIMD_f32x4_floor:
+ case SIMD_f32x4_trunc:
+ case SIMD_f32x4_nearest:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i8x16_shl:
+ case SIMD_i8x16_shr_s:
+ case SIMD_i8x16_shr_u:
+ {
+ POP_I32();
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i8x16_add:
+ case SIMD_i8x16_add_sat_s:
+ case SIMD_i8x16_add_sat_u:
+ case SIMD_i8x16_sub:
+ case SIMD_i8x16_sub_sat_s:
+ case SIMD_i8x16_sub_sat_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_f64x2_ceil:
+ case SIMD_f64x2_floor:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i8x16_min_s:
+ case SIMD_i8x16_min_u:
+ case SIMD_i8x16_max_s:
+ case SIMD_i8x16_max_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_f64x2_trunc:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i8x16_avgr_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_extadd_pairwise_i8x16_s:
+ case SIMD_i16x8_extadd_pairwise_i8x16_u:
+ case SIMD_i32x4_extadd_pairwise_i16x8_s:
+ case SIMD_i32x4_extadd_pairwise_i16x8_u:
+ /* i16x8 operation */
+ case SIMD_i16x8_abs:
+ case SIMD_i16x8_neg:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_q15mulr_sat_s:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_all_true:
+ case SIMD_i16x8_bitmask:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32);
+ break;
+ }
+
+ case SIMD_i16x8_narrow_i32x4_s:
+ case SIMD_i16x8_narrow_i32x4_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_extend_low_i8x16_s:
+ case SIMD_i16x8_extend_high_i8x16_s:
+ case SIMD_i16x8_extend_low_i8x16_u:
+ case SIMD_i16x8_extend_high_i8x16_u:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_shl:
+ case SIMD_i16x8_shr_s:
+ case SIMD_i16x8_shr_u:
+ {
+ POP_I32();
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_add:
+ case SIMD_i16x8_add_sat_s:
+ case SIMD_i16x8_add_sat_u:
+ case SIMD_i16x8_sub:
+ case SIMD_i16x8_sub_sat_s:
+ case SIMD_i16x8_sub_sat_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_f64x2_nearest:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i16x8_mul:
+ case SIMD_i16x8_min_s:
+ case SIMD_i16x8_min_u:
+ case SIMD_i16x8_max_s:
+ case SIMD_i16x8_max_u:
+ case SIMD_i16x8_avgr_u:
+ case SIMD_i16x8_extmul_low_i8x16_s:
+ case SIMD_i16x8_extmul_high_i8x16_s:
+ case SIMD_i16x8_extmul_low_i8x16_u:
+ case SIMD_i16x8_extmul_high_i8x16_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* i32x4 operation */
+ case SIMD_i32x4_abs:
+ case SIMD_i32x4_neg:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i32x4_all_true:
+ case SIMD_i32x4_bitmask:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32);
+ break;
+ }
+
+ case SIMD_i32x4_narrow_i64x2_s:
+ case SIMD_i32x4_narrow_i64x2_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i32x4_extend_low_i16x8_s:
+ case SIMD_i32x4_extend_high_i16x8_s:
+ case SIMD_i32x4_extend_low_i16x8_u:
+ case SIMD_i32x4_extend_high_i16x8_u:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i32x4_shl:
+ case SIMD_i32x4_shr_s:
+ case SIMD_i32x4_shr_u:
+ {
+ POP_I32();
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i32x4_add:
+ case SIMD_i32x4_sub:
+ case SIMD_i32x4_mul:
+ case SIMD_i32x4_min_s:
+ case SIMD_i32x4_min_u:
+ case SIMD_i32x4_max_s:
+ case SIMD_i32x4_max_u:
+ case SIMD_i32x4_dot_i16x8_s:
+ case SIMD_i32x4_avgr_u:
+ case SIMD_i32x4_extmul_low_i16x8_s:
+ case SIMD_i32x4_extmul_high_i16x8_s:
+ case SIMD_i32x4_extmul_low_i16x8_u:
+ case SIMD_i32x4_extmul_high_i16x8_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* i64x2 operation */
+ case SIMD_i64x2_abs:
+ case SIMD_i64x2_neg:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i64x2_all_true:
+ case SIMD_i64x2_bitmask:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32);
+ break;
+ }
+
+ case SIMD_i64x2_extend_low_i32x4_s:
+ case SIMD_i64x2_extend_high_i32x4_s:
+ case SIMD_i64x2_extend_low_i32x4_u:
+ case SIMD_i64x2_extend_high_i32x4_u:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i64x2_shl:
+ case SIMD_i64x2_shr_s:
+ case SIMD_i64x2_shr_u:
+ {
+ POP_I32();
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i64x2_add:
+ case SIMD_i64x2_sub:
+ case SIMD_i64x2_mul:
+ case SIMD_i64x2_eq:
+ case SIMD_i64x2_ne:
+ case SIMD_i64x2_lt_s:
+ case SIMD_i64x2_gt_s:
+ case SIMD_i64x2_le_s:
+ case SIMD_i64x2_ge_s:
+ case SIMD_i64x2_extmul_low_i32x4_s:
+ case SIMD_i64x2_extmul_high_i32x4_s:
+ case SIMD_i64x2_extmul_low_i32x4_u:
+ case SIMD_i64x2_extmul_high_i32x4_u:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* f32x4 operation */
+ case SIMD_f32x4_abs:
+ case SIMD_f32x4_neg:
+ case SIMD_f32x4_round:
+ case SIMD_f32x4_sqrt:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_f32x4_add:
+ case SIMD_f32x4_sub:
+ case SIMD_f32x4_mul:
+ case SIMD_f32x4_div:
+ case SIMD_f32x4_min:
+ case SIMD_f32x4_max:
+ case SIMD_f32x4_pmin:
+ case SIMD_f32x4_pmax:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ /* f64x2 operation */
+ case SIMD_f64x2_abs:
+ case SIMD_f64x2_neg:
+ case SIMD_f64x2_round:
+ case SIMD_f64x2_sqrt:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_f64x2_add:
+ case SIMD_f64x2_sub:
+ case SIMD_f64x2_mul:
+ case SIMD_f64x2_div:
+ case SIMD_f64x2_min:
+ case SIMD_f64x2_max:
+ case SIMD_f64x2_pmin:
+ case SIMD_f64x2_pmax:
+ {
+ POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ case SIMD_i32x4_trunc_sat_f32x4_s:
+ case SIMD_i32x4_trunc_sat_f32x4_u:
+ case SIMD_f32x4_convert_i32x4_s:
+ case SIMD_f32x4_convert_i32x4_u:
+ case SIMD_i32x4_trunc_sat_f64x2_s_zero:
+ case SIMD_i32x4_trunc_sat_f64x2_u_zero:
+ case SIMD_f64x2_convert_low_i32x4_s:
+ case SIMD_f64x2_convert_low_i32x4_u:
+ {
+ POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
+ break;
+ }
+
+ default:
+ {
+ if (error_buf != NULL) {
+ snprintf(error_buf, error_buf_size,
+ "WASM module load failed: "
+ "invalid opcode 0xfd %02x.",
+ opcode);
+ }
+ goto fail;
+ }
+ }
+ break;
+ }
+#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
+#endif /* end of WASM_ENABLE_SIMD */
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case WASM_OP_ATOMIC_PREFIX:
+ {
+ opcode = read_uint8(p);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_byte(loader_ctx, opcode);
+#endif
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ CHECK_MEMORY();
+ read_leb_uint32(p, p_end, align); /* align */
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+ if (!check_memory_align_equal(opcode, align, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, mem_offset);
+#endif
+ }
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ switch (opcode) {
+ case WASM_OP_ATOMIC_NOTIFY:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_ATOMIC_WAIT32:
+ POP_I64();
+ POP_I32();
+ POP_I32();
+ PUSH_I32();
+ break;
+ case WASM_OP_ATOMIC_WAIT64:
+ POP_I64();
+ POP_I64();
+ POP_I32();
+ PUSH_I32();
+ break;
+ case WASM_OP_ATOMIC_FENCE:
+ /* reserved byte 0x00 */
+ if (*p++ != 0x00) {
+ set_error_buf(error_buf, error_buf_size,
+ "zero byte expected");
+ goto fail;
+ }
+ break;
+ case WASM_OP_ATOMIC_I32_LOAD:
+ case WASM_OP_ATOMIC_I32_LOAD8_U:
+ case WASM_OP_ATOMIC_I32_LOAD16_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_ATOMIC_I32_STORE:
+ case WASM_OP_ATOMIC_I32_STORE8:
+ case WASM_OP_ATOMIC_I32_STORE16:
+ POP_I32();
+ POP_I32();
+ break;
+ case WASM_OP_ATOMIC_I64_LOAD:
+ case WASM_OP_ATOMIC_I64_LOAD8_U:
+ case WASM_OP_ATOMIC_I64_LOAD16_U:
+ case WASM_OP_ATOMIC_I64_LOAD32_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
+ break;
+ case WASM_OP_ATOMIC_I64_STORE:
+ case WASM_OP_ATOMIC_I64_STORE8:
+ case WASM_OP_ATOMIC_I64_STORE16:
+ case WASM_OP_ATOMIC_I64_STORE32:
+ POP_I64();
+ POP_I32();
+ break;
+ case WASM_OP_ATOMIC_RMW_I32_ADD:
+ case WASM_OP_ATOMIC_RMW_I32_ADD8_U:
+ case WASM_OP_ATOMIC_RMW_I32_ADD16_U:
+ case WASM_OP_ATOMIC_RMW_I32_SUB:
+ case WASM_OP_ATOMIC_RMW_I32_SUB8_U:
+ case WASM_OP_ATOMIC_RMW_I32_SUB16_U:
+ case WASM_OP_ATOMIC_RMW_I32_AND:
+ case WASM_OP_ATOMIC_RMW_I32_AND8_U:
+ case WASM_OP_ATOMIC_RMW_I32_AND16_U:
+ case WASM_OP_ATOMIC_RMW_I32_OR:
+ case WASM_OP_ATOMIC_RMW_I32_OR8_U:
+ case WASM_OP_ATOMIC_RMW_I32_OR16_U:
+ case WASM_OP_ATOMIC_RMW_I32_XOR:
+ case WASM_OP_ATOMIC_RMW_I32_XOR8_U:
+ case WASM_OP_ATOMIC_RMW_I32_XOR16_U:
+ case WASM_OP_ATOMIC_RMW_I32_XCHG:
+ case WASM_OP_ATOMIC_RMW_I32_XCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I32_XCHG16_U:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_ATOMIC_RMW_I64_ADD:
+ case WASM_OP_ATOMIC_RMW_I64_ADD8_U:
+ case WASM_OP_ATOMIC_RMW_I64_ADD16_U:
+ case WASM_OP_ATOMIC_RMW_I64_ADD32_U:
+ case WASM_OP_ATOMIC_RMW_I64_SUB:
+ case WASM_OP_ATOMIC_RMW_I64_SUB8_U:
+ case WASM_OP_ATOMIC_RMW_I64_SUB16_U:
+ case WASM_OP_ATOMIC_RMW_I64_SUB32_U:
+ case WASM_OP_ATOMIC_RMW_I64_AND:
+ case WASM_OP_ATOMIC_RMW_I64_AND8_U:
+ case WASM_OP_ATOMIC_RMW_I64_AND16_U:
+ case WASM_OP_ATOMIC_RMW_I64_AND32_U:
+ case WASM_OP_ATOMIC_RMW_I64_OR:
+ case WASM_OP_ATOMIC_RMW_I64_OR8_U:
+ case WASM_OP_ATOMIC_RMW_I64_OR16_U:
+ case WASM_OP_ATOMIC_RMW_I64_OR32_U:
+ case WASM_OP_ATOMIC_RMW_I64_XOR:
+ case WASM_OP_ATOMIC_RMW_I64_XOR8_U:
+ case WASM_OP_ATOMIC_RMW_I64_XOR16_U:
+ case WASM_OP_ATOMIC_RMW_I64_XOR32_U:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG16_U:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG32_U:
+ POP_I64();
+ POP_I32();
+ PUSH_I64();
+ break;
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
+ POP_I32();
+ POP_I32();
+ POP_I32();
+ PUSH_I32();
+ break;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
+ POP_I64();
+ POP_I64();
+ POP_I32();
+ PUSH_I64();
+ break;
+ default:
+ set_error_buf_v(error_buf, error_buf_size,
+ "%s %02x %02x", "unsupported opcode",
+ 0xfe, opcode);
+ goto fail;
+ }
+ break;
+ }
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
+
+ default:
+ set_error_buf_v(error_buf, error_buf_size, "%s %02x",
+ "unsupported opcode", opcode);
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ last_op = opcode;
+#endif
+ }
+
+ if (loader_ctx->csp_num > 0) {
+ if (cur_func_idx < module->function_count - 1)
+ /* Function with missing end marker (between two functions) */
+ set_error_buf(error_buf, error_buf_size, "END opcode expected");
+ else
+ /* Function with missing end marker
+ (at EOF or end of code sections) */
+ set_error_buf(error_buf, error_buf_size,
+ "unexpected end of section or function, "
+ "or section size mismatch");
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (loader_ctx->p_code_compiled == NULL)
+ goto re_scan;
+
+ func->const_cell_num = loader_ctx->const_cell_num;
+ if (func->const_cell_num > 0) {
+ int32 j;
+
+ if (!(func->consts = func_const = loader_malloc(
+ func->const_cell_num * 4, error_buf, error_buf_size)))
+ goto fail;
+
+ func_const_end = func->consts + func->const_cell_num * 4;
+ /* reverse the const buf */
+ for (j = loader_ctx->num_const - 1; j >= 0; j--) {
+ Const *c = (Const *)(loader_ctx->const_buf + j * sizeof(Const));
+ if (c->value_type == VALUE_TYPE_F64
+ || c->value_type == VALUE_TYPE_I64) {
+ bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
+ &(c->value.f64), (uint32)sizeof(int64));
+ func_const += sizeof(int64);
+ }
+ else {
+ bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
+ &(c->value.f32), (uint32)sizeof(int32));
+ func_const += sizeof(int32);
+ }
+ }
+ }
+
+ func->max_stack_cell_num = loader_ctx->preserved_local_offset
+ - loader_ctx->start_dynamic_offset + 1;
+#else
+ func->max_stack_cell_num = loader_ctx->max_stack_cell_num;
+#endif
+ func->max_block_num = loader_ctx->max_csp_num;
+ return_value = true;
+
+fail:
+ wasm_loader_ctx_destroy(loader_ctx);
+
+ (void)table_idx;
+ (void)table_seg_idx;
+ (void)data_seg_idx;
+ (void)i64_const;
+ (void)local_offset;
+ (void)p_org;
+ (void)mem_offset;
+ (void)align;
+ return return_value;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.h
new file mode 100644
index 000000000..8b0dc77d6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_loader.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#ifndef _WASM_LOADER_H
+#define _WASM_LOADER_H
+
+#include "wasm.h"
+#include "bh_hashmap.h"
+#include "../common/wasm_runtime_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Load a WASM module from a specified byte buffer.
+ *
+ * @param buf the byte buffer which contains the WASM binary data
+ * @param size the size of the buffer
+ * @param error_buf output of the exception info
+ * @param error_buf_size the size of the exception string
+ *
+ * @return return module loaded, NULL if failed
+ */
+WASMModule *
+wasm_loader_load(uint8 *buf, uint32 size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+ bool main_module,
+#endif
+ char *error_buf, uint32 error_buf_size);
+
+/**
+ * Load a WASM module from a specified WASM section list.
+ *
+ * @param section_list the section list which contains each section data
+ * @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
+ */
+WASMModule *
+wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
+ uint32 error_buf_size);
+
+/**
+ * Unload a WASM module.
+ *
+ * @param module the module to be unloaded
+ */
+void
+wasm_loader_unload(WASMModule *module);
+
+/**
+ * Find address of related else opcode and end opcode of opcode block/loop/if
+ * according to the start address of opcode.
+ *
+ * @param module the module to find
+ * @param start_addr the next address of opcode block/loop/if
+ * @param code_end_addr the end address of function code block
+ * @param block_type the type of block, 0/1/2 denotes block/loop/if
+ * @param p_else_addr returns the else addr if found
+ * @param p_end_addr returns the end addr if found
+ * @param error_buf returns the error log for this function
+ * @param error_buf_size returns the error log string length
+ *
+ * @return true if success, false otherwise
+ */
+
+bool
+wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
+ const uint8 *start_addr, const uint8 *code_end_addr,
+ uint8 block_type, uint8 **p_else_addr,
+ uint8 **p_end_addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_LOADER_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_mini_loader.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_mini_loader.c
new file mode 100644
index 000000000..aa5e18f6a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_mini_loader.c
@@ -0,0 +1,7544 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_loader.h"
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm.h"
+#include "wasm_opcode.h"
+#include "wasm_runtime.h"
+#include "../common/wasm_native.h"
+#include "../common/wasm_memory.h"
+#if WASM_ENABLE_FAST_JIT != 0
+#include "../fast-jit/jit_compiler.h"
+#include "../fast-jit/jit_codecache.h"
+#endif
+#if WASM_ENABLE_JIT != 0
+#include "../compilation/aot_llvm.h"
+#endif
+
+/* 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
+ value being read. */
+#define TEMPLATE_READ_VALUE(Type, p) \
+ (p += sizeof(Type), *(Type *)(p - sizeof(Type)))
+
+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, "WASM module load failed: %s",
+ string);
+}
+
+#define CHECK_BUF(buf, buf_end, length) \
+ do { \
+ bh_assert(buf + length >= buf && buf + length <= buf_end); \
+ } while (0)
+
+#define CHECK_BUF1(buf, buf_end, length) \
+ do { \
+ bh_assert(buf + length >= buf && buf + length <= buf_end); \
+ } while (0)
+
+#define skip_leb(p) while (*p++ & 0x80)
+#define skip_leb_int64(p, p_end) skip_leb(p)
+#define skip_leb_uint32(p, p_end) skip_leb(p)
+#define skip_leb_int32(p, p_end) skip_leb(p)
+
+static bool
+is_32bit_type(uint8 type)
+{
+ if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+#if WASM_ENABLE_REF_TYPES != 0
+ || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+#endif
+ )
+ return true;
+ return false;
+}
+
+static bool
+is_64bit_type(uint8 type)
+{
+ if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)
+ return true;
+ return false;
+}
+
+static bool
+is_value_type(uint8 type)
+{
+ if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_I64
+ || type == VALUE_TYPE_F32 || type == VALUE_TYPE_F64
+#if WASM_ENABLE_REF_TYPES != 0
+ || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+#endif
+ )
+ return true;
+ return false;
+}
+
+static bool
+is_byte_a_type(uint8 type)
+{
+ return is_value_type(type) || (type == VALUE_TYPE_VOID);
+}
+
+static void
+read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
+ uint64 *p_result, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *buf = *p_buf;
+ uint64 result = 0;
+ uint32 shift = 0;
+ uint32 offset = 0, bcnt = 0;
+ uint64 byte;
+
+ while (true) {
+ bh_assert(bcnt + 1 <= (maxbits + 6) / 7);
+ CHECK_BUF(buf, buf_end, offset + 1);
+ byte = buf[offset];
+ offset += 1;
+ result |= ((byte & 0x7f) << shift);
+ shift += 7;
+ bcnt += 1;
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ }
+
+ if (!sign && maxbits == 32 && shift >= maxbits) {
+ /* The top bits set represent values > 32 bits */
+ bh_assert(!(((uint8)byte) & 0xf0));
+ }
+ else if (sign && maxbits == 32) {
+ if (shift < maxbits) {
+ /* Sign extend, second highest bit is the sign bit */
+ if ((uint8)byte & 0x40)
+ result |= (~((uint64)0)) << shift;
+ }
+ else {
+ /* The top bits should be a sign-extension of the sign bit */
+ bool sign_bit_set = ((uint8)byte) & 0x8;
+ int top_bits = ((uint8)byte) & 0xf0;
+ bh_assert(!((sign_bit_set && top_bits != 0x70)
+ || (!sign_bit_set && top_bits != 0)));
+ (void)top_bits;
+ (void)sign_bit_set;
+ }
+ }
+ else if (sign && maxbits == 64) {
+ if (shift < maxbits) {
+ /* Sign extend, second highest bit is the sign bit */
+ if ((uint8)byte & 0x40)
+ result |= (~((uint64)0)) << shift;
+ }
+ else {
+ /* The top bits should be a sign-extension of the sign bit */
+ bool sign_bit_set = ((uint8)byte) & 0x1;
+ int top_bits = ((uint8)byte) & 0xfe;
+
+ bh_assert(!((sign_bit_set && top_bits != 0x7e)
+ || (!sign_bit_set && top_bits != 0)));
+ (void)top_bits;
+ (void)sign_bit_set;
+ }
+ }
+
+ *p_buf += offset;
+ *p_result = result;
+}
+
+#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p)
+#define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p)
+#define read_bool(p) TEMPLATE_READ_VALUE(bool, p)
+
+#define read_leb_int64(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ read_leb((uint8 **)&p, p_end, 64, true, &res64, error_buf, \
+ error_buf_size); \
+ res = (int64)res64; \
+ } while (0)
+
+#define read_leb_uint32(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ read_leb((uint8 **)&p, p_end, 32, false, &res64, error_buf, \
+ error_buf_size); \
+ res = (uint32)res64; \
+ } while (0)
+
+#define read_leb_int32(p, p_end, res) \
+ do { \
+ uint64 res64; \
+ read_leb((uint8 **)&p, p_end, 32, true, &res64, error_buf, \
+ error_buf_size); \
+ res = (int32)res64; \
+ } while (0)
+
+static void *
+loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+static char *
+const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ StringNode *node, *node_next;
+
+ if (len == 0) {
+ return "";
+ }
+ else if (is_load_from_file_buf) {
+ /* As the file buffer can be referred to after loading, we use
+ the previous byte of leb encoded size to adjust the string:
+ move string 1 byte backward and then append '\0' */
+ char *c_str = (char *)str - 1;
+ bh_memmove_s(c_str, len + 1, c_str + 1, len);
+ c_str[len] = '\0';
+ return c_str;
+ }
+
+ /* Search const str list */
+ node = module->const_str_list;
+ while (node) {
+ node_next = node->next;
+ if (strlen(node->str) == len && !memcmp(node->str, str, len))
+ break;
+ node = node_next;
+ }
+
+ if (node) {
+ LOG_DEBUG("reuse %s", node->str);
+ return node->str;
+ }
+
+ if (!(node = loader_malloc(sizeof(StringNode) + len + 1, error_buf,
+ error_buf_size))) {
+ return NULL;
+ }
+
+ node->str = ((char *)node) + sizeof(StringNode);
+ bh_memcpy_s(node->str, len + 1, str, len);
+ node->str[len] = '\0';
+
+ if (!module->const_str_list) {
+ /* set as head */
+ module->const_str_list = node;
+ node->next = NULL;
+ }
+ else {
+ /* insert it */
+ node->next = module->const_str_list;
+ module->const_str_list = node;
+ }
+
+ return node->str;
+}
+
+static void
+destroy_wasm_type(WASMType *type)
+{
+ if (type->ref_count > 1) {
+ /* The type is referenced by other types
+ of current wasm module */
+ type->ref_count--;
+ return;
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ if (type->call_to_llvm_jit_from_fast_jit)
+ jit_code_cache_free(type->call_to_llvm_jit_from_fast_jit);
+#endif
+
+ wasm_runtime_free(type);
+}
+
+static bool
+load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
+ InitializerExpression *init_expr, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint8 flag, end_byte, *p_float;
+ uint32 i;
+
+ CHECK_BUF(p, p_end, 1);
+ init_expr->init_expr_type = read_uint8(p);
+ flag = init_expr->init_expr_type;
+
+ switch (flag) {
+ /* i32.const */
+ case INIT_EXPR_TYPE_I32_CONST:
+ bh_assert(type == VALUE_TYPE_I32);
+ read_leb_int32(p, p_end, init_expr->u.i32);
+ break;
+ /* i64.const */
+ case INIT_EXPR_TYPE_I64_CONST:
+ bh_assert(type == VALUE_TYPE_I64);
+ read_leb_int64(p, p_end, init_expr->u.i64);
+ break;
+ /* f32.const */
+ case INIT_EXPR_TYPE_F32_CONST:
+ bh_assert(type == VALUE_TYPE_F32);
+ CHECK_BUF(p, p_end, 4);
+ p_float = (uint8 *)&init_expr->u.f32;
+ for (i = 0; i < sizeof(float32); i++)
+ *p_float++ = *p++;
+ break;
+ /* f64.const */
+ case INIT_EXPR_TYPE_F64_CONST:
+ bh_assert(type == VALUE_TYPE_F64);
+ CHECK_BUF(p, p_end, 8);
+ p_float = (uint8 *)&init_expr->u.f64;
+ for (i = 0; i < sizeof(float64); i++)
+ *p_float++ = *p++;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case INIT_EXPR_TYPE_FUNCREF_CONST:
+ {
+ bh_assert(type == VALUE_TYPE_FUNCREF);
+ read_leb_uint32(p, p_end, init_expr->u.ref_index);
+ break;
+ }
+ case INIT_EXPR_TYPE_REFNULL_CONST:
+ {
+ uint8 reftype;
+
+ CHECK_BUF(p, p_end, 1);
+ reftype = read_uint8(p);
+
+ bh_assert(type == reftype);
+
+ init_expr->u.ref_index = NULL_REF;
+ (void)reftype;
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+ /* get_global */
+ case INIT_EXPR_TYPE_GET_GLOBAL:
+ read_leb_uint32(p, p_end, init_expr->u.global_index);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ CHECK_BUF(p, p_end, 1);
+ end_byte = read_uint8(p);
+ bh_assert(end_byte == 0x0b);
+ *p_buf = p;
+
+ (void)end_byte;
+ return true;
+}
+
+static bool
+load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end, *p_org;
+ uint32 type_count, param_count, result_count, i, j;
+ uint32 param_cell_num, ret_cell_num;
+ uint64 total_size;
+ uint8 flag;
+ WASMType *type;
+
+ read_leb_uint32(p, p_end, type_count);
+
+ if (type_count) {
+ module->type_count = type_count;
+ total_size = sizeof(WASMType *) * (uint64)type_count;
+ if (!(module->types =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < type_count; i++) {
+ CHECK_BUF(p, p_end, 1);
+ flag = read_uint8(p);
+ bh_assert(flag == 0x60);
+
+ read_leb_uint32(p, p_end, param_count);
+
+ /* Resolve param count and result count firstly */
+ p_org = p;
+ CHECK_BUF(p, p_end, param_count);
+ p += param_count;
+ read_leb_uint32(p, p_end, result_count);
+ CHECK_BUF(p, p_end, result_count);
+ p = p_org;
+
+ bh_assert(param_count <= UINT16_MAX && result_count <= UINT16_MAX);
+
+ total_size = offsetof(WASMType, types)
+ + sizeof(uint8) * (uint64)(param_count + result_count);
+ if (!(type = module->types[i] =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Resolve param types and result types */
+ type->ref_count = 1;
+ type->param_count = (uint16)param_count;
+ type->result_count = (uint16)result_count;
+ for (j = 0; j < param_count; j++) {
+ CHECK_BUF(p, p_end, 1);
+ type->types[j] = read_uint8(p);
+ }
+ read_leb_uint32(p, p_end, result_count);
+ for (j = 0; j < result_count; j++) {
+ CHECK_BUF(p, p_end, 1);
+ type->types[param_count + j] = read_uint8(p);
+ }
+ for (j = 0; j < param_count + result_count; j++) {
+ bh_assert(is_value_type(type->types[j]));
+ }
+
+ param_cell_num = wasm_get_cell_num(type->types, param_count);
+ ret_cell_num =
+ wasm_get_cell_num(type->types + param_count, result_count);
+ bh_assert(param_cell_num <= UINT16_MAX
+ && ret_cell_num <= UINT16_MAX);
+ type->param_cell_num = (uint16)param_cell_num;
+ type->ret_cell_num = (uint16)ret_cell_num;
+
+ /* If there is already a same type created, use it instead */
+ for (j = 0; j < i; ++j) {
+ if (wasm_type_equal(type, module->types[j])) {
+ bh_assert(module->types[j]->ref_count != UINT16_MAX);
+ destroy_wasm_type(type);
+ module->types[i] = module->types[j];
+ module->types[j]->ref_count++;
+ break;
+ }
+ }
+ }
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load type section success.\n");
+ (void)flag;
+ return true;
+}
+
+static void
+adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size)
+{
+ uint32 default_max_size =
+ init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE;
+
+ if (max_size_flag) {
+ /* module defines the table limitation */
+ bh_assert(init_size <= *max_size);
+
+ if (init_size < *max_size) {
+ *max_size =
+ *max_size < default_max_size ? *max_size : default_max_size;
+ }
+ }
+ else {
+ /* partial defined table limitation, gives a default value */
+ *max_size = default_max_size;
+ }
+}
+
+static bool
+load_function_import(const uint8 **p_buf, const uint8 *buf_end,
+ const WASMModule *parent_module,
+ const char *sub_module_name, const char *function_name,
+ WASMFunctionImport *function, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 declare_type_index = 0;
+ WASMType *declare_func_type = NULL;
+ WASMFunction *linked_func = NULL;
+ const char *linked_signature = NULL;
+ void *linked_attachment = NULL;
+ bool linked_call_conv_raw = false;
+
+ read_leb_uint32(p, p_end, declare_type_index);
+ *p_buf = p;
+
+ bh_assert(declare_type_index < parent_module->type_count);
+
+ declare_func_type = parent_module->types[declare_type_index];
+
+ /* check built-in modules */
+ linked_func = wasm_native_resolve_symbol(
+ sub_module_name, function_name, declare_func_type, &linked_signature,
+ &linked_attachment, &linked_call_conv_raw);
+
+ function->module_name = (char *)sub_module_name;
+ function->field_name = (char *)function_name;
+ function->func_type = declare_func_type;
+ function->func_ptr_linked = linked_func;
+ function->signature = linked_signature;
+ function->attachment = linked_attachment;
+ function->call_conv_raw = linked_call_conv_raw;
+ return true;
+}
+
+static bool
+load_table_import(const uint8 **p_buf, const uint8 *buf_end,
+ WASMModule *parent_module, const char *sub_module_name,
+ const char *table_name, WASMTableImport *table,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 declare_elem_type = 0, declare_max_size_flag = 0,
+ declare_init_size = 0, declare_max_size = 0;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x70 or 0x6F */
+ declare_elem_type = read_uint8(p);
+ bh_assert(VALUE_TYPE_FUNCREF == declare_elem_type
+#if WASM_ENABLE_REF_TYPES != 0
+ || VALUE_TYPE_EXTERNREF == declare_elem_type
+#endif
+ );
+
+ read_leb_uint32(p, p_end, declare_max_size_flag);
+ read_leb_uint32(p, p_end, declare_init_size);
+ if (declare_max_size_flag & 1) {
+ read_leb_uint32(p, p_end, declare_max_size);
+ bh_assert(table->init_size <= table->max_size);
+ }
+
+ adjust_table_max_size(declare_init_size, declare_max_size_flag,
+ &declare_max_size);
+ *p_buf = p;
+
+ bh_assert(
+ !((declare_max_size_flag & 1) && declare_init_size > declare_max_size));
+
+ /* now we believe all declaration are ok */
+ table->elem_type = declare_elem_type;
+ table->init_size = declare_init_size;
+ table->flags = declare_max_size_flag;
+ table->max_size = declare_max_size;
+ return true;
+}
+
+static bool
+load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
+ WASMModule *parent_module, const char *sub_module_name,
+ const char *memory_name, WASMMemoryImport *memory,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+#if WASM_ENABLE_APP_FRAMEWORK != 0
+ uint32 pool_size = wasm_runtime_memory_pool_size();
+ uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
+ / DEFAULT_NUM_BYTES_PER_PAGE;
+#else
+ uint32 max_page_count = DEFAULT_MAX_PAGES;
+#endif /* WASM_ENABLE_APP_FRAMEWORK */
+ uint32 declare_max_page_count_flag = 0;
+ uint32 declare_init_page_count = 0;
+ uint32 declare_max_page_count = 0;
+
+ read_leb_uint32(p, p_end, declare_max_page_count_flag);
+ read_leb_uint32(p, p_end, declare_init_page_count);
+ bh_assert(declare_init_page_count <= 65536);
+
+ if (declare_max_page_count_flag & 1) {
+ read_leb_uint32(p, p_end, declare_max_page_count);
+ bh_assert(declare_init_page_count <= declare_max_page_count);
+ bh_assert(declare_max_page_count <= 65536);
+ if (declare_max_page_count > max_page_count) {
+ declare_max_page_count = max_page_count;
+ }
+ }
+ else {
+ /* Limit the maximum memory size to max_page_count */
+ declare_max_page_count = max_page_count;
+ }
+
+ /* now we believe all declaration are ok */
+ memory->flags = declare_max_page_count_flag;
+ memory->init_page_count = declare_init_page_count;
+ memory->max_page_count = declare_max_page_count;
+ memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+
+ *p_buf = p;
+ return true;
+}
+
+static bool
+load_global_import(const uint8 **p_buf, const uint8 *buf_end,
+ const WASMModule *parent_module, char *sub_module_name,
+ char *global_name, WASMGlobalImport *global, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint8 declare_type = 0;
+ uint8 declare_mutable = 0;
+ bool is_mutable = false;
+ bool ret = false;
+
+ CHECK_BUF(p, p_end, 2);
+ declare_type = read_uint8(p);
+ declare_mutable = read_uint8(p);
+ *p_buf = p;
+
+ bh_assert(declare_mutable < 2);
+
+ is_mutable = declare_mutable & 1 ? true : false;
+
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+ /* check built-in modules */
+ ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
+ global);
+ if (ret) {
+ bh_assert(global->type == declare_type
+ && global->is_mutable != declare_mutable);
+ }
+#endif /* WASM_ENABLE_LIBC_BUILTIN */
+
+ global->is_linked = ret;
+ global->module_name = sub_module_name;
+ global->field_name = global_name;
+ global->type = declare_type;
+ global->is_mutable = is_mutable;
+ (void)p_end;
+ return true;
+}
+
+static bool
+load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x70 or 0x6F */
+ table->elem_type = read_uint8(p);
+ bh_assert((VALUE_TYPE_FUNCREF == table->elem_type)
+#if WASM_ENABLE_REF_TYPES != 0
+ || VALUE_TYPE_EXTERNREF == table->elem_type
+#endif
+ );
+
+ p_org = p;
+ read_leb_uint32(p, p_end, table->flags);
+ bh_assert(p - p_org <= 1);
+ bh_assert(table->flags <= 1);
+ (void)p_org;
+
+ read_leb_uint32(p, p_end, table->init_size);
+ if (table->flags == 1) {
+ read_leb_uint32(p, p_end, table->max_size);
+ bh_assert(table->init_size <= table->max_size);
+ }
+
+ adjust_table_max_size(table->init_size, table->flags, &table->max_size);
+
+ *p_buf = p;
+ return true;
+}
+
+static bool
+load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
+#if WASM_ENABLE_APP_FRAMEWORK != 0
+ uint32 pool_size = wasm_runtime_memory_pool_size();
+ uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
+ / DEFAULT_NUM_BYTES_PER_PAGE;
+#else
+ uint32 max_page_count = DEFAULT_MAX_PAGES;
+#endif
+
+ p_org = p;
+ read_leb_uint32(p, p_end, memory->flags);
+ bh_assert(p - p_org <= 1);
+ (void)p_org;
+#if WASM_ENABLE_SHARED_MEMORY == 0
+ bh_assert(memory->flags <= 1);
+#else
+ bh_assert(memory->flags <= 3 && memory->flags != 2);
+#endif
+
+ read_leb_uint32(p, p_end, memory->init_page_count);
+ bh_assert(memory->init_page_count <= 65536);
+
+ if (memory->flags & 1) {
+ read_leb_uint32(p, p_end, memory->max_page_count);
+ bh_assert(memory->init_page_count <= memory->max_page_count);
+ bh_assert(memory->max_page_count <= 65536);
+ if (memory->max_page_count > max_page_count)
+ memory->max_page_count = max_page_count;
+ }
+ else {
+ /* Limit the maximum memory size to max_page_count */
+ memory->max_page_count = max_page_count;
+ }
+
+ memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+
+ *p_buf = p;
+ return true;
+}
+
+static bool
+load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end, *p_old;
+ uint32 import_count, name_len, type_index, i, u32, flags;
+ uint64 total_size;
+ WASMImport *import;
+ WASMImport *import_functions = NULL, *import_tables = NULL;
+ WASMImport *import_memories = NULL, *import_globals = NULL;
+ char *sub_module_name, *field_name;
+ uint8 u8, kind;
+
+ read_leb_uint32(p, p_end, import_count);
+
+ if (import_count) {
+ module->import_count = import_count;
+ total_size = sizeof(WASMImport) * (uint64)import_count;
+ if (!(module->imports =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ p_old = p;
+
+ /* Scan firstly to get import count of each type */
+ for (i = 0; i < import_count; i++) {
+ /* module name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ p += name_len;
+
+ /* field name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ p += name_len;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x00/0x01/0x02/0x03 */
+ kind = read_uint8(p);
+
+ switch (kind) {
+ case IMPORT_KIND_FUNC: /* import function */
+ read_leb_uint32(p, p_end, type_index);
+ module->import_function_count++;
+ break;
+
+ case IMPORT_KIND_TABLE: /* import table */
+ CHECK_BUF(p, p_end, 1);
+ /* 0x70 */
+ u8 = read_uint8(p);
+ read_leb_uint32(p, p_end, flags);
+ read_leb_uint32(p, p_end, u32);
+ if (flags & 1)
+ read_leb_uint32(p, p_end, u32);
+ module->import_table_count++;
+#if WASM_ENABLE_REF_TYPES == 0
+ bh_assert(module->import_table_count <= 1);
+#endif
+ break;
+
+ case IMPORT_KIND_MEMORY: /* import memory */
+ read_leb_uint32(p, p_end, flags);
+ read_leb_uint32(p, p_end, u32);
+ if (flags & 1)
+ read_leb_uint32(p, p_end, u32);
+ module->import_memory_count++;
+ bh_assert(module->import_memory_count <= 1);
+ break;
+
+ case IMPORT_KIND_GLOBAL: /* import global */
+ CHECK_BUF(p, p_end, 2);
+ p += 2;
+ module->import_global_count++;
+ break;
+
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ if (module->import_function_count)
+ import_functions = module->import_functions = module->imports;
+ if (module->import_table_count)
+ import_tables = module->import_tables =
+ module->imports + module->import_function_count;
+ if (module->import_memory_count)
+ import_memories = module->import_memories =
+ module->imports + module->import_function_count
+ + module->import_table_count;
+ if (module->import_global_count)
+ import_globals = module->import_globals =
+ module->imports + module->import_function_count
+ + module->import_table_count + module->import_memory_count;
+
+ p = p_old;
+
+ /* Scan again to resolve the data */
+ for (i = 0; i < import_count; i++) {
+ WASMModule *sub_module = NULL;
+
+ /* load module name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ if (!(sub_module_name = const_str_list_insert(
+ p, name_len, module, is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ p += name_len;
+
+ /* load field name */
+ read_leb_uint32(p, p_end, name_len);
+ CHECK_BUF(p, p_end, name_len);
+ if (!(field_name = const_str_list_insert(
+ p, name_len, module, is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ p += name_len;
+
+ CHECK_BUF(p, p_end, 1);
+ /* 0x00/0x01/0x02/0x03 */
+ kind = read_uint8(p);
+
+ LOG_DEBUG("import #%d: (%s, %s), kind: %d", i, sub_module_name,
+ field_name, kind);
+ switch (kind) {
+ case IMPORT_KIND_FUNC: /* import function */
+ bh_assert(import_functions);
+ import = import_functions++;
+ if (!load_function_import(
+ &p, p_end, module, sub_module_name, field_name,
+ &import->u.function, error_buf, error_buf_size)) {
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_TABLE: /* import table */
+ bh_assert(import_tables);
+ import = import_tables++;
+ if (!load_table_import(&p, p_end, module, sub_module_name,
+ field_name, &import->u.table,
+ error_buf, error_buf_size)) {
+ LOG_DEBUG("can not import such a table (%s,%s)",
+ sub_module_name, field_name);
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_MEMORY: /* import memory */
+ bh_assert(import_memories);
+ import = import_memories++;
+ if (!load_memory_import(&p, p_end, module, sub_module_name,
+ field_name, &import->u.memory,
+ error_buf, error_buf_size)) {
+ return false;
+ }
+ break;
+
+ case IMPORT_KIND_GLOBAL: /* import global */
+ bh_assert(import_globals);
+ import = import_globals++;
+ if (!load_global_import(&p, p_end, module, sub_module_name,
+ field_name, &import->u.global,
+ error_buf, error_buf_size)) {
+ return false;
+ }
+ break;
+
+ default:
+ bh_assert(0);
+ import = NULL;
+ break;
+ }
+ import->kind = kind;
+ import->u.names.module_name = sub_module_name;
+ import->u.names.field_name = field_name;
+ (void)sub_module;
+ }
+
+#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")
+ || !strcmp(import->u.names.module_name,
+ "wasi_snapshot_preview1")) {
+ module->import_wasi_api = true;
+ break;
+ }
+ }
+#endif
+ }
+
+ bh_assert(p == p_end);
+
+ LOG_VERBOSE("Load import section success.\n");
+ (void)u8;
+ (void)u32;
+ (void)type_index;
+ return true;
+}
+
+static bool
+init_function_local_offsets(WASMFunction *func, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMType *param_type = func->func_type;
+ uint32 param_count = param_type->param_count;
+ uint8 *param_types = param_type->types;
+ uint32 local_count = func->local_count;
+ uint8 *local_types = func->local_types;
+ uint32 i, local_offset = 0;
+ uint64 total_size = sizeof(uint16) * ((uint64)param_count + local_count);
+
+ if (total_size > 0
+ && !(func->local_offsets =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < param_count; i++) {
+ func->local_offsets[i] = (uint16)local_offset;
+ local_offset += wasm_value_type_cell_num(param_types[i]);
+ }
+
+ for (i = 0; i < local_count; i++) {
+ func->local_offsets[param_count + i] = (uint16)local_offset;
+ local_offset += wasm_value_type_cell_num(local_types[i]);
+ }
+
+ bh_assert(local_offset == func->param_cell_num + func->local_cell_num);
+ return true;
+}
+
+static bool
+load_function_section(const uint8 *buf, const uint8 *buf_end,
+ const uint8 *buf_code, const uint8 *buf_code_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ const uint8 *p_code = buf_code, *p_code_end, *p_code_save;
+ uint32 func_count;
+ uint64 total_size;
+ uint32 code_count = 0, code_size, type_index, i, j, k, local_type_index;
+ uint32 local_count, local_set_count, sub_local_count, local_cell_num;
+ uint8 type;
+ WASMFunction *func;
+
+ read_leb_uint32(p, p_end, func_count);
+
+ if (buf_code)
+ read_leb_uint32(p_code, buf_code_end, code_count);
+
+ bh_assert(func_count == code_count);
+
+ if (func_count) {
+ module->function_count = func_count;
+ total_size = sizeof(WASMFunction *) * (uint64)func_count;
+ if (!(module->functions =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < func_count; i++) {
+ /* Resolve function type */
+ read_leb_uint32(p, p_end, type_index);
+ bh_assert(type_index < module->type_count);
+
+#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
+ type_index = wasm_get_smallest_type_idx(
+ module->types, module->type_count, type_index);
+#endif
+
+ read_leb_uint32(p_code, buf_code_end, code_size);
+ bh_assert(code_size > 0 && p_code + code_size <= buf_code_end);
+
+ /* Resolve local set count */
+ p_code_end = p_code + code_size;
+ local_count = 0;
+ read_leb_uint32(p_code, buf_code_end, local_set_count);
+ p_code_save = p_code;
+
+ /* Calculate total local count */
+ for (j = 0; j < local_set_count; j++) {
+ read_leb_uint32(p_code, buf_code_end, sub_local_count);
+ bh_assert(sub_local_count <= UINT32_MAX - local_count);
+
+ CHECK_BUF(p_code, buf_code_end, 1);
+ /* 0x7F/0x7E/0x7D/0x7C */
+ type = read_uint8(p_code);
+ local_count += sub_local_count;
+ }
+
+ /* Alloc memory, layout: function structure + local types */
+ code_size = (uint32)(p_code_end - p_code);
+
+ total_size = sizeof(WASMFunction) + (uint64)local_count;
+ if (!(func = module->functions[i] =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Set function type, local count, code size and code body */
+ func->func_type = module->types[type_index];
+ func->local_count = local_count;
+ if (local_count > 0)
+ func->local_types = (uint8 *)func + sizeof(WASMFunction);
+ func->code_size = code_size;
+ /*
+ * we shall make a copy of code body [p_code, p_code + code_size]
+ * when we are worrying about inappropriate releasing behaviour.
+ * all code bodies are actually in a buffer which user allocates in
+ * his embedding environment and we don't have power on them.
+ * it will be like:
+ * code_body_cp = malloc(code_size);
+ * memcpy(code_body_cp, p_code, code_size);
+ * func->code = code_body_cp;
+ */
+ func->code = (uint8 *)p_code;
+
+ /* Load each local type */
+ p_code = p_code_save;
+ local_type_index = 0;
+ for (j = 0; j < local_set_count; j++) {
+ read_leb_uint32(p_code, buf_code_end, sub_local_count);
+ /* Note: sub_local_count is allowed to be 0 */
+ bh_assert(local_type_index <= UINT32_MAX - sub_local_count
+ && local_type_index + sub_local_count <= local_count);
+
+ CHECK_BUF(p_code, buf_code_end, 1);
+ /* 0x7F/0x7E/0x7D/0x7C */
+ type = read_uint8(p_code);
+ bh_assert(is_value_type(type));
+ for (k = 0; k < sub_local_count; k++) {
+ func->local_types[local_type_index++] = type;
+ }
+ }
+
+ func->param_cell_num = func->func_type->param_cell_num;
+ func->ret_cell_num = func->func_type->ret_cell_num;
+ local_cell_num =
+ wasm_get_cell_num(func->local_types, func->local_count);
+ bh_assert(local_cell_num <= UINT16_MAX);
+
+ func->local_cell_num = (uint16)local_cell_num;
+
+ if (!init_function_local_offsets(func, error_buf, error_buf_size))
+ return false;
+
+ p_code = p_code_end;
+ }
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load function section success.\n");
+ (void)code_count;
+ return true;
+}
+
+static bool
+check_function_index(const WASMModule *module, uint32 function_index,
+ char *error_buf, uint32 error_buf_size)
+{
+ return (function_index
+ < module->import_function_count + module->function_count);
+}
+
+static bool
+load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 table_count, i;
+ uint64 total_size;
+ WASMTable *table;
+
+ read_leb_uint32(p, p_end, table_count);
+#if WASM_ENABLE_REF_TYPES == 0
+ bh_assert(module->import_table_count + table_count <= 1);
+#endif
+
+ if (table_count) {
+ module->table_count = table_count;
+ total_size = sizeof(WASMTable) * (uint64)table_count;
+ if (!(module->tables =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* load each table */
+ table = module->tables;
+ for (i = 0; i < table_count; i++, table++)
+ if (!load_table(&p, p_end, table, error_buf, error_buf_size))
+ return false;
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load table section success.\n");
+ return true;
+}
+
+static bool
+load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 memory_count, i;
+ uint64 total_size;
+ WASMMemory *memory;
+
+ read_leb_uint32(p, p_end, memory_count);
+ bh_assert(module->import_memory_count + memory_count <= 1);
+
+ if (memory_count) {
+ module->memory_count = memory_count;
+ total_size = sizeof(WASMMemory) * (uint64)memory_count;
+ if (!(module->memories =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* load each memory */
+ memory = module->memories;
+ for (i = 0; i < memory_count; i++, memory++)
+ if (!load_memory(&p, p_end, memory, error_buf, error_buf_size))
+ return false;
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load memory section success.\n");
+ return true;
+}
+
+static bool
+load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 global_count, i;
+ uint64 total_size;
+ WASMGlobal *global;
+ uint8 mutable;
+
+ read_leb_uint32(p, p_end, global_count);
+
+ if (global_count) {
+ module->global_count = global_count;
+ total_size = sizeof(WASMGlobal) * (uint64)global_count;
+ if (!(module->globals =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ global = module->globals;
+
+ for (i = 0; i < global_count; i++, global++) {
+ CHECK_BUF(p, p_end, 2);
+ global->type = read_uint8(p);
+ mutable = read_uint8(p);
+ bh_assert(mutable < 2);
+ global->is_mutable = mutable ? true : false;
+
+ /* initialize expression */
+ if (!load_init_expr(&p, p_end, &(global->init_expr), global->type,
+ error_buf, error_buf_size))
+ return false;
+
+ if (INIT_EXPR_TYPE_GET_GLOBAL == global->init_expr.init_expr_type) {
+ /**
+ * Currently, constant expressions occurring as initializers
+ * of globals are further constrained in that contained
+ * global.get instructions are
+ * only allowed to refer to imported globals.
+ */
+ uint32 target_global_index = global->init_expr.u.global_index;
+ bh_assert(target_global_index < module->import_global_count);
+ (void)target_global_index;
+ }
+ else if (INIT_EXPR_TYPE_FUNCREF_CONST
+ == global->init_expr.init_expr_type) {
+ bh_assert(global->init_expr.u.ref_index
+ < module->import_function_count
+ + module->function_count);
+ }
+ }
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load global section success.\n");
+ return true;
+}
+
+static bool
+load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 export_count, i, j, index;
+ uint64 total_size;
+ uint32 str_len;
+ WASMExport *export;
+ const char *name;
+
+ read_leb_uint32(p, p_end, export_count);
+
+ if (export_count) {
+ module->export_count = export_count;
+ total_size = sizeof(WASMExport) * (uint64)export_count;
+ if (!(module->exports =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ export = module->exports;
+ for (i = 0; i < export_count; i++, export ++) {
+ read_leb_uint32(p, p_end, str_len);
+ CHECK_BUF(p, p_end, str_len);
+
+ for (j = 0; j < i; j++) {
+ name = module->exports[j].name;
+ bh_assert(!(strlen(name) == str_len
+ && memcmp(name, p, str_len) == 0));
+ }
+
+ if (!(export->name = const_str_list_insert(
+ p, str_len, module, is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+ p += str_len;
+ CHECK_BUF(p, p_end, 1);
+ export->kind = read_uint8(p);
+ read_leb_uint32(p, p_end, index);
+ export->index = index;
+
+ switch (export->kind) {
+ /* function index */
+ case EXPORT_KIND_FUNC:
+ bh_assert(index < module->function_count
+ + module->import_function_count);
+ break;
+ /* table index */
+ case EXPORT_KIND_TABLE:
+ bh_assert(index < module->table_count
+ + module->import_table_count);
+ break;
+ /* memory index */
+ case EXPORT_KIND_MEMORY:
+ bh_assert(index < module->memory_count
+ + module->import_memory_count);
+ break;
+ /* global index */
+ case EXPORT_KIND_GLOBAL:
+ bh_assert(index < module->global_count
+ + module->import_global_count);
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load export section success.\n");
+ (void)name;
+ return true;
+}
+
+static bool
+check_table_index(const WASMModule *module, uint32 table_index, char *error_buf,
+ uint32 error_buf_size)
+{
+#if WASM_ENABLE_REF_TYPES == 0
+ if (table_index != 0) {
+ return false;
+ }
+#endif
+
+ if (table_index >= module->import_table_count + module->table_count) {
+ return false;
+ }
+ return true;
+}
+
+static bool
+load_table_index(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
+ uint32 *p_table_index, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 table_index;
+
+ read_leb_uint32(p, p_end, table_index);
+ if (!check_table_index(module, table_index, error_buf, error_buf_size)) {
+ return false;
+ }
+
+ *p_table_index = table_index;
+ *p_buf = p;
+ return true;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+static bool
+load_elem_type(const uint8 **p_buf, const uint8 *buf_end, uint32 *p_elem_type,
+ bool elemkind_zero, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint8 elem_type;
+
+ CHECK_BUF(p, p_end, 1);
+ elem_type = read_uint8(p);
+ if ((elemkind_zero && elem_type != 0)
+ || (!elemkind_zero && elem_type != VALUE_TYPE_FUNCREF
+ && elem_type != VALUE_TYPE_EXTERNREF)) {
+ set_error_buf(error_buf, error_buf_size, "invalid reference type");
+ return false;
+ }
+
+ if (elemkind_zero)
+ *p_elem_type = VALUE_TYPE_FUNCREF;
+ else
+ *p_elem_type = elem_type;
+ *p_buf = p;
+
+ (void)p_end;
+ return true;
+}
+#endif /* WASM_ENABLE_REF_TYPES != 0*/
+
+static bool
+load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
+ WASMModule *module, WASMTableSeg *table_segment,
+ bool use_init_expr, char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = *p_buf, *p_end = buf_end;
+ uint32 function_count, function_index = 0, i;
+ uint64 total_size;
+
+ read_leb_uint32(p, p_end, function_count);
+ table_segment->function_count = function_count;
+ total_size = sizeof(uint32) * (uint64)function_count;
+ if (total_size > 0
+ && !(table_segment->func_indexes = (uint32 *)loader_malloc(
+ total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < function_count; i++) {
+ InitializerExpression init_expr = { 0 };
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!use_init_expr) {
+ read_leb_uint32(p, p_end, function_index);
+ }
+ else {
+ if (!load_init_expr(&p, p_end, &init_expr, table_segment->elem_type,
+ error_buf, error_buf_size))
+ return false;
+
+ function_index = init_expr.u.ref_index;
+ }
+#else
+ read_leb_uint32(p, p_end, function_index);
+#endif
+
+ /* since we are using -1 to indicate ref.null */
+ if (init_expr.init_expr_type != INIT_EXPR_TYPE_REFNULL_CONST
+ && !check_function_index(module, function_index, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+ table_segment->func_indexes[i] = function_index;
+ }
+
+ *p_buf = p;
+ return true;
+}
+
+static bool
+load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 table_segment_count, i, table_index, function_count;
+ uint64 total_size;
+ WASMTableSeg *table_segment;
+
+ read_leb_uint32(p, p_end, table_segment_count);
+
+ if (table_segment_count) {
+ module->table_seg_count = table_segment_count;
+ total_size = sizeof(WASMTableSeg) * (uint64)table_segment_count;
+ if (!(module->table_segments =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ table_segment = module->table_segments;
+ for (i = 0; i < table_segment_count; i++, table_segment++) {
+ bh_assert(p < p_end);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ read_leb_uint32(p, p_end, table_segment->mode);
+ /* last three bits */
+ table_segment->mode = table_segment->mode & 0x07;
+ switch (table_segment->mode) {
+ /* elemkind/elemtype + active */
+ case 0:
+ case 4:
+ table_segment->elem_type = VALUE_TYPE_FUNCREF;
+ table_segment->table_index = 0;
+
+ if (!check_table_index(module, table_segment->table_index,
+ error_buf, error_buf_size))
+ return false;
+
+ if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+ VALUE_TYPE_I32, error_buf,
+ error_buf_size))
+ return false;
+
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ table_segment->mode == 0 ? false
+ : true,
+ error_buf, error_buf_size))
+ return false;
+ break;
+ /* elemkind + passive/declarative */
+ case 1:
+ case 3:
+ if (!load_elem_type(&p, p_end, &table_segment->elem_type,
+ true, error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ false, error_buf, error_buf_size))
+ return false;
+ break;
+ /* elemkind/elemtype + table_idx + active */
+ case 2:
+ case 6:
+ if (!load_table_index(&p, p_end, module,
+ &table_segment->table_index,
+ error_buf, error_buf_size))
+ return false;
+ if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+ VALUE_TYPE_I32, error_buf,
+ error_buf_size))
+ return false;
+ if (!load_elem_type(&p, p_end, &table_segment->elem_type,
+ table_segment->mode == 2 ? true : false,
+ error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ table_segment->mode == 2 ? false
+ : true,
+ error_buf, error_buf_size))
+ return false;
+ break;
+ case 5:
+ case 7:
+ if (!load_elem_type(&p, p_end, &table_segment->elem_type,
+ false, error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment,
+ true, error_buf, error_buf_size))
+ return false;
+ break;
+ default:
+ return false;
+ }
+#else
+ /*
+ * like: 00 41 05 0b 04 00 01 00 01
+ * for: (elem 0 (offset (i32.const 5)) $f1 $f2 $f1 $f2)
+ */
+ if (!load_table_index(&p, p_end, module,
+ &table_segment->table_index, error_buf,
+ error_buf_size))
+ return false;
+ if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+ VALUE_TYPE_I32, error_buf, error_buf_size))
+ return false;
+ if (!load_func_index_vec(&p, p_end, module, table_segment, false,
+ error_buf, error_buf_size))
+ return false;
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+ }
+ }
+
+ (void)table_index;
+ (void)function_count;
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load table segment section success.\n");
+ return true;
+}
+
+static bool
+load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 data_seg_count, i, mem_index, data_seg_len;
+ uint64 total_size;
+ WASMDataSeg *dataseg;
+ InitializerExpression init_expr;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ bool is_passive = false;
+ uint32 mem_flag;
+#endif
+
+ read_leb_uint32(p, p_end, data_seg_count);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ bh_assert(module->data_seg_count1 == 0
+ || data_seg_count == module->data_seg_count1);
+#endif
+
+ if (data_seg_count) {
+ module->data_seg_count = data_seg_count;
+ total_size = sizeof(WASMDataSeg *) * (uint64)data_seg_count;
+ if (!(module->data_segments =
+ loader_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < data_seg_count; i++) {
+ read_leb_uint32(p, p_end, mem_index);
+#if WASM_ENABLE_BULK_MEMORY != 0
+ is_passive = false;
+ mem_flag = mem_index & 0x03;
+ switch (mem_flag) {
+ case 0x01:
+ is_passive = true;
+ break;
+ case 0x00:
+ /* no memory index, treat index as 0 */
+ mem_index = 0;
+ goto check_mem_index;
+ case 0x02:
+ /* read following memory index */
+ read_leb_uint32(p, p_end, mem_index);
+ check_mem_index:
+ bh_assert(mem_index < module->import_memory_count
+ + module->memory_count);
+ break;
+ case 0x03:
+ default:
+ bh_assert(0);
+ break;
+ }
+#else
+ bh_assert(mem_index
+ < module->import_memory_count + module->memory_count);
+#endif /* WASM_ENABLE_BULK_MEMORY */
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if (!is_passive)
+#endif
+ if (!load_init_expr(&p, p_end, &init_expr, VALUE_TYPE_I32,
+ error_buf, error_buf_size))
+ return false;
+
+ read_leb_uint32(p, p_end, data_seg_len);
+
+ if (!(dataseg = module->data_segments[i] = loader_malloc(
+ sizeof(WASMDataSeg), error_buf, error_buf_size))) {
+ return false;
+ }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ dataseg->is_passive = is_passive;
+ if (!is_passive)
+#endif
+ {
+ bh_memcpy_s(&dataseg->base_offset,
+ sizeof(InitializerExpression), &init_expr,
+ sizeof(InitializerExpression));
+
+ dataseg->memory_index = mem_index;
+ }
+
+ dataseg->data_length = data_seg_len;
+ CHECK_BUF(p, p_end, data_seg_len);
+ dataseg->data = (uint8 *)p;
+ p += data_seg_len;
+ }
+ }
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load data segment section success.\n");
+ return true;
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+static bool
+load_datacount_section(const uint8 *buf, const uint8 *buf_end,
+ WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 data_seg_count1 = 0;
+
+ read_leb_uint32(p, p_end, data_seg_count1);
+ module->data_seg_count1 = data_seg_count1;
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load datacount section success.\n");
+ return true;
+}
+#endif
+
+static bool
+load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func,
+ const uint8 *buf_func_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ const uint8 *p_func = buf_func;
+ uint32 func_count = 0, code_count;
+
+ /* code has been loaded in function section, so pass it here, just check
+ * whether function and code section have inconsistent lengths */
+ read_leb_uint32(p, p_end, code_count);
+
+ if (buf_func)
+ read_leb_uint32(p_func, buf_func_end, func_count);
+
+ bh_assert(func_count == code_count);
+ LOG_VERBOSE("Load code segment section success.\n");
+ (void)code_count;
+ (void)func_count;
+ return true;
+}
+
+static bool
+load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ WASMType *type;
+ uint32 start_function;
+
+ read_leb_uint32(p, p_end, start_function);
+
+ bh_assert(start_function
+ < module->function_count + module->import_function_count);
+
+ if (start_function < module->import_function_count)
+ type = module->import_functions[start_function].u.function.func_type;
+ else
+ type = module->functions[start_function - module->import_function_count]
+ ->func_type;
+
+ bh_assert(type->param_count == 0 && type->result_count == 0);
+
+ module->start_function = start_function;
+
+ bh_assert(p == p_end);
+ LOG_VERBOSE("Load start section success.\n");
+ (void)type;
+ return true;
+}
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+static bool
+handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 name_type, subsection_size;
+ uint32 previous_name_type = 0;
+ uint32 num_func_name;
+ uint32 func_index;
+ uint32 previous_func_index = ~0U;
+ uint32 func_name_len;
+ uint32 name_index;
+ int i = 0;
+
+ bh_assert(p < p_end);
+
+ while (p < p_end) {
+ read_leb_uint32(p, p_end, name_type);
+ if (i != 0) {
+ bh_assert(name_type > previous_name_type);
+ }
+ previous_name_type = name_type;
+ read_leb_uint32(p, p_end, subsection_size);
+ CHECK_BUF(p, p_end, subsection_size);
+ switch (name_type) {
+ case SUB_SECTION_TYPE_FUNC:
+ if (subsection_size) {
+ read_leb_uint32(p, p_end, num_func_name);
+ for (name_index = 0; name_index < num_func_name;
+ name_index++) {
+ read_leb_uint32(p, p_end, func_index);
+ bh_assert(func_index > previous_func_index);
+ previous_func_index = func_index;
+ read_leb_uint32(p, p_end, func_name_len);
+ CHECK_BUF(p, p_end, func_name_len);
+ /* Skip the import functions */
+ if (func_index >= module->import_function_count) {
+ func_index -= module->import_function_count;
+ bh_assert(func_index < module->function_count);
+ if (!(module->functions[func_index]->field_name =
+ const_str_list_insert(
+ p, func_name_len, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+ }
+ p += func_name_len;
+ }
+ }
+ break;
+ case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection
+ */
+ case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */
+ default:
+ p = p + subsection_size;
+ break;
+ }
+ i++;
+ }
+
+ (void)previous_name_type;
+ (void)previous_func_index;
+ return true;
+}
+#endif
+
+static bool
+load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ const uint8 *p = buf, *p_end = buf_end;
+ uint32 name_len;
+
+ bh_assert(p < p_end);
+
+ read_leb_uint32(p, p_end, name_len);
+
+ bh_assert(name_len > 0 && p + name_len <= p_end);
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ if (memcmp(p, "name", 4) == 0) {
+ p += name_len;
+ handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf,
+ error_buf_size);
+ }
+#endif
+ LOG_VERBOSE("Load custom section success.\n");
+ (void)name_len;
+ return true;
+}
+
+static void
+calculate_global_data_offset(WASMModule *module)
+{
+ uint32 i, data_offset;
+
+ data_offset = 0;
+ for (i = 0; i < module->import_global_count; i++) {
+ WASMGlobalImport *import_global =
+ &((module->import_globals + i)->u.global);
+#if WASM_ENABLE_FAST_JIT != 0
+ import_global->data_offset = data_offset;
+#endif
+ data_offset += wasm_value_type_size(import_global->type);
+ }
+
+ for (i = 0; i < module->global_count; i++) {
+ WASMGlobal *global = module->globals + i;
+#if WASM_ENABLE_FAST_JIT != 0
+ global->data_offset = data_offset;
+#endif
+ data_offset += wasm_value_type_size(global->type);
+ }
+
+ module->global_data_size = data_offset;
+}
+
+#if WASM_ENABLE_FAST_JIT != 0
+static bool
+init_fast_jit_functions(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+#if WASM_ENABLE_LAZY_JIT != 0
+ JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+#endif
+ uint32 i;
+
+ if (!module->function_count)
+ return true;
+
+ if (!(module->fast_jit_func_ptrs =
+ loader_malloc(sizeof(void *) * module->function_count, error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+#if WASM_ENABLE_LAZY_JIT != 0
+ for (i = 0; i < module->function_count; i++) {
+ module->fast_jit_func_ptrs[i] =
+ jit_globals->compile_fast_jit_and_then_call;
+ }
+#endif
+
+ for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) {
+ if (os_mutex_init(&module->fast_jit_thread_locks[i]) != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "init fast jit thread lock failed");
+ return false;
+ }
+ module->fast_jit_thread_locks_inited[i] = true;
+ }
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 */
+
+#if WASM_ENABLE_JIT != 0
+static bool
+init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
+ AOTCompOption option = { 0 };
+ char *aot_last_error;
+ uint64 size;
+
+ if (module->function_count == 0)
+ return true;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LLVM_JIT != 0
+ if (os_mutex_init(&module->tierup_wait_lock) != 0) {
+ set_error_buf(error_buf, error_buf_size, "init jit tierup lock failed");
+ return false;
+ }
+ if (os_cond_init(&module->tierup_wait_cond) != 0) {
+ set_error_buf(error_buf, error_buf_size, "init jit tierup cond failed");
+ os_mutex_destroy(&module->tierup_wait_lock);
+ return false;
+ }
+ module->tierup_wait_lock_inited = true;
+#endif
+
+ size = sizeof(void *) * (uint64)module->function_count
+ + sizeof(bool) * (uint64)module->function_count;
+ if (!(module->func_ptrs = loader_malloc(size, error_buf, error_buf_size))) {
+ return false;
+ }
+ module->func_ptrs_compiled =
+ (bool *)((uint8 *)module->func_ptrs
+ + sizeof(void *) * module->function_count);
+
+ module->comp_data = aot_create_comp_data(module);
+ if (!module->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 false;
+ }
+
+ option.is_jit_mode = true;
+ option.opt_level = llvm_jit_options.opt_level;
+ option.size_level = llvm_jit_options.size_level;
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ option.enable_bulk_memory = true;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ option.enable_thread_mgr = true;
+#endif
+#if WASM_ENABLE_TAIL_CALL != 0
+ option.enable_tail_call = true;
+#endif
+#if WASM_ENABLE_SIMD != 0
+ option.enable_simd = true;
+#endif
+#if WASM_ENABLE_REF_TYPES != 0
+ option.enable_ref_types = true;
+#endif
+ option.enable_aux_stack_check = true;
+#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+ option.enable_aux_stack_frame = true;
+#endif
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ option.enable_stack_estimation = true;
+#endif
+
+ module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
+ if (!module->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);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ char *aot_last_error;
+ uint32 i;
+
+ if (module->function_count == 0)
+ return true;
+
+ if (!aot_compile_wasm(module->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);
+ return false;
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ if (module->orcjit_stop_compiling)
+ return false;
+#endif
+
+ bh_print_time("Begin to lookup llvm jit functions");
+
+ for (i = 0; i < module->function_count; i++) {
+ LLVMOrcJITTargetAddress func_addr = 0;
+ LLVMErrorRef error;
+ char func_name[48];
+
+ snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
+ error = LLVMOrcLLLazyJITLookup(module->comp_ctx->orc_jit, &func_addr,
+ func_name);
+ if (error != LLVMErrorSuccess) {
+ char *err_msg = LLVMGetErrorMessage(error);
+ char buf[96];
+ snprintf(buf, sizeof(buf),
+ "failed to compile llvm jit function: %s", err_msg);
+ set_error_buf(error_buf, error_buf_size, buf);
+ LLVMDisposeErrorMessage(err_msg);
+ return false;
+ }
+
+ /**
+ * No need to lock the func_ptr[func_idx] here as it is basic
+ * data type, the load/store for it can be finished by one cpu
+ * instruction, and there can be only one cpu instruction
+ * loading/storing at the same time.
+ */
+ module->func_ptrs[i] = (void *)func_addr;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
+
+ if (module->orcjit_stop_compiling)
+ return false;
+#endif
+ }
+
+ bh_print_time("End lookup llvm jit functions");
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_JIT != 0 */
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+static void *
+init_llvm_jit_functions_stage2_callback(void *arg)
+{
+ WASMModule *module = (WASMModule *)arg;
+ char error_buf[128];
+ uint32 error_buf_size = (uint32)sizeof(error_buf);
+
+ if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) {
+ module->orcjit_stop_compiling = true;
+ return NULL;
+ }
+
+ os_mutex_lock(&module->tierup_wait_lock);
+ module->llvm_jit_inited = true;
+ os_cond_broadcast(&module->tierup_wait_cond);
+ os_mutex_unlock(&module->tierup_wait_lock);
+
+ return NULL;
+}
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+/* The callback function to compile jit functions */
+static void *
+orcjit_thread_callback(void *arg)
+{
+ OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
+#if WASM_ENABLE_JIT != 0
+ AOTCompContext *comp_ctx = thread_arg->comp_ctx;
+#endif
+ WASMModule *module = thread_arg->module;
+ uint32 group_idx = thread_arg->group_idx;
+ uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+ uint32 func_count = module->function_count;
+ uint32 i;
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /* Compile fast jit funcitons of this group */
+ for (i = group_idx; i < func_count; i += group_stride) {
+ if (!jit_compiler_compile(module, i + module->import_function_count)) {
+ os_printf("failed to compile fast jit function %u\n", i);
+ break;
+ }
+
+ if (module->orcjit_stop_compiling) {
+ return NULL;
+ }
+ }
+#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ os_mutex_lock(&module->tierup_wait_lock);
+ module->fast_jit_ready_groups++;
+ os_mutex_unlock(&module->tierup_wait_lock);
+#endif
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ /* For JIT tier-up, set each llvm jit func to call_to_fast_jit */
+ for (i = group_idx; i < func_count;
+ i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
+ uint32 j;
+
+ for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+ if (i + j * group_stride < func_count) {
+ if (!jit_compiler_set_call_to_fast_jit(
+ module,
+ i + j * group_stride + module->import_function_count)) {
+ os_printf(
+ "failed to compile call_to_fast_jit for func %u\n",
+ i + j * group_stride + module->import_function_count);
+ module->orcjit_stop_compiling = true;
+ return NULL;
+ }
+ }
+ if (module->orcjit_stop_compiling) {
+ return NULL;
+ }
+ }
+ }
+
+ /* Wait until init_llvm_jit_functions_stage2 finishes and all
+ fast jit functions are compiled */
+ os_mutex_lock(&module->tierup_wait_lock);
+ while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation
+ && module->fast_jit_ready_groups >= group_stride)) {
+ os_cond_reltimedwait(&module->tierup_wait_cond,
+ &module->tierup_wait_lock, 10000);
+ if (module->orcjit_stop_compiling) {
+ /* init_llvm_jit_functions_stage2 failed */
+ os_mutex_unlock(&module->tierup_wait_lock);
+ return NULL;
+ }
+ }
+ os_mutex_unlock(&module->tierup_wait_lock);
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ /* Compile llvm jit functions of this group */
+ for (i = group_idx; i < func_count;
+ i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
+ LLVMOrcJITTargetAddress func_addr = 0;
+ LLVMErrorRef error;
+ char func_name[48];
+ typedef void (*F)(void);
+ union {
+ F f;
+ void *v;
+ } u;
+ uint32 j;
+
+ snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i,
+ "_wrapper");
+ LOG_DEBUG("compile llvm jit func %s", func_name);
+ error =
+ LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name);
+ if (error != LLVMErrorSuccess) {
+ char *err_msg = LLVMGetErrorMessage(error);
+ os_printf("failed to compile llvm jit function %u: %s", i, err_msg);
+ LLVMDisposeErrorMessage(err_msg);
+ break;
+ }
+
+ /* Call the jit wrapper function to trigger its compilation, so as
+ to compile the actual jit functions, since we add the latter to
+ function list in the PartitionFunction callback */
+ u.v = (void *)func_addr;
+ u.f();
+
+ for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+ if (i + j * group_stride < func_count) {
+ module->func_ptrs_compiled[i + j * group_stride] = true;
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX,
+ i + j * group_stride);
+ error = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr,
+ func_name);
+ if (error != LLVMErrorSuccess) {
+ char *err_msg = LLVMGetErrorMessage(error);
+ os_printf("failed to compile llvm jit function %u: %s", i,
+ err_msg);
+ LLVMDisposeErrorMessage(err_msg);
+ /* Ignore current llvm jit func, as its func ptr is
+ previous set to call_to_fast_jit, which also works */
+ continue;
+ }
+
+ jit_compiler_set_llvm_jit_func_ptr(
+ module,
+ i + j * group_stride + module->import_function_count,
+ (void *)func_addr);
+
+ /* Try to switch to call this llvm jit funtion instead of
+ fast jit function from fast jit jitted code */
+ jit_compiler_set_call_to_llvm_jit(
+ module,
+ i + j * group_stride + module->import_function_count);
+#endif
+ }
+ }
+
+ if (module->orcjit_stop_compiling) {
+ break;
+ }
+ }
+#endif
+
+ return NULL;
+}
+
+static void
+orcjit_stop_compile_threads(WASMModule *module)
+{
+ uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args)
+ / sizeof(OrcJitThreadArg));
+
+ module->orcjit_stop_compiling = true;
+ for (i = 0; i < thread_num; i++) {
+ if (module->orcjit_threads[i])
+ os_thread_join(module->orcjit_threads[i], NULL);
+ }
+}
+
+static bool
+compile_jit_functions(WASMModule *module, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 thread_num =
+ (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg));
+ uint32 i, j;
+
+ bh_print_time("Begin to compile jit functions");
+
+ /* Create threads to compile the jit functions */
+ for (i = 0; i < thread_num && i < module->function_count; i++) {
+#if WASM_ENABLE_JIT != 0
+ module->orcjit_thread_args[i].comp_ctx = module->comp_ctx;
+#endif
+ module->orcjit_thread_args[i].module = module;
+ module->orcjit_thread_args[i].group_idx = i;
+
+ if (os_thread_create(&module->orcjit_threads[i], orcjit_thread_callback,
+ (void *)&module->orcjit_thread_args[i],
+ APP_THREAD_STACK_SIZE_DEFAULT)
+ != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "create orcjit compile thread failed");
+ /* Terminate the threads created */
+ module->orcjit_stop_compiling = true;
+ for (j = 0; j < i; j++) {
+ os_thread_join(module->orcjit_threads[j], NULL);
+ }
+ return false;
+ }
+ }
+
+#if WASM_ENABLE_LAZY_JIT == 0
+ /* Wait until all jit functions are compiled for eager mode */
+ for (i = 0; i < thread_num; i++) {
+ if (module->orcjit_threads[i])
+ os_thread_join(module->orcjit_threads[i], NULL);
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0
+ /* Ensure all the fast-jit functions are compiled */
+ for (i = 0; i < module->function_count; i++) {
+ if (!jit_compiler_is_compiled(module,
+ i + module->import_function_count)) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to compile fast jit function");
+ return false;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ /* Ensure all the llvm-jit functions are compiled */
+ for (i = 0; i < module->function_count; i++) {
+ if (!module->func_ptrs_compiled[i]) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to compile llvm jit function");
+ return false;
+ }
+ }
+#endif
+#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
+
+ bh_print_time("End compile jit functions");
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
+
+#if WASM_ENABLE_REF_TYPES != 0
+static bool
+get_table_elem_type(const WASMModule *module, uint32 table_idx,
+ uint8 *p_elem_type, char *error_buf, uint32 error_buf_size)
+{
+ if (!check_table_index(module, table_idx, error_buf, error_buf_size)) {
+ return false;
+ }
+
+ if (p_elem_type) {
+ if (table_idx < module->import_table_count)
+ *p_elem_type = module->import_tables[table_idx].u.table.elem_type;
+ else
+ *p_elem_type =
+ module->tables[module->import_table_count + table_idx]
+ .elem_type;
+ }
+ return true;
+}
+
+static bool
+get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx,
+ uint8 *p_elem_type, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (table_seg_idx >= module->table_seg_count) {
+ return false;
+ }
+
+ if (p_elem_type) {
+ *p_elem_type = module->table_segments[table_seg_idx].elem_type;
+ }
+ return true;
+}
+#endif
+
+static bool
+wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
+ uint32 cur_func_idx, char *error_buf,
+ uint32 error_buf_size);
+
+#if WASM_ENABLE_FAST_INTERP != 0 && WASM_ENABLE_LABELS_AS_VALUES != 0
+void **
+wasm_interp_get_handle_table();
+
+static void **handle_table;
+#endif
+
+static bool
+load_from_sections(WASMModule *module, WASMSection *sections,
+ bool is_load_from_file_buf, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMExport *export;
+ WASMSection *section = sections;
+ const uint8 *buf, *buf_end, *buf_code = NULL, *buf_code_end = NULL,
+ *buf_func = NULL, *buf_func_end = NULL;
+ WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL;
+ WASMGlobal *aux_stack_top_global = NULL, *global;
+ uint32 aux_data_end = (uint32)-1, aux_heap_base = (uint32)-1;
+ uint32 aux_stack_top = (uint32)-1, global_index, func_index, i;
+ uint32 aux_data_end_global_index = (uint32)-1;
+ uint32 aux_heap_base_global_index = (uint32)-1;
+ WASMType *func_type;
+
+ /* Find code and function sections if have */
+ while (section) {
+ if (section->section_type == SECTION_TYPE_CODE) {
+ buf_code = section->section_body;
+ buf_code_end = buf_code + section->section_body_size;
+ }
+ else if (section->section_type == SECTION_TYPE_FUNC) {
+ buf_func = section->section_body;
+ buf_func_end = buf_func + section->section_body_size;
+ }
+ section = section->next;
+ }
+
+ section = sections;
+ while (section) {
+ buf = section->section_body;
+ buf_end = buf + section->section_body_size;
+ LOG_DEBUG("load section, type: %d", section->section_type);
+ switch (section->section_type) {
+ case SECTION_TYPE_USER:
+ /* unsupported user section, ignore it. */
+ if (!load_user_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_TYPE:
+ if (!load_type_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_IMPORT:
+ if (!load_import_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_FUNC:
+ if (!load_function_section(buf, buf_end, buf_code, buf_code_end,
+ module, error_buf, error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_TABLE:
+ if (!load_table_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_MEMORY:
+ if (!load_memory_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_GLOBAL:
+ if (!load_global_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_EXPORT:
+ if (!load_export_section(buf, buf_end, module,
+ is_load_from_file_buf, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_START:
+ if (!load_start_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_ELEM:
+ if (!load_table_segment_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_CODE:
+ if (!load_code_section(buf, buf_end, buf_func, buf_func_end,
+ module, error_buf, error_buf_size))
+ return false;
+ break;
+ case SECTION_TYPE_DATA:
+ if (!load_data_segment_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case SECTION_TYPE_DATACOUNT:
+ if (!load_datacount_section(buf, buf_end, module, error_buf,
+ error_buf_size))
+ return false;
+ break;
+#endif
+ default:
+ set_error_buf(error_buf, error_buf_size, "invalid section id");
+ return false;
+ }
+
+ section = section->next;
+ }
+
+ module->aux_data_end_global_index = (uint32)-1;
+ module->aux_heap_base_global_index = (uint32)-1;
+ module->aux_stack_top_global_index = (uint32)-1;
+
+ /* Resolve auxiliary data/stack/heap info and reset memory info */
+ export = module->exports;
+ for (i = 0; i < module->export_count; i++, export ++) {
+ if (export->kind == EXPORT_KIND_GLOBAL) {
+ if (!strcmp(export->name, "__heap_base")) {
+ global_index = export->index - module->import_global_count;
+ global = module->globals + global_index;
+ if (global->type == VALUE_TYPE_I32 && !global->is_mutable
+ && global->init_expr.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST) {
+ aux_heap_base_global = global;
+ aux_heap_base = global->init_expr.u.i32;
+ aux_heap_base_global_index = export->index;
+ LOG_VERBOSE("Found aux __heap_base global, value: %d",
+ aux_heap_base);
+ }
+ }
+ else if (!strcmp(export->name, "__data_end")) {
+ global_index = export->index - module->import_global_count;
+ global = module->globals + global_index;
+ if (global->type == VALUE_TYPE_I32 && !global->is_mutable
+ && global->init_expr.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST) {
+ aux_data_end_global = global;
+ aux_data_end = global->init_expr.u.i32;
+ aux_data_end_global_index = export->index;
+ LOG_VERBOSE("Found aux __data_end global, value: %d",
+ aux_data_end);
+
+ aux_data_end = align_uint(aux_data_end, 16);
+ }
+ }
+
+ /* For module compiled with -pthread option, the global is:
+ [0] stack_top <-- 0
+ [1] tls_pointer
+ [2] tls_size
+ [3] data_end <-- 3
+ [4] global_base
+ [5] heap_base <-- 5
+ [6] dso_handle
+
+ For module compiled without -pthread option:
+ [0] stack_top <-- 0
+ [1] data_end <-- 1
+ [2] global_base
+ [3] heap_base <-- 3
+ [4] dso_handle
+ */
+ if (aux_data_end_global && aux_heap_base_global
+ && aux_data_end <= aux_heap_base) {
+ module->aux_data_end_global_index = aux_data_end_global_index;
+ module->aux_data_end = aux_data_end;
+ module->aux_heap_base_global_index = aux_heap_base_global_index;
+ module->aux_heap_base = aux_heap_base;
+
+ /* Resolve aux stack top global */
+ for (global_index = 0; global_index < module->global_count;
+ global_index++) {
+ global = module->globals + global_index;
+ if (global->is_mutable /* heap_base and data_end is
+ not mutable */
+ && global->type == VALUE_TYPE_I32
+ && global->init_expr.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST
+ && (uint32)global->init_expr.u.i32 <= aux_heap_base) {
+ aux_stack_top_global = global;
+ aux_stack_top = (uint32)global->init_expr.u.i32;
+ module->aux_stack_top_global_index =
+ module->import_global_count + global_index;
+ module->aux_stack_bottom = aux_stack_top;
+ module->aux_stack_size =
+ aux_stack_top > aux_data_end
+ ? aux_stack_top - aux_data_end
+ : aux_stack_top;
+ LOG_VERBOSE("Found aux stack top global, value: %d, "
+ "global index: %d, stack size: %d",
+ aux_stack_top, global_index,
+ module->aux_stack_size);
+ break;
+ }
+ }
+ if (!aux_stack_top_global) {
+ /* Auxiliary stack global isn't found, it must be unused
+ in the wasm app, as if it is used, the global must be
+ defined. Here we set it to __heap_base global and set
+ its size to 0. */
+ aux_stack_top_global = aux_heap_base_global;
+ aux_stack_top = aux_heap_base;
+ module->aux_stack_top_global_index =
+ module->aux_heap_base_global_index;
+ module->aux_stack_bottom = aux_stack_top;
+ module->aux_stack_size = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ module->malloc_function = (uint32)-1;
+ module->free_function = (uint32)-1;
+ module->retain_function = (uint32)-1;
+
+ /* Resolve malloc/free function exported by wasm module */
+ export = module->exports;
+ for (i = 0; i < module->export_count; i++, export ++) {
+ if (export->kind == EXPORT_KIND_FUNC) {
+ if (!strcmp(export->name, "malloc")
+ && export->index >= module->import_function_count) {
+ func_index = export->index - module->import_function_count;
+ func_type = module->functions[func_index]->func_type;
+ if (func_type->param_count == 1 && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32) {
+ bh_assert(module->malloc_function == (uint32)-1);
+ module->malloc_function = export->index;
+ LOG_VERBOSE("Found malloc function, name: %s, index: %u",
+ export->name, export->index);
+ }
+ }
+ else if (!strcmp(export->name, "__new")
+ && export->index >= module->import_function_count) {
+ /* __new && __pin for AssemblyScript */
+ func_index = export->index - module->import_function_count;
+ func_type = module->functions[func_index]->func_type;
+ if (func_type->param_count == 2 && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32
+ && func_type->types[2] == VALUE_TYPE_I32) {
+ uint32 j;
+ WASMExport *export_tmp;
+
+ bh_assert(module->malloc_function == (uint32)-1);
+ module->malloc_function = export->index;
+ LOG_VERBOSE("Found malloc function, name: %s, index: %u",
+ export->name, export->index);
+
+ /* resolve retain function.
+ If not found, reset malloc function index */
+ export_tmp = module->exports;
+ for (j = 0; j < module->export_count; j++, export_tmp++) {
+ if ((export_tmp->kind == EXPORT_KIND_FUNC)
+ && (!strcmp(export_tmp->name, "__retain")
+ || !strcmp(export_tmp->name, "__pin"))
+ && (export_tmp->index
+ >= module->import_function_count)) {
+ func_index = export_tmp->index
+ - module->import_function_count;
+ func_type =
+ module->functions[func_index]->func_type;
+ if (func_type->param_count == 1
+ && func_type->result_count == 1
+ && func_type->types[0] == VALUE_TYPE_I32
+ && func_type->types[1] == VALUE_TYPE_I32) {
+ bh_assert(module->retain_function
+ == (uint32)-1);
+ module->retain_function = export_tmp->index;
+ LOG_VERBOSE("Found retain function, name: %s, "
+ "index: %u",
+ export_tmp->name,
+ export_tmp->index);
+ break;
+ }
+ }
+ }
+ if (j == module->export_count) {
+ module->malloc_function = (uint32)-1;
+ LOG_VERBOSE("Can't find retain function,"
+ "reset malloc function index to -1");
+ }
+ }
+ }
+ else if (((!strcmp(export->name, "free"))
+ || (!strcmp(export->name, "__release"))
+ || (!strcmp(export->name, "__unpin")))
+ && export->index >= module->import_function_count) {
+ func_index = export->index - module->import_function_count;
+ func_type = module->functions[func_index]->func_type;
+ if (func_type->param_count == 1 && func_type->result_count == 0
+ && func_type->types[0] == VALUE_TYPE_I32) {
+ bh_assert(module->free_function == (uint32)-1);
+ module->free_function = export->index;
+ LOG_VERBOSE("Found free function, name: %s, index: %u",
+ export->name, export->index);
+ }
+ }
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0 && WASM_ENABLE_LABELS_AS_VALUES != 0
+ handle_table = wasm_interp_get_handle_table();
+#endif
+
+ for (i = 0; i < module->function_count; i++) {
+ WASMFunction *func = module->functions[i];
+ if (!wasm_loader_prepare_bytecode(module, func, i, error_buf,
+ error_buf_size)) {
+ return false;
+ }
+
+ if (i == module->function_count - 1) {
+ bh_assert(func->code + func->code_size == buf_code_end);
+ }
+ }
+
+ if (!module->possible_memory_grow) {
+ WASMMemoryImport *memory_import;
+ WASMMemory *memory;
+
+ if (aux_data_end_global && aux_heap_base_global
+ && aux_stack_top_global) {
+ uint64 init_memory_size;
+ uint32 shrunk_memory_size = align_uint(aux_heap_base, 8);
+
+ if (module->import_memory_count) {
+ memory_import = &module->import_memories[0].u.memory;
+ init_memory_size = (uint64)memory_import->num_bytes_per_page
+ * memory_import->init_page_count;
+ if (shrunk_memory_size <= init_memory_size) {
+ /* Reset memory info to decrease memory usage */
+ memory_import->num_bytes_per_page = shrunk_memory_size;
+ memory_import->init_page_count = 1;
+ LOG_VERBOSE("Shrink import memory size to %d",
+ shrunk_memory_size);
+ }
+ }
+ if (module->memory_count) {
+ memory = &module->memories[0];
+ init_memory_size = (uint64)memory->num_bytes_per_page
+ * memory->init_page_count;
+ if (shrunk_memory_size <= init_memory_size) {
+ /* Reset memory info to decrease memory usage */
+ memory->num_bytes_per_page = shrunk_memory_size;
+ memory->init_page_count = 1;
+ LOG_VERBOSE("Shrink memory size to %d", shrunk_memory_size);
+ }
+ }
+ }
+
+ if (module->import_memory_count) {
+ memory_import = &module->import_memories[0].u.memory;
+ if (memory_import->init_page_count < DEFAULT_MAX_PAGES)
+ memory_import->num_bytes_per_page *=
+ memory_import->init_page_count;
+ else
+ memory_import->num_bytes_per_page = UINT32_MAX;
+
+ if (memory_import->init_page_count > 0)
+ memory_import->init_page_count = memory_import->max_page_count =
+ 1;
+ else
+ memory_import->init_page_count = memory_import->max_page_count =
+ 0;
+ }
+
+ if (module->memory_count) {
+ memory = &module->memories[0];
+ if (memory->init_page_count < DEFAULT_MAX_PAGES)
+ memory->num_bytes_per_page *= memory->init_page_count;
+ else
+ memory->num_bytes_per_page = UINT32_MAX;
+
+ if (memory->init_page_count > 0)
+ memory->init_page_count = memory->max_page_count = 1;
+ else
+ memory->init_page_count = memory->max_page_count = 0;
+ }
+ }
+
+ calculate_global_data_offset(module);
+
+#if WASM_ENABLE_FAST_JIT != 0
+ if (!init_fast_jit_functions(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ if (!init_llvm_jit_functions_stage1(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0)
+ if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#else
+ /* Run aot_compile_wasm in a backend thread, so as not to block the main
+ thread fast jit execution, since applying llvm optimizations in
+ aot_compile_wasm may cost a lot of time.
+ Create thread with enough native stack to apply llvm optimizations */
+ if (os_thread_create(&module->llvm_jit_init_thread,
+ init_llvm_jit_functions_stage2_callback,
+ (void *)module, APP_THREAD_STACK_SIZE_DEFAULT * 8)
+ != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "create orcjit compile thread failed");
+ return false;
+ }
+#endif
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ /* Create threads to compile the jit functions */
+ if (!compile_jit_functions(module, error_buf, error_buf_size)) {
+ return false;
+ }
+#endif
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ wasm_runtime_dump_module_mem_consumption(module);
+#endif
+ return true;
+}
+
+static WASMModule *
+create_module(char *error_buf, uint32 error_buf_size)
+{
+ WASMModule *module =
+ loader_malloc(sizeof(WASMModule), error_buf, error_buf_size);
+ bh_list_status ret;
+
+ if (!module) {
+ return NULL;
+ }
+
+ module->module_type = Wasm_Module_Bytecode;
+
+ /* Set start_function to -1, means no start function */
+ module->start_function = (uint32)-1;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ module->br_table_cache_list = &module->br_table_cache_list_head;
+ ret = bh_list_init(module->br_table_cache_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ if (os_mutex_init(&module->instance_list_lock) != 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "init instance list lock failed");
+ wasm_runtime_free(module);
+ return NULL;
+ }
+#endif
+
+ (void)ret;
+ return module;
+}
+
+WASMModule *
+wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModule *module = create_module(error_buf, error_buf_size);
+ if (!module)
+ return NULL;
+
+ if (!load_from_sections(module, section_list, false, error_buf,
+ error_buf_size)) {
+ wasm_loader_unload(module);
+ return NULL;
+ }
+
+ LOG_VERBOSE("Load module from sections success.\n");
+ return module;
+}
+
+static void
+destroy_sections(WASMSection *section_list)
+{
+ WASMSection *section = section_list, *next;
+ while (section) {
+ next = section->next;
+ wasm_runtime_free(section);
+ section = next;
+ }
+}
+
+/* clang-format off */
+static uint8 section_ids[] = {
+ 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,
+#if WASM_ENABLE_BULK_MEMORY != 0
+ SECTION_TYPE_DATACOUNT,
+#endif
+ SECTION_TYPE_CODE,
+ SECTION_TYPE_DATA
+};
+/* clang-format on */
+
+static uint8
+get_section_index(uint8 section_type)
+{
+ uint8 max_id = sizeof(section_ids) / sizeof(uint8);
+
+ for (uint8 i = 0; i < max_id; i++) {
+ if (section_type == section_ids[i])
+ return i;
+ }
+
+ return (uint8)-1;
+}
+
+static bool
+create_sections(const uint8 *buf, uint32 size, WASMSection **p_section_list,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMSection *section_list_end = NULL, *section;
+ const uint8 *p = buf, *p_end = buf + size /*, *section_body*/;
+ uint8 section_type, section_index, last_section_index = (uint8)-1;
+ uint32 section_size;
+
+ bh_assert(!*p_section_list);
+
+ p += 8;
+ while (p < p_end) {
+ CHECK_BUF(p, p_end, 1);
+ section_type = read_uint8(p);
+ section_index = get_section_index(section_type);
+ if (section_index != (uint8)-1) {
+ if (section_type != SECTION_TYPE_USER) {
+ /* Custom sections may be inserted at any place,
+ while other sections must occur at most once
+ and in prescribed order. */
+ bh_assert(last_section_index == (uint8)-1
+ || last_section_index < section_index);
+ last_section_index = section_index;
+ }
+ read_leb_uint32(p, p_end, section_size);
+ CHECK_BUF1(p, p_end, section_size);
+
+ if (!(section = loader_malloc(sizeof(WASMSection), error_buf,
+ error_buf_size))) {
+ return false;
+ }
+
+ section->section_type = section_type;
+ section->section_body = (uint8 *)p;
+ section->section_body_size = section_size;
+
+ if (!*p_section_list)
+ *p_section_list = section_list_end = section;
+ else {
+ section_list_end->next = section;
+ section_list_end = section;
+ }
+
+ p += section_size;
+ }
+ else {
+ bh_assert(0);
+ }
+ }
+
+ (void)last_section_index;
+ return true;
+}
+
+static void
+exchange32(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 union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+static bool
+load(const uint8 *buf, uint32 size, WASMModule *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;
+ WASMSection *section_list = NULL;
+
+ CHECK_BUF1(p, p_end, sizeof(uint32));
+ magic_number = read_uint32(p);
+ if (!is_little_endian())
+ exchange32((uint8 *)&magic_number);
+
+ bh_assert(magic_number == WASM_MAGIC_NUMBER);
+
+ CHECK_BUF1(p, p_end, sizeof(uint32));
+ version = read_uint32(p);
+ if (!is_little_endian())
+ exchange32((uint8 *)&version);
+
+ if (version != WASM_CURRENT_VERSION) {
+ set_error_buf(error_buf, error_buf_size, "unknown binary version");
+ return false;
+ }
+
+ if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
+ || !load_from_sections(module, section_list, true, error_buf,
+ error_buf_size)) {
+ destroy_sections(section_list);
+ return false;
+ }
+
+ destroy_sections(section_list);
+ (void)p_end;
+ return true;
+}
+
+WASMModule *
+wasm_loader_load(uint8 *buf, uint32 size, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModule *module = create_module(error_buf, error_buf_size);
+ if (!module) {
+ return NULL;
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0
+ module->load_addr = (uint8 *)buf;
+ module->load_size = size;
+#endif
+
+ if (!load(buf, size, module, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ LOG_VERBOSE("Load module success.\n");
+ return module;
+
+fail:
+ wasm_loader_unload(module);
+ return NULL;
+}
+
+void
+wasm_loader_unload(WASMModule *module)
+{
+ uint32 i;
+
+ if (!module)
+ return;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ module->orcjit_stop_compiling = true;
+ if (module->llvm_jit_init_thread)
+ os_thread_join(module->llvm_jit_init_thread, NULL);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ /* Stop Fast/LLVM JIT compilation firstly to avoid accessing
+ module internal data after they were freed */
+ orcjit_stop_compile_threads(module);
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ if (module->func_ptrs)
+ wasm_runtime_free(module->func_ptrs);
+ if (module->comp_ctx)
+ aot_destroy_comp_context(module->comp_ctx);
+ if (module->comp_data)
+ aot_destroy_comp_data(module->comp_data);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ if (module->tierup_wait_lock_inited) {
+ os_mutex_destroy(&module->tierup_wait_lock);
+ os_cond_destroy(&module->tierup_wait_cond);
+ }
+#endif
+
+ if (module->types) {
+ for (i = 0; i < module->type_count; i++) {
+ if (module->types[i])
+ destroy_wasm_type(module->types[i]);
+ }
+ wasm_runtime_free(module->types);
+ }
+
+ if (module->imports)
+ wasm_runtime_free(module->imports);
+
+ if (module->functions) {
+ for (i = 0; i < module->function_count; i++) {
+ if (module->functions[i]) {
+ if (module->functions[i]->local_offsets)
+ wasm_runtime_free(module->functions[i]->local_offsets);
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (module->functions[i]->code_compiled)
+ wasm_runtime_free(module->functions[i]->code_compiled);
+ if (module->functions[i]->consts)
+ wasm_runtime_free(module->functions[i]->consts);
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+ if (module->functions[i]->fast_jit_jitted_code) {
+ jit_code_cache_free(
+ module->functions[i]->fast_jit_jitted_code);
+ }
+#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+ if (module->functions[i]->call_to_fast_jit_from_llvm_jit) {
+ jit_code_cache_free(
+ module->functions[i]->call_to_fast_jit_from_llvm_jit);
+ }
+#endif
+#endif
+ wasm_runtime_free(module->functions[i]);
+ }
+ }
+ wasm_runtime_free(module->functions);
+ }
+
+ if (module->tables)
+ wasm_runtime_free(module->tables);
+
+ if (module->memories)
+ wasm_runtime_free(module->memories);
+
+ if (module->globals)
+ wasm_runtime_free(module->globals);
+
+ if (module->exports)
+ wasm_runtime_free(module->exports);
+
+ if (module->table_segments) {
+ for (i = 0; i < module->table_seg_count; i++) {
+ if (module->table_segments[i].func_indexes)
+ wasm_runtime_free(module->table_segments[i].func_indexes);
+ }
+ wasm_runtime_free(module->table_segments);
+ }
+
+ if (module->data_segments) {
+ for (i = 0; i < module->data_seg_count; i++) {
+ if (module->data_segments[i])
+ wasm_runtime_free(module->data_segments[i]);
+ }
+ wasm_runtime_free(module->data_segments);
+ }
+
+ if (module->const_str_list) {
+ StringNode *node = module->const_str_list, *node_next;
+ while (node) {
+ node_next = node->next;
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ if (module->br_table_cache_list) {
+ BrTableCache *node = bh_list_first_elem(module->br_table_cache_list);
+ BrTableCache *node_next;
+ while (node) {
+ node_next = bh_list_elem_next(node);
+ wasm_runtime_free(node);
+ node = node_next;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ os_mutex_destroy(&module->instance_list_lock);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0
+ if (module->fast_jit_func_ptrs) {
+ wasm_runtime_free(module->fast_jit_func_ptrs);
+ }
+
+ for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) {
+ if (module->fast_jit_thread_locks_inited[i]) {
+ os_mutex_destroy(&module->fast_jit_thread_locks[i]);
+ }
+ }
+#endif
+
+ wasm_runtime_free(module);
+}
+
+bool
+wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
+ const uint8 *start_addr, const uint8 *code_end_addr,
+ uint8 label_type, uint8 **p_else_addr,
+ uint8 **p_end_addr)
+{
+ const uint8 *p = start_addr, *p_end = code_end_addr;
+ uint8 *else_addr = NULL;
+ char error_buf[128];
+ uint32 block_nested_depth = 1, count, i, j, t;
+ uint32 error_buf_size = sizeof(error_buf);
+ uint8 opcode, u8;
+ BlockAddr block_stack[16] = { 0 }, *block;
+
+ i = ((uintptr_t)start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
+ block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i;
+
+ for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) {
+ if (block[j].start_addr == start_addr) {
+ /* Cache hit */
+ *p_else_addr = block[j].else_addr;
+ *p_end_addr = block[j].end_addr;
+ return true;
+ }
+ }
+
+ /* Cache unhit */
+ block_stack[0].start_addr = start_addr;
+
+ while (p < code_end_addr) {
+ opcode = *p++;
+
+ switch (opcode) {
+ case WASM_OP_UNREACHABLE:
+ case WASM_OP_NOP:
+ break;
+
+ case WASM_OP_BLOCK:
+ case WASM_OP_LOOP:
+ case WASM_OP_IF:
+ /* block result type: 0x40/0x7F/0x7E/0x7D/0x7C */
+ u8 = read_uint8(p);
+ if (block_nested_depth
+ < sizeof(block_stack) / sizeof(BlockAddr)) {
+ block_stack[block_nested_depth].start_addr = p;
+ block_stack[block_nested_depth].else_addr = NULL;
+ }
+ block_nested_depth++;
+ break;
+
+ case EXT_OP_BLOCK:
+ case EXT_OP_LOOP:
+ case EXT_OP_IF:
+ /* block type */
+ skip_leb_uint32(p, p_end);
+ if (block_nested_depth
+ < sizeof(block_stack) / sizeof(BlockAddr)) {
+ block_stack[block_nested_depth].start_addr = p;
+ block_stack[block_nested_depth].else_addr = NULL;
+ }
+ block_nested_depth++;
+ break;
+
+ case WASM_OP_ELSE:
+ if (label_type == LABEL_TYPE_IF && block_nested_depth == 1)
+ else_addr = (uint8 *)(p - 1);
+ if (block_nested_depth - 1
+ < sizeof(block_stack) / sizeof(BlockAddr))
+ block_stack[block_nested_depth - 1].else_addr =
+ (uint8 *)(p - 1);
+ break;
+
+ case WASM_OP_END:
+ if (block_nested_depth == 1) {
+ if (label_type == LABEL_TYPE_IF)
+ *p_else_addr = else_addr;
+ *p_end_addr = (uint8 *)(p - 1);
+
+ block_stack[0].end_addr = (uint8 *)(p - 1);
+ for (t = 0; t < sizeof(block_stack) / sizeof(BlockAddr);
+ t++) {
+ start_addr = block_stack[t].start_addr;
+ if (start_addr) {
+ i = ((uintptr_t)start_addr)
+ & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
+ block =
+ block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i;
+ for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++)
+ if (!block[j].start_addr)
+ break;
+
+ if (j == BLOCK_ADDR_CONFLICT_SIZE) {
+ memmove(block + 1, block,
+ (BLOCK_ADDR_CONFLICT_SIZE - 1)
+ * sizeof(BlockAddr));
+ j = 0;
+ }
+ block[j].start_addr = block_stack[t].start_addr;
+ block[j].else_addr = block_stack[t].else_addr;
+ block[j].end_addr = block_stack[t].end_addr;
+ }
+ else
+ break;
+ }
+ return true;
+ }
+ else {
+ block_nested_depth--;
+ if (block_nested_depth
+ < sizeof(block_stack) / sizeof(BlockAddr))
+ block_stack[block_nested_depth].end_addr =
+ (uint8 *)(p - 1);
+ }
+ break;
+
+ case WASM_OP_BR:
+ case WASM_OP_BR_IF:
+ skip_leb_uint32(p, p_end); /* labelidx */
+ break;
+
+ case WASM_OP_BR_TABLE:
+ read_leb_uint32(p, p_end, count); /* lable num */
+#if WASM_ENABLE_FAST_INTERP != 0
+ for (i = 0; i <= count; i++) /* lableidxs */
+ skip_leb_uint32(p, p_end);
+#else
+ p += count + 1;
+ while (*p == WASM_OP_NOP)
+ p++;
+#endif
+ break;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ case EXT_OP_BR_TABLE_CACHE:
+ read_leb_uint32(p, p_end, count); /* lable num */
+ while (*p == WASM_OP_NOP)
+ p++;
+ break;
+#endif
+
+ case WASM_OP_RETURN:
+ break;
+
+ case WASM_OP_CALL:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL:
+#endif
+ skip_leb_uint32(p, p_end); /* funcidx */
+ break;
+
+ case WASM_OP_CALL_INDIRECT:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL_INDIRECT:
+#endif
+ skip_leb_uint32(p, p_end); /* typeidx */
+ CHECK_BUF(p, p_end, 1);
+ u8 = read_uint8(p); /* 0x00 */
+ break;
+
+ case WASM_OP_DROP:
+ case WASM_OP_SELECT:
+ case WASM_OP_DROP_64:
+ case WASM_OP_SELECT_64:
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_SELECT_T:
+ skip_leb_uint32(p, p_end); /* vec length */
+ CHECK_BUF(p, p_end, 1);
+ u8 = read_uint8(p); /* typeidx */
+ break;
+ case WASM_OP_TABLE_GET:
+ case WASM_OP_TABLE_SET:
+ skip_leb_uint32(p, p_end); /* table index */
+ break;
+ case WASM_OP_REF_NULL:
+ CHECK_BUF(p, p_end, 1);
+ u8 = read_uint8(p); /* type */
+ break;
+ case WASM_OP_REF_IS_NULL:
+ break;
+ case WASM_OP_REF_FUNC:
+ skip_leb_uint32(p, p_end); /* func index */
+ break;
+#endif /* WASM_ENABLE_REF_TYPES */
+ case WASM_OP_GET_LOCAL:
+ case WASM_OP_SET_LOCAL:
+ case WASM_OP_TEE_LOCAL:
+ case WASM_OP_GET_GLOBAL:
+ case WASM_OP_SET_GLOBAL:
+ case WASM_OP_GET_GLOBAL_64:
+ case WASM_OP_SET_GLOBAL_64:
+ case WASM_OP_SET_GLOBAL_AUX_STACK:
+ skip_leb_uint32(p, p_end); /* localidx */
+ break;
+
+ case EXT_OP_GET_LOCAL_FAST:
+ case EXT_OP_SET_LOCAL_FAST:
+ case EXT_OP_TEE_LOCAL_FAST:
+ CHECK_BUF(p, p_end, 1);
+ p++;
+ break;
+
+ case WASM_OP_I32_LOAD:
+ case WASM_OP_I64_LOAD:
+ case WASM_OP_F32_LOAD:
+ case WASM_OP_F64_LOAD:
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ case WASM_OP_I64_LOAD8_S:
+ case WASM_OP_I64_LOAD8_U:
+ case WASM_OP_I64_LOAD16_S:
+ case WASM_OP_I64_LOAD16_U:
+ case WASM_OP_I64_LOAD32_S:
+ case WASM_OP_I64_LOAD32_U:
+ case WASM_OP_I32_STORE:
+ case WASM_OP_I64_STORE:
+ case WASM_OP_F32_STORE:
+ case WASM_OP_F64_STORE:
+ case WASM_OP_I32_STORE8:
+ case WASM_OP_I32_STORE16:
+ case WASM_OP_I64_STORE8:
+ case WASM_OP_I64_STORE16:
+ case WASM_OP_I64_STORE32:
+ skip_leb_uint32(p, p_end); /* align */
+ skip_leb_uint32(p, p_end); /* offset */
+ break;
+
+ case WASM_OP_MEMORY_SIZE:
+ case WASM_OP_MEMORY_GROW:
+ skip_leb_uint32(p, p_end); /* 0x00 */
+ break;
+
+ case WASM_OP_I32_CONST:
+ skip_leb_int32(p, p_end);
+ break;
+ case WASM_OP_I64_CONST:
+ skip_leb_int64(p, p_end);
+ break;
+ case WASM_OP_F32_CONST:
+ p += sizeof(float32);
+ break;
+ case WASM_OP_F64_CONST:
+ p += sizeof(float64);
+ 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:
+ 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:
+ 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:
+ 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:
+ case WASM_OP_I32_CLZ:
+ case WASM_OP_I32_CTZ:
+ case WASM_OP_I32_POPCNT:
+ 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:
+ case WASM_OP_I32_AND:
+ case WASM_OP_I32_OR:
+ case WASM_OP_I32_XOR:
+ 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:
+ case WASM_OP_I64_CLZ:
+ case WASM_OP_I64_CTZ:
+ case WASM_OP_I64_POPCNT:
+ 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:
+ case WASM_OP_I64_AND:
+ case WASM_OP_I64_OR:
+ case WASM_OP_I64_XOR:
+ 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:
+ 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:
+ 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:
+ case WASM_OP_F32_COPYSIGN:
+ 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:
+ 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:
+ case WASM_OP_F64_COPYSIGN:
+ case WASM_OP_I32_WRAP_I64:
+ case WASM_OP_I32_TRUNC_S_F32:
+ case WASM_OP_I32_TRUNC_U_F32:
+ case WASM_OP_I32_TRUNC_S_F64:
+ case WASM_OP_I32_TRUNC_U_F64:
+ case WASM_OP_I64_EXTEND_S_I32:
+ case WASM_OP_I64_EXTEND_U_I32:
+ case WASM_OP_I64_TRUNC_S_F32:
+ case WASM_OP_I64_TRUNC_U_F32:
+ case WASM_OP_I64_TRUNC_S_F64:
+ case WASM_OP_I64_TRUNC_U_F64:
+ case WASM_OP_F32_CONVERT_S_I32:
+ case WASM_OP_F32_CONVERT_U_I32:
+ case WASM_OP_F32_CONVERT_S_I64:
+ case WASM_OP_F32_CONVERT_U_I64:
+ case WASM_OP_F32_DEMOTE_F64:
+ case WASM_OP_F64_CONVERT_S_I32:
+ case WASM_OP_F64_CONVERT_U_I32:
+ case WASM_OP_F64_CONVERT_S_I64:
+ case WASM_OP_F64_CONVERT_U_I64:
+ case WASM_OP_F64_PROMOTE_F32:
+ case WASM_OP_I32_REINTERPRET_F32:
+ case WASM_OP_I64_REINTERPRET_F64:
+ case WASM_OP_F32_REINTERPRET_I32:
+ case WASM_OP_F64_REINTERPRET_I64:
+ case WASM_OP_I32_EXTEND8_S:
+ case WASM_OP_I32_EXTEND16_S:
+ case WASM_OP_I64_EXTEND8_S:
+ case WASM_OP_I64_EXTEND16_S:
+ case WASM_OP_I64_EXTEND32_S:
+ break;
+ case WASM_OP_MISC_PREFIX:
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(p, p_end, opcode1);
+
+ switch (opcode1) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ skip_leb_uint32(p, p_end);
+ /* skip memory idx */
+ p++;
+ break;
+ case WASM_OP_DATA_DROP:
+ skip_leb_uint32(p, p_end);
+ break;
+ case WASM_OP_MEMORY_COPY:
+ /* skip two memory idx */
+ p += 2;
+ break;
+ case WASM_OP_MEMORY_FILL:
+ /* skip memory idx */
+ p++;
+ break;
+#endif
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ case WASM_OP_TABLE_COPY:
+ /* tableidx */
+ skip_leb_uint32(p, p_end);
+ /* elemidx */
+ skip_leb_uint32(p, p_end);
+ break;
+ case WASM_OP_ELEM_DROP:
+ /* elemidx */
+ skip_leb_uint32(p, p_end);
+ break;
+ case WASM_OP_TABLE_SIZE:
+ case WASM_OP_TABLE_GROW:
+ case WASM_OP_TABLE_FILL:
+ skip_leb_uint32(p, p_end); /* table idx */
+ break;
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ bh_assert(0);
+ break;
+ }
+ break;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case WASM_OP_ATOMIC_PREFIX:
+ {
+ /* atomic_op (1 u8) + memarg (2 u32_leb) */
+ opcode = read_uint8(p);
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ skip_leb_uint32(p, p_end); /* align */
+ skip_leb_uint32(p, p_end); /* offset */
+ }
+ else {
+ /* atomic.fence doesn't have memarg */
+ p++;
+ }
+ break;
+ }
+#endif
+
+ default:
+ bh_assert(0);
+ break;
+ }
+ }
+
+ (void)u8;
+ return false;
+}
+
+#define REF_I32 VALUE_TYPE_I32
+#define REF_F32 VALUE_TYPE_F32
+#define REF_I64_1 VALUE_TYPE_I64
+#define REF_I64_2 VALUE_TYPE_I64
+#define REF_F64_1 VALUE_TYPE_F64
+#define REF_F64_2 VALUE_TYPE_F64
+#define REF_ANY VALUE_TYPE_ANY
+
+#if WASM_ENABLE_FAST_INTERP != 0
+
+#if WASM_DEBUG_PREPROCESSOR != 0
+#define LOG_OP(...) os_printf(__VA_ARGS__)
+#else
+#define LOG_OP(...) (void)0
+#endif
+
+#define PATCH_ELSE 0
+#define PATCH_END 1
+typedef struct BranchBlockPatch {
+ struct BranchBlockPatch *next;
+ uint8 patch_type;
+ uint8 *code_compiled;
+} BranchBlockPatch;
+#endif
+
+typedef struct BranchBlock {
+ uint8 label_type;
+ BlockType block_type;
+ uint8 *start_addr;
+ uint8 *else_addr;
+ uint8 *end_addr;
+ uint32 stack_cell_num;
+#if WASM_ENABLE_FAST_INTERP != 0
+ uint16 dynamic_offset;
+ uint8 *code_compiled;
+ BranchBlockPatch *patch_list;
+ /* This is used to save params frame_offset of of if block */
+ int16 *param_frame_offsets;
+#endif
+
+ /* Indicate the operand stack is in polymorphic state.
+ * If the opcode is one of unreachable/br/br_table/return, stack is marked
+ * to polymorphic state until the block's 'end' opcode is processed.
+ * If stack is in polymorphic state and stack is empty, instruction can
+ * pop any type of value directly without decreasing stack top pointer
+ * and stack cell num. */
+ bool is_stack_polymorphic;
+} BranchBlock;
+
+typedef struct WASMLoaderContext {
+ /* frame ref stack */
+ uint8 *frame_ref;
+ uint8 *frame_ref_bottom;
+ uint8 *frame_ref_boundary;
+ uint32 frame_ref_size;
+ uint32 stack_cell_num;
+ uint32 max_stack_cell_num;
+
+ /* frame csp stack */
+ BranchBlock *frame_csp;
+ BranchBlock *frame_csp_bottom;
+ BranchBlock *frame_csp_boundary;
+ uint32 frame_csp_size;
+ uint32 csp_num;
+ uint32 max_csp_num;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* frame offset stack */
+ int16 *frame_offset;
+ int16 *frame_offset_bottom;
+ int16 *frame_offset_boundary;
+ uint32 frame_offset_size;
+ int16 dynamic_offset;
+ int16 start_dynamic_offset;
+ int16 max_dynamic_offset;
+
+ /* preserved local offset */
+ int16 preserved_local_offset;
+
+ /* const buffer */
+ uint8 *const_buf;
+ uint16 num_const;
+ uint16 const_cell_num;
+ uint32 const_buf_size;
+
+ /* processed code */
+ uint8 *p_code_compiled;
+ uint8 *p_code_compiled_end;
+ uint32 code_compiled_size;
+ /* If the last opcode will be dropped, the peak memory usage will be larger
+ * than the final code_compiled_size, we record the peak size to ensure
+ * there will not be invalid memory access during second traverse */
+ uint32 code_compiled_peak_size;
+#endif
+} WASMLoaderContext;
+
+typedef struct Const {
+ WASMValue value;
+ uint16 slot_index;
+ uint8 value_type;
+} Const;
+
+static void *
+memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 *mem_new;
+ bh_assert(size_new > size_old);
+ if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
+ bh_memcpy_s(mem_new, size_new, mem_old, size_old);
+ memset(mem_new + size_old, 0, size_new - size_old);
+ wasm_runtime_free(mem_old);
+ }
+ return mem_new;
+}
+
+#define MEM_REALLOC(mem, size_old, size_new) \
+ do { \
+ void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \
+ error_buf_size); \
+ if (!mem_new) \
+ goto fail; \
+ mem = mem_new; \
+ } while (0)
+
+#define CHECK_CSP_PUSH() \
+ do { \
+ if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
+ MEM_REALLOC( \
+ ctx->frame_csp_bottom, ctx->frame_csp_size, \
+ (uint32)(ctx->frame_csp_size + 8 * sizeof(BranchBlock))); \
+ ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \
+ ctx->frame_csp_boundary = \
+ ctx->frame_csp_bottom \
+ + ctx->frame_csp_size / sizeof(BranchBlock); \
+ ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \
+ } \
+ } while (0)
+
+#define CHECK_CSP_POP() \
+ do { \
+ bh_assert(ctx->csp_num >= 1); \
+ } while (0)
+
+#if WASM_ENABLE_FAST_INTERP != 0
+static bool
+check_offset_push(WASMLoaderContext *ctx, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 cell_num = (uint32)(ctx->frame_offset - ctx->frame_offset_bottom);
+ if (ctx->frame_offset >= ctx->frame_offset_boundary) {
+ MEM_REALLOC(ctx->frame_offset_bottom, ctx->frame_offset_size,
+ ctx->frame_offset_size + 16);
+ ctx->frame_offset_size += 16;
+ ctx->frame_offset_boundary =
+ ctx->frame_offset_bottom + ctx->frame_offset_size / sizeof(int16);
+ ctx->frame_offset = ctx->frame_offset_bottom + cell_num;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_offset_pop(WASMLoaderContext *ctx, uint32 cells)
+{
+ if (ctx->frame_offset - cells < ctx->frame_offset_bottom)
+ return false;
+ return true;
+}
+
+static void
+free_label_patch_list(BranchBlock *frame_csp)
+{
+ BranchBlockPatch *label_patch = frame_csp->patch_list;
+ BranchBlockPatch *next;
+ while (label_patch != NULL) {
+ next = label_patch->next;
+ wasm_runtime_free(label_patch);
+ label_patch = next;
+ }
+ frame_csp->patch_list = NULL;
+}
+
+static void
+free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
+{
+ BranchBlock *tmp_csp = frame_csp;
+
+ for (uint32 i = 0; i < csp_num; i++) {
+ free_label_patch_list(tmp_csp);
+ tmp_csp++;
+ }
+}
+
+#endif
+
+static bool
+check_stack_push(WASMLoaderContext *ctx, char *error_buf, uint32 error_buf_size)
+{
+ if (ctx->frame_ref >= ctx->frame_ref_boundary) {
+ MEM_REALLOC(ctx->frame_ref_bottom, ctx->frame_ref_size,
+ ctx->frame_ref_size + 16);
+ ctx->frame_ref_size += 16;
+ ctx->frame_ref_boundary = ctx->frame_ref_bottom + ctx->frame_ref_size;
+ ctx->frame_ref = ctx->frame_ref_bottom + ctx->stack_cell_num;
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type,
+ char *error_buf, uint32 error_buf_size)
+{
+ bh_assert(!((is_32bit_type(type) && stack_cell_num < 1)
+ || (is_64bit_type(type) && stack_cell_num < 2)));
+
+ bh_assert(!(
+ (type == VALUE_TYPE_I32 && *(frame_ref - 1) != REF_I32)
+ || (type == VALUE_TYPE_F32 && *(frame_ref - 1) != REF_F32)
+ || (type == VALUE_TYPE_I64
+ && (*(frame_ref - 2) != REF_I64_1 || *(frame_ref - 1) != REF_I64_2))
+ || (type == VALUE_TYPE_F64
+ && (*(frame_ref - 2) != REF_F64_1
+ || *(frame_ref - 1) != REF_F64_2))));
+ return true;
+}
+
+static bool
+check_stack_pop(WASMLoaderContext *ctx, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ int32 block_stack_cell_num =
+ (int32)(ctx->stack_cell_num - (ctx->frame_csp - 1)->stack_cell_num);
+
+ if (block_stack_cell_num > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
+ /* the stack top is a value of any type, return success */
+ return true;
+ }
+
+ if (!check_stack_top_values(ctx->frame_ref, block_stack_cell_num, type,
+ error_buf, error_buf_size))
+ return false;
+
+ return true;
+}
+
+static void
+wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
+{
+ if (ctx) {
+ if (ctx->frame_ref_bottom)
+ wasm_runtime_free(ctx->frame_ref_bottom);
+ if (ctx->frame_csp_bottom) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
+#endif
+ wasm_runtime_free(ctx->frame_csp_bottom);
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (ctx->frame_offset_bottom)
+ wasm_runtime_free(ctx->frame_offset_bottom);
+ if (ctx->const_buf)
+ wasm_runtime_free(ctx->const_buf);
+#endif
+ wasm_runtime_free(ctx);
+ }
+}
+
+static WASMLoaderContext *
+wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size)
+{
+ WASMLoaderContext *loader_ctx =
+ loader_malloc(sizeof(WASMLoaderContext), error_buf, error_buf_size);
+ if (!loader_ctx)
+ return NULL;
+
+ loader_ctx->frame_ref_size = 32;
+ if (!(loader_ctx->frame_ref_bottom = loader_ctx->frame_ref = loader_malloc(
+ loader_ctx->frame_ref_size, error_buf, error_buf_size)))
+ goto fail;
+ loader_ctx->frame_ref_boundary = loader_ctx->frame_ref_bottom + 32;
+
+ loader_ctx->frame_csp_size = sizeof(BranchBlock) * 8;
+ if (!(loader_ctx->frame_csp_bottom = loader_ctx->frame_csp = loader_malloc(
+ loader_ctx->frame_csp_size, error_buf, error_buf_size)))
+ goto fail;
+ loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ loader_ctx->frame_offset_size = sizeof(int16) * 32;
+ if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset =
+ loader_malloc(loader_ctx->frame_offset_size, error_buf,
+ error_buf_size)))
+ goto fail;
+ loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32;
+
+ loader_ctx->num_const = 0;
+ loader_ctx->const_buf_size = sizeof(Const) * 8;
+ if (!(loader_ctx->const_buf = loader_malloc(loader_ctx->const_buf_size,
+ error_buf, error_buf_size)))
+ goto fail;
+
+ if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) {
+ set_error_buf(error_buf, error_buf_size,
+ "fast interpreter offset overflow");
+ goto fail;
+ }
+
+ loader_ctx->start_dynamic_offset = loader_ctx->dynamic_offset =
+ loader_ctx->max_dynamic_offset =
+ func->param_cell_num + func->local_cell_num;
+#endif
+ return loader_ctx;
+
+fail:
+ wasm_loader_ctx_destroy(loader_ctx);
+ return NULL;
+}
+
+static bool
+wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ if (!check_stack_push(ctx, error_buf, error_buf_size))
+ return false;
+
+ *ctx->frame_ref++ = type;
+ ctx->stack_cell_num++;
+ if (ctx->stack_cell_num > ctx->max_stack_cell_num)
+ ctx->max_stack_cell_num = ctx->stack_cell_num;
+
+ if (is_32bit_type(type))
+ return true;
+
+ if (!check_stack_push(ctx, error_buf, error_buf_size))
+ return false;
+ *ctx->frame_ref++ = type;
+ ctx->stack_cell_num++;
+ if (ctx->stack_cell_num > ctx->max_stack_cell_num) {
+ ctx->max_stack_cell_num = ctx->stack_cell_num;
+ bh_assert(ctx->max_stack_cell_num <= UINT16_MAX);
+ }
+ return true;
+}
+
+static bool
+wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
+ uint32 error_buf_size)
+{
+ BranchBlock *cur_block = ctx->frame_csp - 1;
+ int32 available_stack_cell =
+ (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
+
+ /* Directly return success if current block is in stack
+ * polymorphic state while stack is empty. */
+ if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
+ return true;
+
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ if (!check_stack_pop(ctx, type, error_buf, error_buf_size))
+ return false;
+
+ ctx->frame_ref--;
+ ctx->stack_cell_num--;
+
+ if (is_32bit_type(type) || *ctx->frame_ref == VALUE_TYPE_ANY)
+ return true;
+
+ ctx->frame_ref--;
+ ctx->stack_cell_num--;
+ return true;
+}
+
+static bool
+wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
+ uint8 type_push, uint8 type_pop, char *error_buf,
+ uint32 error_buf_size)
+{
+ for (int i = 0; i < pop_cnt; i++) {
+ if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf,
+ error_buf_size))
+ return false;
+ }
+ if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size))
+ return false;
+ return true;
+}
+
+static bool
+wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type,
+ BlockType block_type, uint8 *start_addr,
+ char *error_buf, uint32 error_buf_size)
+{
+ CHECK_CSP_PUSH();
+ memset(ctx->frame_csp, 0, sizeof(BranchBlock));
+ ctx->frame_csp->label_type = label_type;
+ ctx->frame_csp->block_type = block_type;
+ ctx->frame_csp->start_addr = start_addr;
+ ctx->frame_csp->stack_cell_num = ctx->stack_cell_num;
+#if WASM_ENABLE_FAST_INTERP != 0
+ ctx->frame_csp->dynamic_offset = ctx->dynamic_offset;
+ ctx->frame_csp->patch_list = NULL;
+#endif
+ ctx->frame_csp++;
+ ctx->csp_num++;
+ if (ctx->csp_num > ctx->max_csp_num) {
+ ctx->max_csp_num = ctx->csp_num;
+ bh_assert(ctx->max_csp_num <= UINT16_MAX);
+ }
+ return true;
+fail:
+ return false;
+}
+
+static bool
+wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf,
+ uint32 error_buf_size)
+{
+ CHECK_CSP_POP();
+#if WASM_ENABLE_FAST_INTERP != 0
+ if ((ctx->frame_csp - 1)->param_frame_offsets)
+ wasm_runtime_free((ctx->frame_csp - 1)->param_frame_offsets);
+#endif
+ ctx->frame_csp--;
+ ctx->csp_num--;
+ return true;
+}
+
+#if WASM_ENABLE_FAST_INTERP != 0
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+#define emit_label(opcode) \
+ do { \
+ wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \
+ LOG_OP("\nemit_op [%02x]\t", opcode); \
+ } while (0)
+#define skip_label() \
+ do { \
+ wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \
+ LOG_OP("\ndelete last op\n"); \
+ } while (0)
+#else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#define emit_label(opcode) \
+ do { \
+ int32 offset = \
+ (int32)((uint8 *)handle_table[opcode] - (uint8 *)handle_table[0]); \
+ if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \
+ set_error_buf(error_buf, error_buf_size, \
+ "pre-compiled label offset out of range"); \
+ goto fail; \
+ } \
+ wasm_loader_emit_int16(loader_ctx, offset); \
+ LOG_OP("\nemit_op [%02x]\t", opcode); \
+ } while (0)
+#define skip_label() \
+ do { \
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \
+ LOG_OP("\ndelete last op\n"); \
+ } while (0)
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#define emit_label(opcode) \
+ do { \
+ wasm_loader_emit_uint8(loader_ctx, opcode); \
+ LOG_OP("\nemit_op [%02x]\t", opcode); \
+ } while (0)
+#define skip_label() \
+ do { \
+ wasm_loader_emit_backspace(loader_ctx, sizeof(uint8)); \
+ LOG_OP("\ndelete last op\n"); \
+ } while (0)
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+
+#define emit_empty_label_addr_and_frame_ip(type) \
+ do { \
+ if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \
+ loader_ctx->p_code_compiled, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ /* label address, to be patched */ \
+ wasm_loader_emit_ptr(loader_ctx, NULL); \
+ } while (0)
+
+#define emit_br_info(frame_csp) \
+ do { \
+ if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define LAST_OP_OUTPUT_I32() \
+ (last_op >= WASM_OP_I32_EQZ && last_op <= WASM_OP_I32_ROTR) \
+ || (last_op == WASM_OP_I32_LOAD || last_op == WASM_OP_F32_LOAD) \
+ || (last_op >= WASM_OP_I32_LOAD8_S && last_op <= WASM_OP_I32_LOAD16_U) \
+ || (last_op >= WASM_OP_F32_ABS && last_op <= WASM_OP_F32_COPYSIGN) \
+ || (last_op >= WASM_OP_I32_WRAP_I64 \
+ && last_op <= WASM_OP_I32_TRUNC_U_F64) \
+ || (last_op >= WASM_OP_F32_CONVERT_S_I32 \
+ && last_op <= WASM_OP_F32_DEMOTE_F64) \
+ || (last_op == WASM_OP_I32_REINTERPRET_F32) \
+ || (last_op == WASM_OP_F32_REINTERPRET_I32) \
+ || (last_op == EXT_OP_COPY_STACK_TOP)
+
+#define LAST_OP_OUTPUT_I64() \
+ (last_op >= WASM_OP_I64_CLZ && last_op <= WASM_OP_I64_ROTR) \
+ || (last_op >= WASM_OP_F64_ABS && last_op <= WASM_OP_F64_COPYSIGN) \
+ || (last_op == WASM_OP_I64_LOAD || last_op == WASM_OP_F64_LOAD) \
+ || (last_op >= WASM_OP_I64_LOAD8_S && last_op <= WASM_OP_I64_LOAD32_U) \
+ || (last_op >= WASM_OP_I64_EXTEND_S_I32 \
+ && last_op <= WASM_OP_I64_TRUNC_U_F64) \
+ || (last_op >= WASM_OP_F64_CONVERT_S_I32 \
+ && last_op <= WASM_OP_F64_PROMOTE_F32) \
+ || (last_op == WASM_OP_I64_REINTERPRET_F64) \
+ || (last_op == WASM_OP_F64_REINTERPRET_I64) \
+ || (last_op == EXT_OP_COPY_STACK_TOP_I64)
+
+#define GET_CONST_OFFSET(type, val) \
+ do { \
+ if (!(wasm_loader_get_const_offset(loader_ctx, type, &val, \
+ &operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define GET_CONST_F32_OFFSET(type, fval) \
+ do { \
+ if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \
+ &operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define GET_CONST_F64_OFFSET(type, fval) \
+ do { \
+ if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \
+ &operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define emit_operand(ctx, offset) \
+ do { \
+ wasm_loader_emit_int16(ctx, offset); \
+ LOG_OP("%d\t", offset); \
+ } while (0)
+
+#define emit_byte(ctx, byte) \
+ do { \
+ wasm_loader_emit_uint8(ctx, byte); \
+ LOG_OP("%d\t", byte); \
+ } while (0)
+
+#define emit_uint32(ctx, value) \
+ do { \
+ wasm_loader_emit_uint32(ctx, value); \
+ LOG_OP("%d\t", value); \
+ } while (0)
+
+#define emit_uint64(ctx, value) \
+ do { \
+ wasm_loader_emit_const(ctx, &value, false); \
+ LOG_OP("%lld\t", value); \
+ } while (0)
+
+#define emit_float32(ctx, value) \
+ do { \
+ wasm_loader_emit_const(ctx, &value, true); \
+ LOG_OP("%f\t", value); \
+ } while (0)
+
+#define emit_float64(ctx, value) \
+ do { \
+ wasm_loader_emit_const(ctx, &value, false); \
+ LOG_OP("%f\t", value); \
+ } while (0)
+
+static bool
+wasm_loader_ctx_reinit(WASMLoaderContext *ctx)
+{
+ if (!(ctx->p_code_compiled =
+ loader_malloc(ctx->code_compiled_peak_size, NULL, 0)))
+ return false;
+ ctx->p_code_compiled_end =
+ ctx->p_code_compiled + ctx->code_compiled_peak_size;
+
+ /* clean up frame ref */
+ memset(ctx->frame_ref_bottom, 0, ctx->frame_ref_size);
+ ctx->frame_ref = ctx->frame_ref_bottom;
+ ctx->stack_cell_num = 0;
+
+ /* clean up frame csp */
+ memset(ctx->frame_csp_bottom, 0, ctx->frame_csp_size);
+ ctx->frame_csp = ctx->frame_csp_bottom;
+ ctx->csp_num = 0;
+ ctx->max_csp_num = 0;
+
+ /* clean up frame offset */
+ memset(ctx->frame_offset_bottom, 0, ctx->frame_offset_size);
+ ctx->frame_offset = ctx->frame_offset_bottom;
+ ctx->dynamic_offset = ctx->start_dynamic_offset;
+
+ /* init preserved local offsets */
+ ctx->preserved_local_offset = ctx->max_dynamic_offset;
+
+ /* const buf is reserved */
+ return true;
+}
+
+static void
+increase_compiled_code_space(WASMLoaderContext *ctx, int32 size)
+{
+ ctx->code_compiled_size += size;
+ if (ctx->code_compiled_size >= ctx->code_compiled_peak_size) {
+ ctx->code_compiled_peak_size = ctx->code_compiled_size;
+ }
+}
+
+static void
+wasm_loader_emit_const(WASMLoaderContext *ctx, void *value, bool is_32_bit)
+{
+ uint32 size = is_32_bit ? sizeof(uint32) : sizeof(uint64);
+
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ bh_memcpy_s(ctx->p_code_compiled,
+ (uint32)(ctx->p_code_compiled_end - ctx->p_code_compiled),
+ value, size);
+ ctx->p_code_compiled += size;
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, size);
+ }
+}
+
+static void
+wasm_loader_emit_uint32(WASMLoaderContext *ctx, uint32 value)
+{
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ STORE_U32(ctx->p_code_compiled, value);
+ ctx->p_code_compiled += sizeof(uint32);
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, sizeof(uint32));
+ }
+}
+
+static void
+wasm_loader_emit_int16(WASMLoaderContext *ctx, int16 value)
+{
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ STORE_U16(ctx->p_code_compiled, (uint16)value);
+ ctx->p_code_compiled += sizeof(int16);
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, sizeof(uint16));
+ }
+}
+
+static void
+wasm_loader_emit_uint8(WASMLoaderContext *ctx, uint8 value)
+{
+ if (ctx->p_code_compiled) {
+ *(ctx->p_code_compiled) = value;
+ ctx->p_code_compiled += sizeof(uint8);
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ ctx->p_code_compiled++;
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ }
+ else {
+ increase_compiled_code_space(ctx, sizeof(uint8));
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ increase_compiled_code_space(ctx, sizeof(uint8));
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ }
+}
+
+static void
+wasm_loader_emit_ptr(WASMLoaderContext *ctx, void *value)
+{
+ if (ctx->p_code_compiled) {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+#endif
+ STORE_PTR(ctx->p_code_compiled, value);
+ ctx->p_code_compiled += sizeof(void *);
+ }
+ else {
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+#endif
+ increase_compiled_code_space(ctx, sizeof(void *));
+ }
+}
+
+static void
+wasm_loader_emit_backspace(WASMLoaderContext *ctx, uint32 size)
+{
+ if (ctx->p_code_compiled) {
+ ctx->p_code_compiled -= size;
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ if (size == sizeof(uint8)) {
+ ctx->p_code_compiled--;
+ bh_assert(((uintptr_t)ctx->p_code_compiled & 1) == 0);
+ }
+#endif
+ }
+ else {
+ ctx->code_compiled_size -= size;
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+ if (size == sizeof(uint8)) {
+ ctx->code_compiled_size--;
+ bh_assert((ctx->code_compiled_size & 1) == 0);
+ }
+#endif
+ }
+}
+
+static bool
+preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
+ uint32 local_index, uint32 local_type,
+ bool *preserved, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 i = 0;
+ int16 preserved_offset = (int16)local_index;
+
+ *preserved = false;
+ while (i < loader_ctx->stack_cell_num) {
+ uint8 cur_type = loader_ctx->frame_ref_bottom[i];
+
+ /* move previous local into dynamic space before a set/tee_local opcode
+ */
+ if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) {
+ if (!(*preserved)) {
+ *preserved = true;
+ skip_label();
+ preserved_offset = loader_ctx->preserved_local_offset;
+ if (loader_ctx->p_code_compiled) {
+ bh_assert(preserved_offset != (int16)local_index);
+ }
+ if (is_32bit_type(local_type)) {
+ /* Only increase preserve offset in the second traversal */
+ if (loader_ctx->p_code_compiled)
+ loader_ctx->preserved_local_offset++;
+ emit_label(EXT_OP_COPY_STACK_TOP);
+ }
+ else {
+ if (loader_ctx->p_code_compiled)
+ loader_ctx->preserved_local_offset += 2;
+ emit_label(EXT_OP_COPY_STACK_TOP_I64);
+ }
+ emit_operand(loader_ctx, local_index);
+ emit_operand(loader_ctx, preserved_offset);
+ emit_label(opcode);
+ }
+ loader_ctx->frame_offset_bottom[i] = preserved_offset;
+ }
+
+ if (is_32bit_type(cur_type))
+ i++;
+ else
+ i += 2;
+ }
+
+ return true;
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
+fail:
+ return false;
+#endif
+#endif
+}
+
+static bool
+preserve_local_for_block(WASMLoaderContext *loader_ctx, uint8 opcode,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint32 i = 0;
+ bool preserve_local;
+
+ /* preserve locals before blocks to ensure that "tee/set_local" inside
+ blocks will not influence the value of these locals */
+ while (i < loader_ctx->stack_cell_num) {
+ int16 cur_offset = loader_ctx->frame_offset_bottom[i];
+ uint8 cur_type = loader_ctx->frame_ref_bottom[i];
+
+ if ((cur_offset < loader_ctx->start_dynamic_offset)
+ && (cur_offset >= 0)) {
+ if (!(preserve_referenced_local(loader_ctx, opcode, cur_offset,
+ cur_type, &preserve_local,
+ error_buf, error_buf_size)))
+ return false;
+ }
+
+ if (is_32bit_type(cur_type == VALUE_TYPE_I32)) {
+ i++;
+ }
+ else {
+ i += 2;
+ }
+ }
+
+ return true;
+}
+
+static bool
+add_label_patch_to_list(BranchBlock *frame_csp, uint8 patch_type,
+ uint8 *p_code_compiled, char *error_buf,
+ uint32 error_buf_size)
+{
+ BranchBlockPatch *patch =
+ loader_malloc(sizeof(BranchBlockPatch), error_buf, error_buf_size);
+ if (!patch) {
+ return false;
+ }
+ patch->patch_type = patch_type;
+ patch->code_compiled = p_code_compiled;
+ if (!frame_csp->patch_list) {
+ frame_csp->patch_list = patch;
+ patch->next = NULL;
+ }
+ else {
+ patch->next = frame_csp->patch_list;
+ frame_csp->patch_list = patch;
+ }
+ return true;
+}
+
+static void
+apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type)
+{
+ BranchBlock *frame_csp = ctx->frame_csp - depth;
+ BranchBlockPatch *node = frame_csp->patch_list;
+ BranchBlockPatch *node_prev = NULL, *node_next;
+
+ if (!ctx->p_code_compiled)
+ return;
+
+ while (node) {
+ node_next = node->next;
+ if (node->patch_type == patch_type) {
+ STORE_PTR(node->code_compiled, ctx->p_code_compiled);
+ if (node_prev == NULL) {
+ frame_csp->patch_list = node_next;
+ }
+ else {
+ node_prev->next = node_next;
+ }
+ wasm_runtime_free(node);
+ }
+ else {
+ node_prev = node;
+ }
+ node = node_next;
+ }
+}
+
+static bool
+wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
+ char *error_buf, uint32 error_buf_size)
+{
+ /* br info layout:
+ * a) arity of target block
+ * b) total cell num of arity values
+ * c) each arity value's cell num
+ * d) each arity value's src frame offset
+ * e) each arity values's dst dynamic offset
+ * f) branch target address
+ *
+ * Note: b-e are omitted when arity is 0 so that
+ * interpreter can recover the br info quickly.
+ */
+ BlockType *block_type = &frame_csp->block_type;
+ uint8 *types = NULL, cell;
+ uint32 arity = 0;
+ int32 i;
+ int16 *frame_offset = ctx->frame_offset;
+ uint16 dynamic_offset;
+
+ /* Note: loop's arity is different from if and block. loop's arity is
+ * its parameter count while if and block arity is result count.
+ */
+ if (frame_csp->label_type == LABEL_TYPE_LOOP)
+ arity = block_type_get_param_types(block_type, &types);
+ else
+ arity = block_type_get_result_types(block_type, &types);
+
+ /* Part a */
+ emit_uint32(ctx, arity);
+
+ if (arity) {
+ /* Part b */
+ emit_uint32(ctx, wasm_get_cell_num(types, arity));
+
+ /* Part c */
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ cell = (uint8)wasm_value_type_cell_num(types[i]);
+ emit_byte(ctx, cell);
+ }
+ /* Part d */
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ cell = (uint8)wasm_value_type_cell_num(types[i]);
+ frame_offset -= cell;
+ emit_operand(ctx, *(int16 *)(frame_offset));
+ }
+ /* Part e */
+ dynamic_offset =
+ frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ cell = (uint8)wasm_value_type_cell_num(types[i]);
+ dynamic_offset -= cell;
+ emit_operand(ctx, dynamic_offset);
+ }
+ }
+
+ /* Part f */
+ if (frame_csp->label_type == LABEL_TYPE_LOOP) {
+ wasm_loader_emit_ptr(ctx, frame_csp->code_compiled);
+ }
+ else {
+ if (!add_label_patch_to_list(frame_csp, PATCH_END, ctx->p_code_compiled,
+ error_buf, error_buf_size))
+ return false;
+ /* label address, to be patched */
+ wasm_loader_emit_ptr(ctx, NULL);
+ }
+
+ return true;
+}
+
+static bool
+wasm_loader_push_frame_offset(WASMLoaderContext *ctx, uint8 type,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ /* only check memory overflow in first traverse */
+ if (ctx->p_code_compiled == NULL) {
+ if (!check_offset_push(ctx, error_buf, error_buf_size))
+ return false;
+ }
+
+ if (disable_emit)
+ *(ctx->frame_offset)++ = operand_offset;
+ else {
+ emit_operand(ctx, ctx->dynamic_offset);
+ *(ctx->frame_offset)++ = ctx->dynamic_offset;
+ ctx->dynamic_offset++;
+ if (ctx->dynamic_offset > ctx->max_dynamic_offset) {
+ ctx->max_dynamic_offset = ctx->dynamic_offset;
+ bh_assert(ctx->max_dynamic_offset < INT16_MAX);
+ }
+ }
+
+ if (is_32bit_type(type))
+ return true;
+
+ if (ctx->p_code_compiled == NULL) {
+ if (!check_offset_push(ctx, error_buf, error_buf_size))
+ return false;
+ }
+
+ ctx->frame_offset++;
+ if (!disable_emit) {
+ ctx->dynamic_offset++;
+ if (ctx->dynamic_offset > ctx->max_dynamic_offset) {
+ ctx->max_dynamic_offset = ctx->dynamic_offset;
+ bh_assert(ctx->max_dynamic_offset < INT16_MAX);
+ }
+ }
+ return true;
+}
+
+/* This function should be in front of wasm_loader_pop_frame_ref
+ as they both use ctx->stack_cell_num, and ctx->stack_cell_num
+ will be modified by wasm_loader_pop_frame_ref */
+static bool
+wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
+ char *error_buf, uint32 error_buf_size)
+{
+ /* if ctx->frame_csp equals ctx->frame_csp_bottom,
+ then current block is the function block */
+ uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
+ BranchBlock *cur_block = ctx->frame_csp - depth;
+ int32 available_stack_cell =
+ (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
+
+ /* Directly return success if current block is in stack
+ * polymorphic state while stack is empty. */
+ if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
+ return true;
+
+ if (type == VALUE_TYPE_VOID)
+ return true;
+
+ if (is_32bit_type(type)) {
+ /* Check the offset stack bottom to ensure the frame offset
+ stack will not go underflow. But we don't thrown error
+ and return true here, because the error msg should be
+ given in wasm_loader_pop_frame_ref */
+ if (!check_offset_pop(ctx, 1))
+ return true;
+
+ ctx->frame_offset -= 1;
+ if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+ && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
+ ctx->dynamic_offset -= 1;
+ }
+ else {
+ if (!check_offset_pop(ctx, 2))
+ return true;
+
+ ctx->frame_offset -= 2;
+ if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+ && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
+ ctx->dynamic_offset -= 2;
+ }
+ emit_operand(ctx, *(ctx->frame_offset));
+ return true;
+}
+
+static bool
+wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
+ uint8 type_push, uint8 type_pop,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ for (int i = 0; i < pop_cnt; i++) {
+ if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf,
+ error_buf_size))
+ return false;
+ }
+ if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit,
+ operand_offset, error_buf,
+ error_buf_size))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (!(wasm_loader_push_frame_offset(ctx, type, disable_emit, operand_offset,
+ error_buf, error_buf_size)))
+ return false;
+ if (!(wasm_loader_push_frame_ref(ctx, type, error_buf, error_buf_size)))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
+ char *error_buf, uint32 error_buf_size)
+{
+ /* put wasm_loader_pop_frame_offset in front of wasm_loader_pop_frame_ref */
+ if (!wasm_loader_pop_frame_offset(ctx, type, error_buf, error_buf_size))
+ return false;
+ if (!wasm_loader_pop_frame_ref(ctx, type, error_buf, error_buf_size))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
+ uint8 type_push, uint8 type_pop,
+ bool disable_emit, int16 operand_offset,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop,
+ disable_emit, operand_offset,
+ error_buf, error_buf_size))
+ return false;
+ if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop,
+ error_buf, error_buf_size))
+ return false;
+
+ return true;
+}
+
+static bool
+wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
+ int16 *offset, char *error_buf,
+ uint32 error_buf_size)
+{
+ int8 bytes_to_increase;
+ int16 operand_offset = 0;
+ Const *c;
+
+ /* Search existing constant */
+ for (c = (Const *)ctx->const_buf;
+ (uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) {
+ if ((type == c->value_type)
+ && ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64)
+ || (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32)
+#if WASM_ENABLE_REF_TYPES != 0
+ || (type == VALUE_TYPE_FUNCREF
+ && *(int32 *)value == c->value.i32)
+ || (type == VALUE_TYPE_EXTERNREF
+ && *(int32 *)value == c->value.i32)
+#endif
+ || (type == VALUE_TYPE_F64
+ && (0 == memcmp(value, &(c->value.f64), sizeof(float64))))
+ || (type == VALUE_TYPE_F32
+ && (0
+ == memcmp(value, &(c->value.f32), sizeof(float32)))))) {
+ operand_offset = c->slot_index;
+ break;
+ }
+ if (c->value_type == VALUE_TYPE_I64 || c->value_type == VALUE_TYPE_F64)
+ operand_offset += 2;
+ else
+ operand_offset += 1;
+ }
+
+ if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) {
+ /* New constant, append to the const buffer */
+ if ((type == VALUE_TYPE_F64) || (type == VALUE_TYPE_I64)) {
+ bytes_to_increase = 2;
+ }
+ else {
+ bytes_to_increase = 1;
+ }
+
+ /* The max cell num of const buffer is 32768 since the valid index range
+ * is -32768 ~ -1. Return an invalid index 0 to indicate the buffer is
+ * full */
+ if (ctx->const_cell_num > INT16_MAX - bytes_to_increase + 1) {
+ *offset = 0;
+ return true;
+ }
+
+ if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) {
+ MEM_REALLOC(ctx->const_buf, ctx->const_buf_size,
+ ctx->const_buf_size + 4 * sizeof(Const));
+ ctx->const_buf_size += 4 * sizeof(Const);
+ c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const));
+ }
+ c->value_type = type;
+ switch (type) {
+ case VALUE_TYPE_F64:
+ bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value,
+ sizeof(float64));
+ ctx->const_cell_num += 2;
+ /* The const buf will be reversed, we use the second cell */
+ /* of the i64/f64 const so the finnal offset is corrent */
+ operand_offset++;
+ break;
+ case VALUE_TYPE_I64:
+ c->value.i64 = *(int64 *)value;
+ ctx->const_cell_num += 2;
+ operand_offset++;
+ break;
+ case VALUE_TYPE_F32:
+ bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value,
+ sizeof(float32));
+ ctx->const_cell_num++;
+ break;
+ case VALUE_TYPE_I32:
+ c->value.i32 = *(int32 *)value;
+ ctx->const_cell_num++;
+ break;
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_EXTERNREF:
+ case VALUE_TYPE_FUNCREF:
+ c->value.i32 = *(int32 *)value;
+ ctx->const_cell_num++;
+ break;
+#endif
+ default:
+ break;
+ }
+ c->slot_index = operand_offset;
+ ctx->num_const++;
+ LOG_OP("#### new const [%d]: %ld\n", ctx->num_const,
+ (int64)c->value.i64);
+ }
+ /* use negetive index for const */
+ operand_offset = -(operand_offset + 1);
+ *offset = operand_offset;
+ return true;
+fail:
+ return false;
+}
+
+/*
+ PUSH(POP)_XXX = push(pop) frame_ref + push(pop) frame_offset
+ -- Mostly used for the binary / compare operation
+ PUSH(POP)_OFFSET_TYPE only push(pop) the frame_offset stack
+ -- Mostly used in block / control instructions
+
+ The POP will always emit the offset on the top of the frame_offset stack
+ PUSH can be used in two ways:
+ 1. directly PUSH:
+ PUSH_XXX();
+ will allocate a dynamic space and emit
+ 2. silent PUSH:
+ operand_offset = xxx; disable_emit = true;
+ PUSH_XXX();
+ only push the frame_offset stack, no emit
+*/
+#define PUSH_I32() \
+ do { \
+ if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \
+ disable_emit, operand_offset, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_F32() \
+ do { \
+ if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \
+ disable_emit, operand_offset, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_I64() \
+ do { \
+ if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \
+ disable_emit, operand_offset, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_F64() \
+ do { \
+ if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \
+ disable_emit, operand_offset, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_FUNCREF() \
+ do { \
+ if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_FUNCREF, \
+ disable_emit, operand_offset, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define POP_I32() \
+ do { \
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define POP_F32() \
+ do { \
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define POP_I64() \
+ do { \
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define POP_F64() \
+ do { \
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \
+ error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_OFFSET_TYPE(type) \
+ do { \
+ if (!(wasm_loader_push_frame_offset(loader_ctx, type, disable_emit, \
+ operand_offset, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_OFFSET_TYPE(type) \
+ do { \
+ if (!(wasm_loader_pop_frame_offset(loader_ctx, type, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref_offset( \
+ loader_ctx, 1, type_push, type_pop, disable_emit, \
+ operand_offset, error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+/* type of POPs should be the same */
+#define POP2_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref_offset( \
+ loader_ctx, 2, type_push, type_pop, disable_emit, \
+ operand_offset, error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#else /* WASM_ENABLE_FAST_INTERP */
+
+#define PUSH_I32() \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I32, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_F32() \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F32, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_I64() \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I64, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_F64() \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F64, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_FUNCREF() \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_I32() \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_F32() \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F32, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_I64() \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I64, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_F64() \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F64, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_FUNCREF() \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, \
+ error_buf, error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \
+ type_pop, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+/* type of POPs should be the same */
+#define POP2_AND_PUSH(type_pop, type_push) \
+ do { \
+ if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2, type_push, \
+ type_pop, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+#endif /* WASM_ENABLE_FAST_INTERP */
+
+#if WASM_ENABLE_FAST_INTERP != 0
+
+static bool
+reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode,
+ bool disable_emit, char *error_buf, uint32 error_buf_size)
+{
+ int16 operand_offset = 0;
+ BranchBlock *block = (opcode == WASM_OP_ELSE) ? loader_ctx->frame_csp - 1
+ : loader_ctx->frame_csp;
+ BlockType *block_type = &block->block_type;
+ uint8 *return_types = NULL;
+ uint32 return_count = 0, value_count = 0, total_cel_num = 0;
+ int32 i = 0;
+ int16 dynamic_offset, dynamic_offset_org, *frame_offset = NULL,
+ *frame_offset_org = NULL;
+
+ return_count = block_type_get_result_types(block_type, &return_types);
+
+ /* If there is only one return value, use EXT_OP_COPY_STACK_TOP/_I64 instead
+ * of EXT_OP_COPY_STACK_VALUES for interpreter performance. */
+ if (return_count == 1) {
+ uint8 cell = (uint8)wasm_value_type_cell_num(return_types[0]);
+ if (cell <= 2 /* V128 isn't supported whose cell num is 4 */
+ && block->dynamic_offset != *(loader_ctx->frame_offset - cell)) {
+ /* insert op_copy before else opcode */
+ if (opcode == WASM_OP_ELSE)
+ skip_label();
+ emit_label(cell == 1 ? EXT_OP_COPY_STACK_TOP
+ : EXT_OP_COPY_STACK_TOP_I64);
+ emit_operand(loader_ctx, *(loader_ctx->frame_offset - cell));
+ emit_operand(loader_ctx, block->dynamic_offset);
+
+ if (opcode == WASM_OP_ELSE) {
+ *(loader_ctx->frame_offset - cell) = block->dynamic_offset;
+ }
+ else {
+ loader_ctx->frame_offset -= cell;
+ loader_ctx->dynamic_offset = block->dynamic_offset;
+ PUSH_OFFSET_TYPE(return_types[0]);
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ }
+ if (opcode == WASM_OP_ELSE)
+ emit_label(opcode);
+ }
+ return true;
+ }
+
+ /* Copy stack top values to block's results which are in dynamic space.
+ * The instruction format:
+ * Part a: values count
+ * Part b: all values total cell num
+ * Part c: each value's cell_num, src offset and dst offset
+ * Part d: each value's src offset and dst offset
+ * Part e: each value's dst offset
+ */
+ frame_offset = frame_offset_org = loader_ctx->frame_offset;
+ dynamic_offset = dynamic_offset_org =
+ block->dynamic_offset + wasm_get_cell_num(return_types, return_count);
+
+ /* First traversal to get the count of values needed to be copied. */
+ for (i = (int32)return_count - 1; i >= 0; i--) {
+ uint8 cells = (uint8)wasm_value_type_cell_num(return_types[i]);
+
+ frame_offset -= cells;
+ dynamic_offset -= cells;
+ if (dynamic_offset != *frame_offset) {
+ value_count++;
+ total_cel_num += cells;
+ }
+ }
+
+ if (value_count) {
+ uint32 j = 0;
+ uint8 *emit_data = NULL, *cells = NULL;
+ int16 *src_offsets = NULL;
+ uint16 *dst_offsets = NULL;
+ uint64 size =
+ (uint64)value_count
+ * (sizeof(*cells) + sizeof(*src_offsets) + sizeof(*dst_offsets));
+
+ /* Allocate memory for the emit data */
+ if (!(emit_data = loader_malloc(size, error_buf, error_buf_size)))
+ return false;
+
+ cells = emit_data;
+ src_offsets = (int16 *)(cells + value_count);
+ dst_offsets = (uint16 *)(src_offsets + value_count);
+
+ /* insert op_copy before else opcode */
+ if (opcode == WASM_OP_ELSE)
+ skip_label();
+ emit_label(EXT_OP_COPY_STACK_VALUES);
+ /* Part a) */
+ emit_uint32(loader_ctx, value_count);
+ /* Part b) */
+ emit_uint32(loader_ctx, total_cel_num);
+
+ /* Second traversal to get each value's cell num, src offset and dst
+ * offset. */
+ frame_offset = frame_offset_org;
+ dynamic_offset = dynamic_offset_org;
+ for (i = (int32)return_count - 1, j = 0; i >= 0; i--) {
+ uint8 cell = (uint8)wasm_value_type_cell_num(return_types[i]);
+ frame_offset -= cell;
+ dynamic_offset -= cell;
+ if (dynamic_offset != *frame_offset) {
+ /* cell num */
+ cells[j] = cell;
+ /* src offset */
+ src_offsets[j] = *frame_offset;
+ /* dst offset */
+ dst_offsets[j] = dynamic_offset;
+ j++;
+ }
+ if (opcode == WASM_OP_ELSE) {
+ *frame_offset = dynamic_offset;
+ }
+ else {
+ loader_ctx->frame_offset = frame_offset;
+ loader_ctx->dynamic_offset = dynamic_offset;
+ PUSH_OFFSET_TYPE(return_types[i]);
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ loader_ctx->frame_offset = frame_offset_org;
+ loader_ctx->dynamic_offset = dynamic_offset_org;
+ }
+ }
+
+ bh_assert(j == value_count);
+
+ /* Emit the cells, src_offsets and dst_offsets */
+ for (j = 0; j < value_count; j++)
+ emit_byte(loader_ctx, cells[j]);
+ for (j = 0; j < value_count; j++)
+ emit_operand(loader_ctx, src_offsets[j]);
+ for (j = 0; j < value_count; j++)
+ emit_operand(loader_ctx, dst_offsets[j]);
+
+ if (opcode == WASM_OP_ELSE)
+ emit_label(opcode);
+
+ wasm_runtime_free(emit_data);
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+
+#endif /* WASM_ENABLE_FAST_INTERP */
+
+#define RESERVE_BLOCK_RET() \
+ do { \
+ if (!reserve_block_ret(loader_ctx, opcode, disable_emit, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_TYPE(type) \
+ do { \
+ if (!(wasm_loader_push_frame_ref(loader_ctx, type, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define POP_TYPE(type) \
+ do { \
+ if (!(wasm_loader_pop_frame_ref(loader_ctx, type, error_buf, \
+ error_buf_size))) \
+ goto fail; \
+ } while (0)
+
+#define PUSH_CSP(label_type, block_type, _start_addr) \
+ do { \
+ if (!wasm_loader_push_frame_csp(loader_ctx, label_type, block_type, \
+ _start_addr, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define POP_CSP() \
+ do { \
+ if (!wasm_loader_pop_frame_csp(loader_ctx, error_buf, error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \
+ do { \
+ read_leb_uint32(p, p_end, local_idx); \
+ bh_assert(local_idx < param_count + local_count); \
+ local_type = local_idx < param_count \
+ ? param_types[local_idx] \
+ : local_types[local_idx - param_count]; \
+ local_offset = local_offsets[local_idx]; \
+ } while (0)
+
+#define CHECK_BR(depth) \
+ do { \
+ if (!wasm_loader_check_br(loader_ctx, depth, error_buf, \
+ error_buf_size)) \
+ goto fail; \
+ } while (0)
+
+#define CHECK_MEMORY() \
+ do { \
+ bh_assert(module->import_memory_count + module->memory_count > 0); \
+ } while (0)
+
+static bool
+wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
+ char *error_buf, uint32 error_buf_size)
+{
+ BranchBlock *target_block, *cur_block;
+ BlockType *target_block_type;
+ uint8 *types = NULL, *frame_ref;
+ uint32 arity = 0;
+ int32 i, available_stack_cell;
+ uint16 cell_num;
+
+ if (loader_ctx->csp_num < depth + 1) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown label, "
+ "unexpected end of section or function");
+ return false;
+ }
+
+ cur_block = loader_ctx->frame_csp - 1;
+ target_block = loader_ctx->frame_csp - (depth + 1);
+ target_block_type = &target_block->block_type;
+ frame_ref = loader_ctx->frame_ref;
+
+ /* Note: loop's arity is different from if and block. loop's arity is
+ * its parameter count while if and block arity is result count.
+ */
+ if (target_block->label_type == LABEL_TYPE_LOOP)
+ arity = block_type_get_param_types(target_block_type, &types);
+ else
+ arity = block_type_get_result_types(target_block_type, &types);
+
+ /* If the stack is in polymorphic state, just clear the stack
+ * and then re-push the values to make the stack top values
+ * match block type. */
+ if (cur_block->is_stack_polymorphic) {
+ for (i = (int32)arity - 1; i >= 0; i--) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(types[i]);
+#endif
+ POP_TYPE(types[i]);
+ }
+ for (i = 0; i < (int32)arity; i++) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ bool disable_emit = true;
+ int16 operand_offset = 0;
+ PUSH_OFFSET_TYPE(types[i]);
+#endif
+ PUSH_TYPE(types[i]);
+ }
+ return true;
+ }
+
+ available_stack_cell =
+ (int32)(loader_ctx->stack_cell_num - cur_block->stack_cell_num);
+
+ /* Check stack top values match target block type */
+ for (i = (int32)arity - 1; i >= 0; i--) {
+ if (!check_stack_top_values(frame_ref, available_stack_cell, types[i],
+ error_buf, error_buf_size))
+ return false;
+ cell_num = wasm_value_type_cell_num(types[i]);
+ frame_ref -= cell_num;
+ available_stack_cell -= cell_num;
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+
+static BranchBlock *
+check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint8 *p = *p_buf, *p_end = buf_end;
+ BranchBlock *frame_csp_tmp;
+ uint32 depth;
+
+ read_leb_uint32(p, p_end, depth);
+ CHECK_BR(depth);
+ frame_csp_tmp = loader_ctx->frame_csp - depth - 1;
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_br_info(frame_csp_tmp);
+#endif
+
+ *p_buf = p;
+ return frame_csp_tmp;
+fail:
+ return NULL;
+}
+
+static bool
+check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block,
+ char *error_buf, uint32 error_buf_size)
+{
+ BlockType *block_type = &block->block_type;
+ uint8 *return_types = NULL;
+ uint32 return_count = 0;
+ int32 available_stack_cell, return_cell_num, i;
+ uint8 *frame_ref = NULL;
+
+ available_stack_cell =
+ (int32)(loader_ctx->stack_cell_num - block->stack_cell_num);
+
+ return_count = block_type_get_result_types(block_type, &return_types);
+ return_cell_num =
+ return_count > 0 ? wasm_get_cell_num(return_types, return_count) : 0;
+
+ /* If the stack is in polymorphic state, just clear the stack
+ * and then re-push the values to make the stack top values
+ * match block type. */
+ if (block->is_stack_polymorphic) {
+ for (i = (int32)return_count - 1; i >= 0; i--) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(return_types[i]);
+#endif
+ POP_TYPE(return_types[i]);
+ }
+
+ /* Check stack is empty */
+ bh_assert(loader_ctx->stack_cell_num == block->stack_cell_num);
+
+ for (i = 0; i < (int32)return_count; i++) {
+#if WASM_ENABLE_FAST_INTERP != 0
+ bool disable_emit = true;
+ int16 operand_offset = 0;
+ PUSH_OFFSET_TYPE(return_types[i]);
+#endif
+ PUSH_TYPE(return_types[i]);
+ }
+ return true;
+ }
+
+ /* Check stack cell num equals return cell num */
+ bh_assert(available_stack_cell == return_cell_num);
+
+ /* Check stack values match return types */
+ frame_ref = loader_ctx->frame_ref;
+ for (i = (int32)return_count - 1; i >= 0; i--) {
+ if (!check_stack_top_values(frame_ref, available_stack_cell,
+ return_types[i], error_buf, error_buf_size))
+ return false;
+ frame_ref -= wasm_value_type_cell_num(return_types[i]);
+ available_stack_cell -= wasm_value_type_cell_num(return_types[i]);
+ }
+
+ (void)return_cell_num;
+ return true;
+
+fail:
+ return false;
+}
+
+#if WASM_ENABLE_FAST_INTERP != 0
+/* Copy parameters to dynamic space.
+ * 1) POP original parameter out;
+ * 2) Push and copy original values to dynamic space.
+ * The copy instruction format:
+ * Part a: param count
+ * Part b: all param total cell num
+ * Part c: each param's cell_num, src offset and dst offset
+ * Part d: each param's src offset
+ * Part e: each param's dst offset
+ */
+static bool
+copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
+ char *error_buf, uint32 error_buf_size)
+{
+ int16 *frame_offset = NULL;
+ uint8 *cells = NULL, cell;
+ int16 *src_offsets = NULL;
+ uint8 *emit_data = NULL;
+ uint32 i;
+ BranchBlock *block = loader_ctx->frame_csp - 1;
+ BlockType *block_type = &block->block_type;
+ WASMType *wasm_type = block_type->u.type;
+ uint32 param_count = block_type->u.type->param_count;
+ int16 condition_offset = 0;
+ bool disable_emit = false;
+ int16 operand_offset = 0;
+
+ uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
+
+ /* For if block, we also need copy the condition operand offset. */
+ if (is_if_block)
+ size += sizeof(*cells) + sizeof(*src_offsets);
+
+ /* Allocate memory for the emit data */
+ if (!(emit_data = loader_malloc(size, error_buf, error_buf_size)))
+ return false;
+
+ cells = emit_data;
+ src_offsets = (int16 *)(cells + param_count);
+
+ if (is_if_block)
+ condition_offset = *loader_ctx->frame_offset;
+
+ /* POP original parameter out */
+ for (i = 0; i < param_count; i++) {
+ POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]);
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ }
+ frame_offset = loader_ctx->frame_offset;
+
+ /* Get each param's cell num and src offset */
+ for (i = 0; i < param_count; i++) {
+ cell = (uint8)wasm_value_type_cell_num(wasm_type->types[i]);
+ cells[i] = cell;
+ src_offsets[i] = *frame_offset;
+ frame_offset += cell;
+ }
+
+ /* emit copy instruction */
+ emit_label(EXT_OP_COPY_STACK_VALUES);
+ /* Part a) */
+ emit_uint32(loader_ctx, is_if_block ? param_count + 1 : param_count);
+ /* Part b) */
+ emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1
+ : wasm_type->param_cell_num);
+ /* Part c) */
+ for (i = 0; i < param_count; i++)
+ emit_byte(loader_ctx, cells[i]);
+ if (is_if_block)
+ emit_byte(loader_ctx, 1);
+
+ /* Part d) */
+ for (i = 0; i < param_count; i++)
+ emit_operand(loader_ctx, src_offsets[i]);
+ if (is_if_block)
+ emit_operand(loader_ctx, condition_offset);
+
+ /* Part e) */
+ /* Push to dynamic space. The push will emit the dst offset. */
+ for (i = 0; i < param_count; i++)
+ PUSH_OFFSET_TYPE(wasm_type->types[i]);
+ if (is_if_block)
+ PUSH_OFFSET_TYPE(VALUE_TYPE_I32);
+
+ /* Free the emit data */
+ wasm_runtime_free(emit_data);
+ return true;
+
+fail:
+ /* Free the emit data */
+ wasm_runtime_free(emit_data);
+ return false;
+}
+#endif
+
+/* reset the stack to the state of before entering the last block */
+#if WASM_ENABLE_FAST_INTERP != 0
+#define RESET_STACK() \
+ do { \
+ loader_ctx->stack_cell_num = \
+ (loader_ctx->frame_csp - 1)->stack_cell_num; \
+ loader_ctx->frame_ref = \
+ loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \
+ loader_ctx->frame_offset = \
+ loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; \
+ } while (0)
+#else
+#define RESET_STACK() \
+ do { \
+ loader_ctx->stack_cell_num = \
+ (loader_ctx->frame_csp - 1)->stack_cell_num; \
+ loader_ctx->frame_ref = \
+ loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \
+ } while (0)
+#endif
+
+/* set current block's stack polymorphic state */
+#define SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(flag) \
+ do { \
+ BranchBlock *_cur_block = loader_ctx->frame_csp - 1; \
+ _cur_block->is_stack_polymorphic = flag; \
+ } while (0)
+
+#define BLOCK_HAS_PARAM(block_type) \
+ (!block_type.is_value_type && block_type.u.type->param_count > 0)
+
+#define PRESERVE_LOCAL_FOR_BLOCK() \
+ do { \
+ if (!(preserve_local_for_block(loader_ctx, opcode, error_buf, \
+ error_buf_size))) { \
+ goto fail; \
+ } \
+ } while (0)
+
+static bool
+wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
+ uint32 cur_func_idx, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org;
+ uint32 param_count, local_count, global_count;
+ uint8 *param_types, *local_types, local_type, global_type;
+ BlockType func_block_type;
+ uint16 *local_offsets, local_offset;
+ uint32 count, local_idx, global_idx, u32, align, mem_offset, i;
+ int32 i32, i32_const = 0;
+ int64 i64_const;
+ uint8 opcode, u8;
+ bool return_value = false;
+ WASMLoaderContext *loader_ctx;
+ BranchBlock *frame_csp_tmp;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ uint32 segment_index;
+#endif
+#if WASM_ENABLE_FAST_INTERP != 0
+ uint8 *func_const_end, *func_const = NULL;
+ int16 operand_offset = 0;
+ uint8 last_op = 0;
+ bool disable_emit, preserve_local = false;
+ float32 f32_const;
+ float64 f64_const;
+
+ LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n",
+ func->param_cell_num, func->local_cell_num, func->ret_cell_num);
+#endif
+
+ global_count = module->import_global_count + module->global_count;
+
+ param_count = func->func_type->param_count;
+ param_types = func->func_type->types;
+
+ func_block_type.is_value_type = false;
+ func_block_type.u.type = func->func_type;
+
+ local_count = func->local_count;
+ local_types = func->local_types;
+ local_offsets = func->local_offsets;
+
+ if (!(loader_ctx = wasm_loader_ctx_init(func, error_buf, error_buf_size))) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* For the first traverse, the initial value of preserved_local_offset has
+ * not been determined, we use the INT16_MAX to represent that a slot has
+ * been copied to preserve space. For second traverse, this field will be
+ * set to the appropriate value in wasm_loader_ctx_reinit.
+ * This is for Issue #1230,
+ * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1230, the
+ * drop opcodes need to know which slots are preserved, so those slots will
+ * not be treated as dynamically allocated slots */
+ loader_ctx->preserved_local_offset = INT16_MAX;
+
+re_scan:
+ if (loader_ctx->code_compiled_size > 0) {
+ if (!wasm_loader_ctx_reinit(loader_ctx)) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ goto fail;
+ }
+ p = func->code;
+ func->code_compiled = loader_ctx->p_code_compiled;
+ func->code_compiled_size = loader_ctx->code_compiled_size;
+ }
+#endif
+
+ PUSH_CSP(LABEL_TYPE_FUNCTION, func_block_type, p);
+
+ while (p < p_end) {
+ opcode = *p++;
+#if WASM_ENABLE_FAST_INTERP != 0
+ p_org = p;
+ disable_emit = false;
+ emit_label(opcode);
+#endif
+
+ switch (opcode) {
+ case WASM_OP_UNREACHABLE:
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ break;
+
+ case WASM_OP_NOP:
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+#endif
+ break;
+
+ case WASM_OP_IF:
+#if WASM_ENABLE_FAST_INTERP != 0
+ PRESERVE_LOCAL_FOR_BLOCK();
+#endif
+ POP_I32();
+ goto handle_op_block_and_loop;
+ case WASM_OP_BLOCK:
+ case WASM_OP_LOOP:
+#if WASM_ENABLE_FAST_INTERP != 0
+ PRESERVE_LOCAL_FOR_BLOCK();
+#endif
+ handle_op_block_and_loop:
+ {
+ uint8 value_type;
+ BlockType block_type;
+
+ p_org = p - 1;
+ value_type = read_uint8(p);
+ if (is_byte_a_type(value_type)) {
+ /* If the first byte is one of these special values:
+ * 0x40/0x7F/0x7E/0x7D/0x7C, take it as the type of
+ * the single return value. */
+ block_type.is_value_type = true;
+ block_type.u.value_type = value_type;
+ }
+ else {
+ uint32 type_index;
+ /* Resolve the leb128 encoded type index as block type */
+ p--;
+ read_leb_uint32(p, p_end, type_index);
+ bh_assert(type_index < module->type_count);
+ block_type.is_value_type = false;
+ block_type.u.type = module->types[type_index];
+#if WASM_ENABLE_FAST_INTERP == 0
+ /* If block use type index as block type, change the opcode
+ * to new extended opcode so that interpreter can resolve
+ * the block quickly.
+ */
+ *p_org = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK);
+#endif
+ }
+
+ /* Pop block parameters from stack */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ WASMType *wasm_type = block_type.u.type;
+ for (i = 0; i < block_type.u.type->param_count; i++)
+ POP_TYPE(
+ wasm_type->types[wasm_type->param_count - i - 1]);
+ }
+
+ PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK),
+ block_type, p);
+
+ /* Pass parameters to block */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ for (i = 0; i < block_type.u.type->param_count; i++)
+ PUSH_TYPE(block_type.u.type->types[i]);
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (opcode == WASM_OP_BLOCK) {
+ skip_label();
+ }
+ else if (opcode == WASM_OP_LOOP) {
+ skip_label();
+ if (BLOCK_HAS_PARAM(block_type)) {
+ /* Make sure params are in dynamic space */
+ if (!copy_params_to_dynamic_space(
+ loader_ctx, false, error_buf, error_buf_size))
+ goto fail;
+ }
+ (loader_ctx->frame_csp - 1)->code_compiled =
+ loader_ctx->p_code_compiled;
+ }
+ else if (opcode == WASM_OP_IF) {
+ /* If block has parameters, we should make sure they are in
+ * dynamic space. Otherwise, when else branch is missing,
+ * the later opcode may consume incorrect operand offset.
+ * Spec case:
+ * (func (export "params-id") (param i32) (result i32)
+ * (i32.const 1)
+ * (i32.const 2)
+ * (if (param i32 i32) (result i32 i32) (local.get 0)
+ * (then)) (i32.add)
+ * )
+ *
+ * So we should emit a copy instruction before the if.
+ *
+ * And we also need to save the parameter offsets and
+ * recover them before entering else branch.
+ *
+ */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ BranchBlock *block = loader_ctx->frame_csp - 1;
+ uint64 size;
+
+ /* skip the if condition operand offset */
+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+ /* skip the if label */
+ skip_label();
+ /* Emit a copy instruction */
+ if (!copy_params_to_dynamic_space(
+ loader_ctx, true, error_buf, error_buf_size))
+ goto fail;
+
+ /* Emit the if instruction */
+ emit_label(opcode);
+ /* Emit the new condition operand offset */
+ POP_OFFSET_TYPE(VALUE_TYPE_I32);
+
+ /* Save top param_count values of frame_offset stack, so
+ * that we can recover it before executing else branch
+ */
+ size = sizeof(int16)
+ * (uint64)block_type.u.type->param_cell_num;
+ if (!(block->param_frame_offsets = loader_malloc(
+ size, error_buf, error_buf_size)))
+ goto fail;
+ bh_memcpy_s(block->param_frame_offsets, (uint32)size,
+ loader_ctx->frame_offset
+ - size / sizeof(int16),
+ (uint32)size);
+ }
+
+ emit_empty_label_addr_and_frame_ip(PATCH_ELSE);
+ emit_empty_label_addr_and_frame_ip(PATCH_END);
+ }
+#endif
+ break;
+ }
+
+ case WASM_OP_ELSE:
+ {
+ BlockType block_type = (loader_ctx->frame_csp - 1)->block_type;
+ bh_assert(loader_ctx->csp_num >= 2
+ && (loader_ctx->frame_csp - 1)->label_type
+ == LABEL_TYPE_IF);
+
+ /* check whether if branch's stack matches its result type */
+ if (!check_block_stack(loader_ctx, loader_ctx->frame_csp - 1,
+ error_buf, error_buf_size))
+ goto fail;
+
+ (loader_ctx->frame_csp - 1)->else_addr = p - 1;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* if the result of if branch is in local or const area, add a
+ * copy op */
+ RESERVE_BLOCK_RET();
+
+ emit_empty_label_addr_and_frame_ip(PATCH_END);
+ apply_label_patch(loader_ctx, 1, PATCH_ELSE);
+#endif
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(false);
+
+ /* Pass parameters to if-false branch */
+ if (BLOCK_HAS_PARAM(block_type)) {
+ for (i = 0; i < block_type.u.type->param_count; i++)
+ PUSH_TYPE(block_type.u.type->types[i]);
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Recover top param_count values of frame_offset stack */
+ if (BLOCK_HAS_PARAM((block_type))) {
+ uint32 size;
+ BranchBlock *block = loader_ctx->frame_csp - 1;
+ size = sizeof(int16) * block_type.u.type->param_cell_num;
+ bh_memcpy_s(loader_ctx->frame_offset, size,
+ block->param_frame_offsets, size);
+ loader_ctx->frame_offset += (size / sizeof(int16));
+ }
+#endif
+
+ break;
+ }
+
+ case WASM_OP_END:
+ {
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+
+ /* check whether block stack matches its result type */
+ if (!check_block_stack(loader_ctx, cur_block, error_buf,
+ error_buf_size))
+ goto fail;
+
+ /* if no else branch, and return types do not match param types,
+ * fail */
+ if (cur_block->label_type == LABEL_TYPE_IF
+ && !cur_block->else_addr) {
+ uint32 block_param_count = 0, block_ret_count = 0;
+ uint8 *block_param_types = NULL, *block_ret_types = NULL;
+ BlockType *cur_block_type = &cur_block->block_type;
+ if (cur_block_type->is_value_type) {
+ if (cur_block_type->u.value_type != VALUE_TYPE_VOID) {
+ block_ret_count = 1;
+ block_ret_types = &cur_block_type->u.value_type;
+ }
+ }
+ else {
+ block_param_count = cur_block_type->u.type->param_count;
+ block_ret_count = cur_block_type->u.type->result_count;
+ block_param_types = cur_block_type->u.type->types;
+ block_ret_types =
+ cur_block_type->u.type->types + block_param_count;
+ }
+ bh_assert(block_param_count == block_ret_count
+ && (!block_param_count
+ || !memcmp(block_param_types, block_ret_types,
+ block_param_count)));
+ (void)block_ret_types;
+ (void)block_ret_count;
+ (void)block_param_types;
+ }
+
+ POP_CSP();
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ /* copy the result to the block return address */
+ RESERVE_BLOCK_RET();
+
+ apply_label_patch(loader_ctx, 0, PATCH_END);
+ free_label_patch_list(loader_ctx->frame_csp);
+ if (loader_ctx->frame_csp->label_type == LABEL_TYPE_FUNCTION) {
+ int32 idx;
+ uint8 ret_type;
+
+ emit_label(WASM_OP_RETURN);
+ for (idx = (int32)func->func_type->result_count - 1;
+ idx >= 0; idx--) {
+ ret_type = *(func->func_type->types
+ + func->func_type->param_count + idx);
+ POP_OFFSET_TYPE(ret_type);
+ }
+ }
+#endif
+ if (loader_ctx->csp_num > 0) {
+ loader_ctx->frame_csp->end_addr = p - 1;
+ }
+ else {
+ /* end of function block, function will return */
+ bh_assert(p == p_end);
+ }
+
+ break;
+ }
+
+ case WASM_OP_BR:
+ {
+ if (!(frame_csp_tmp = check_branch_block(
+ loader_ctx, &p, p_end, error_buf, error_buf_size)))
+ goto fail;
+
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+ break;
+ }
+
+ case WASM_OP_BR_IF:
+ {
+ POP_I32();
+
+ if (!(frame_csp_tmp = check_branch_block(
+ loader_ctx, &p, p_end, error_buf, error_buf_size)))
+ goto fail;
+
+ break;
+ }
+
+ case WASM_OP_BR_TABLE:
+ {
+ uint8 *ret_types = NULL;
+ uint32 ret_count = 0;
+#if WASM_ENABLE_FAST_INTERP == 0
+ uint8 *p_depth_begin, *p_depth;
+ uint32 depth, j;
+ BrTableCache *br_table_cache = NULL;
+
+ p_org = p - 1;
+#endif
+
+ read_leb_uint32(p, p_end, count);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, count);
+#endif
+ POP_I32();
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ p_depth_begin = p_depth = p;
+#endif
+ for (i = 0; i <= count; i++) {
+ if (!(frame_csp_tmp =
+ check_branch_block(loader_ctx, &p, p_end,
+ error_buf, error_buf_size)))
+ goto fail;
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ depth = (uint32)(loader_ctx->frame_csp - 1 - frame_csp_tmp);
+ if (br_table_cache) {
+ br_table_cache->br_depths[i] = depth;
+ }
+ else {
+ if (depth > 255) {
+ /* The depth cannot be stored in one byte,
+ create br_table cache to store each depth */
+ if (!(br_table_cache = loader_malloc(
+ offsetof(BrTableCache, br_depths)
+ + sizeof(uint32)
+ * (uint64)(count + 1),
+ error_buf, error_buf_size))) {
+ goto fail;
+ }
+ *p_org = EXT_OP_BR_TABLE_CACHE;
+ br_table_cache->br_table_op_addr = p_org;
+ br_table_cache->br_count = count;
+ /* Copy previous depths which are one byte */
+ for (j = 0; j < i; j++) {
+ br_table_cache->br_depths[j] = p_depth_begin[j];
+ }
+ br_table_cache->br_depths[i] = depth;
+ bh_list_insert(module->br_table_cache_list,
+ br_table_cache);
+ }
+ else {
+ /* The depth can be stored in one byte, use the
+ byte of the leb to store it */
+ *p_depth++ = (uint8)depth;
+ }
+ }
+#endif
+ }
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ /* Set the tailing bytes to nop */
+ if (br_table_cache)
+ p_depth = p_depth_begin;
+ while (p_depth < p)
+ *p_depth++ = WASM_OP_NOP;
+#endif
+
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+
+ (void)ret_count;
+ (void)ret_types;
+ break;
+ }
+
+ case WASM_OP_RETURN:
+ {
+ int32 idx;
+ uint8 ret_type;
+ for (idx = (int32)func->func_type->result_count - 1; idx >= 0;
+ idx--) {
+ ret_type = *(func->func_type->types
+ + func->func_type->param_count + idx);
+ POP_TYPE(ret_type);
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* emit the offset after return opcode */
+ POP_OFFSET_TYPE(ret_type);
+#endif
+ }
+
+ RESET_STACK();
+ SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
+
+ break;
+ }
+
+ case WASM_OP_CALL:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL:
+#endif
+ {
+ WASMType *func_type;
+ uint32 func_idx;
+ int32 idx;
+
+ read_leb_uint32(p, p_end, func_idx);
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* we need to emit func_idx before arguments */
+ emit_uint32(loader_ctx, func_idx);
+#endif
+
+ bh_assert(func_idx < module->import_function_count
+ + module->function_count);
+
+ if (func_idx < module->import_function_count)
+ func_type =
+ module->import_functions[func_idx].u.function.func_type;
+ else
+ func_type = module
+ ->functions[func_idx
+ - module->import_function_count]
+ ->func_type;
+
+ if (func_type->param_count > 0) {
+ for (idx = (int32)(func_type->param_count - 1); idx >= 0;
+ idx--) {
+ POP_TYPE(func_type->types[idx]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(func_type->types[idx]);
+#endif
+ }
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ if (opcode == WASM_OP_CALL) {
+#endif
+ for (i = 0; i < func_type->result_count; i++) {
+ PUSH_TYPE(func_type->types[func_type->param_count + i]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Here we emit each return value's dynamic_offset. But
+ * in fact these offsets are continuous, so interpreter
+ * only need to get the first return value's offset.
+ */
+ PUSH_OFFSET_TYPE(
+ func_type->types[func_type->param_count + i]);
+#endif
+ }
+#if WASM_ENABLE_TAIL_CALL != 0
+ }
+ else {
+ bh_assert(func_type->result_count
+ == func->func_type->result_count);
+ for (i = 0; i < func_type->result_count; i++) {
+ bh_assert(
+ func_type->types[func_type->param_count + i]
+ == func->func_type
+ ->types[func->func_type->param_count + i]);
+ }
+ }
+#endif
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_func_call = true;
+#endif
+ break;
+ }
+
+ case WASM_OP_CALL_INDIRECT:
+#if WASM_ENABLE_TAIL_CALL != 0
+ case WASM_OP_RETURN_CALL_INDIRECT:
+#endif
+ {
+ int32 idx;
+ WASMType *func_type;
+ uint32 type_idx, table_idx;
+
+ bh_assert(module->import_table_count + module->table_count > 0);
+
+ read_leb_uint32(p, p_end, type_idx);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ read_leb_uint32(p, p_end, table_idx);
+#else
+ CHECK_BUF(p, p_end, 1);
+ table_idx = read_uint8(p);
+#endif
+ if (!check_table_index(module, table_idx, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* we need to emit before arguments */
+ emit_uint32(loader_ctx, type_idx);
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ /* skip elem idx */
+ POP_I32();
+
+ bh_assert(type_idx < module->type_count);
+
+ func_type = module->types[type_idx];
+
+ if (func_type->param_count > 0) {
+ for (idx = (int32)(func_type->param_count - 1); idx >= 0;
+ idx--) {
+ POP_TYPE(func_type->types[idx]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(func_type->types[idx]);
+#endif
+ }
+ }
+
+#if WASM_ENABLE_TAIL_CALL != 0
+ if (opcode == WASM_OP_CALL) {
+#endif
+ for (i = 0; i < func_type->result_count; i++) {
+ PUSH_TYPE(func_type->types[func_type->param_count + i]);
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(
+ func_type->types[func_type->param_count + i]);
+#endif
+ }
+#if WASM_ENABLE_TAIL_CALL != 0
+ }
+ else {
+ bh_assert(func_type->result_count
+ == func->func_type->result_count);
+ for (i = 0; i < func_type->result_count; i++) {
+ bh_assert(
+ func_type->types[func_type->param_count + i]
+ == func->func_type
+ ->types[func->func_type->param_count + i]);
+ }
+ }
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_func_call = true;
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_call_indirect = true;
+#endif
+ break;
+ }
+
+ case WASM_OP_DROP:
+ {
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+ int32 available_stack_cell =
+ (int32)(loader_ctx->stack_cell_num
+ - cur_block->stack_cell_num);
+
+ bh_assert(!(available_stack_cell <= 0
+ && !cur_block->is_stack_polymorphic));
+
+ if (available_stack_cell > 0) {
+ if (is_32bit_type(*(loader_ctx->frame_ref - 1))) {
+ loader_ctx->frame_ref--;
+ loader_ctx->stack_cell_num--;
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ loader_ctx->frame_offset--;
+ if ((*(loader_ctx->frame_offset)
+ > loader_ctx->start_dynamic_offset)
+ && (*(loader_ctx->frame_offset)
+ < loader_ctx->max_dynamic_offset))
+ loader_ctx->dynamic_offset--;
+#endif
+ }
+ else if (is_64bit_type(*(loader_ctx->frame_ref - 1))) {
+ loader_ctx->frame_ref -= 2;
+ loader_ctx->stack_cell_num -= 2;
+#if WASM_ENABLE_FAST_INTERP == 0
+ *(p - 1) = WASM_OP_DROP_64;
+#endif
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ loader_ctx->frame_offset -= 2;
+ if ((*(loader_ctx->frame_offset)
+ > loader_ctx->start_dynamic_offset)
+ && (*(loader_ctx->frame_offset)
+ < loader_ctx->max_dynamic_offset))
+ loader_ctx->dynamic_offset -= 2;
+#endif
+ }
+ else {
+ bh_assert(0);
+ }
+ }
+ else {
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+#endif
+ }
+ break;
+ }
+
+ case WASM_OP_SELECT:
+ {
+ uint8 ref_type;
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+ int32 available_stack_cell;
+
+ POP_I32();
+
+ available_stack_cell = (int32)(loader_ctx->stack_cell_num
+ - cur_block->stack_cell_num);
+
+ bh_assert(!(available_stack_cell <= 0
+ && !cur_block->is_stack_polymorphic));
+
+ if (available_stack_cell > 0) {
+ switch (*(loader_ctx->frame_ref - 1)) {
+ case REF_I32:
+ case REF_F32:
+ break;
+ case REF_I64_2:
+ case REF_F64_2:
+#if WASM_ENABLE_FAST_INTERP == 0
+ *(p - 1) = WASM_OP_SELECT_64;
+#endif
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (loader_ctx->p_code_compiled) {
+ uint8 opcode_tmp = WASM_OP_SELECT_64;
+ uint8 *p_code_compiled_tmp =
+ loader_ctx->p_code_compiled - 2;
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(void **)(p_code_compiled_tmp
+ - sizeof(void *)) =
+ handle_table[opcode_tmp];
+#else
+ int32 offset =
+ (int32)((uint8 *)handle_table[opcode_tmp]
+ - (uint8 *)handle_table[0]);
+ if (!(offset >= INT16_MIN
+ && offset < INT16_MAX)) {
+ set_error_buf(error_buf, error_buf_size,
+ "pre-compiled label offset "
+ "out of range");
+ goto fail;
+ }
+ *(int16 *)(p_code_compiled_tmp
+ - sizeof(int16)) = (int16)offset;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(p_code_compiled_tmp - 1) = opcode_tmp;
+#else
+ *(p_code_compiled_tmp - 2) = opcode_tmp;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+ }
+#endif
+ break;
+ }
+
+ ref_type = *(loader_ctx->frame_ref - 1);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(ref_type);
+#endif
+ POP_TYPE(ref_type);
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(ref_type);
+#endif
+ POP_TYPE(ref_type);
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(ref_type);
+#endif
+ PUSH_TYPE(ref_type);
+ }
+ else {
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(VALUE_TYPE_ANY);
+#endif
+ PUSH_TYPE(VALUE_TYPE_ANY);
+ }
+ break;
+ }
+
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_SELECT_T:
+ {
+ uint8 vec_len, ref_type;
+
+ read_leb_uint32(p, p_end, vec_len);
+ if (!vec_len) {
+ set_error_buf(error_buf, error_buf_size,
+ "invalid result arity");
+ goto fail;
+ }
+
+ CHECK_BUF(p, p_end, 1);
+ ref_type = read_uint8(p);
+ if (!is_value_type(ref_type)) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown value type");
+ goto fail;
+ }
+
+ POP_I32();
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (loader_ctx->p_code_compiled) {
+ uint8 opcode_tmp = WASM_OP_SELECT;
+ uint8 *p_code_compiled_tmp =
+ loader_ctx->p_code_compiled - 2;
+
+ if (ref_type == VALUE_TYPE_F64
+ || ref_type == VALUE_TYPE_I64)
+ opcode_tmp = WASM_OP_SELECT_64;
+
+#if WASM_ENABLE_LABELS_AS_VALUES != 0
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(void **)(p_code_compiled_tmp - sizeof(void *)) =
+ handle_table[opcode_tmp];
+#else
+ int32 offset = (int32)((uint8 *)handle_table[opcode_tmp]
+ - (uint8 *)handle_table[0]);
+ if (!(offset >= INT16_MIN && offset < INT16_MAX)) {
+ set_error_buf(error_buf, error_buf_size,
+ "pre-compiled label offset out of range");
+ goto fail;
+ }
+ *(int16 *)(p_code_compiled_tmp - sizeof(int16)) =
+ (int16)offset;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+ *(p_code_compiled_tmp - 1) = opcode_tmp;
+#else
+ *(p_code_compiled_tmp - 2) = opcode_tmp;
+#endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */
+#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
+ }
+#endif /* WASM_ENABLE_FAST_INTERP != 0 */
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(ref_type);
+ POP_TYPE(ref_type);
+ POP_OFFSET_TYPE(ref_type);
+ POP_TYPE(ref_type);
+ PUSH_OFFSET_TYPE(ref_type);
+ PUSH_TYPE(ref_type);
+#else
+ POP2_AND_PUSH(ref_type, ref_type);
+#endif /* WASM_ENABLE_FAST_INTERP != 0 */
+
+ (void)vec_len;
+ break;
+ }
+
+ /* table.get x. tables[x]. [i32] -> [t] */
+ /* table.set x. tables[x]. [i32 t] -> [] */
+ case WASM_OP_TABLE_GET:
+ case WASM_OP_TABLE_SET:
+ {
+ uint8 decl_ref_type;
+ uint32 table_idx;
+
+ read_leb_uint32(p, p_end, table_idx);
+ if (!get_table_elem_type(module, table_idx, &decl_ref_type,
+ error_buf, error_buf_size))
+ goto fail;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ if (opcode == WASM_OP_TABLE_GET) {
+ POP_I32();
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(decl_ref_type);
+#endif
+ PUSH_TYPE(decl_ref_type);
+ }
+ else {
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(decl_ref_type);
+#endif
+ POP_TYPE(decl_ref_type);
+ POP_I32();
+ }
+ break;
+ }
+ case WASM_OP_REF_NULL:
+ {
+ uint8 ref_type;
+
+ CHECK_BUF(p, p_end, 1);
+ ref_type = read_uint8(p);
+ if (ref_type != VALUE_TYPE_FUNCREF
+ && ref_type != VALUE_TYPE_EXTERNREF) {
+ set_error_buf(error_buf, error_buf_size,
+ "unknown value type");
+ goto fail;
+ }
+#if WASM_ENABLE_FAST_INTERP != 0
+ PUSH_OFFSET_TYPE(ref_type);
+#endif
+ PUSH_TYPE(ref_type);
+ break;
+ }
+ case WASM_OP_REF_IS_NULL:
+ {
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (!wasm_loader_pop_frame_ref_offset(loader_ctx,
+ VALUE_TYPE_FUNCREF,
+ error_buf, error_buf_size)
+ && !wasm_loader_pop_frame_ref_offset(
+ loader_ctx, VALUE_TYPE_EXTERNREF, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+#else
+ if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,
+ error_buf, error_buf_size)
+ && !wasm_loader_pop_frame_ref(loader_ctx,
+ VALUE_TYPE_EXTERNREF,
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+#endif
+ PUSH_I32();
+ break;
+ }
+ case WASM_OP_REF_FUNC:
+ {
+ uint32 func_idx = 0;
+ read_leb_uint32(p, p_end, func_idx);
+
+ if (!check_function_index(module, func_idx, error_buf,
+ error_buf_size)) {
+ goto fail;
+ }
+
+ /* Refer to a forward-declared function */
+ if (func_idx >= cur_func_idx + module->import_function_count) {
+ WASMTableSeg *table_seg = module->table_segments;
+ bool func_declared = false;
+ uint32 j;
+
+ /* Check whether the function is declared in table segs */
+ for (i = 0; i < module->table_seg_count; i++, table_seg++) {
+ if (table_seg->elem_type == VALUE_TYPE_FUNCREF
+ && wasm_elem_is_declarative(table_seg->mode)) {
+ for (j = 0; j < table_seg->function_count; j++) {
+ if (table_seg->func_indexes[j] == func_idx) {
+ func_declared = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!func_declared) {
+ /* Check whether the function is exported */
+ for (i = 0; i < module->export_count; i++) {
+ if (module->exports[i].kind == EXPORT_KIND_FUNC
+ && module->exports[i].index == func_idx) {
+ func_declared = true;
+ break;
+ }
+ }
+ }
+ bh_assert(func_declared);
+ (void)func_declared;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, func_idx);
+#endif
+ PUSH_FUNCREF();
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+
+ case WASM_OP_GET_LOCAL:
+ {
+ p_org = p - 1;
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+ PUSH_TYPE(local_type);
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* Get Local is optimized out */
+ skip_label();
+ disable_emit = true;
+ operand_offset = local_offset;
+ PUSH_OFFSET_TYPE(local_type);
+#else
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
+ && (WASM_ENABLE_FAST_JIT == 0)
+ if (local_offset < 0x80) {
+ *p_org++ = EXT_OP_GET_LOCAL_FAST;
+ if (is_32bit_type(local_type))
+ *p_org++ = (uint8)local_offset;
+ else
+ *p_org++ = (uint8)(local_offset | 0x80);
+ while (p_org < p)
+ *p_org++ = WASM_OP_NOP;
+ }
+#endif
+#endif
+ break;
+ }
+
+ case WASM_OP_SET_LOCAL:
+ {
+ p_org = p - 1;
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+ POP_TYPE(local_type);
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (!(preserve_referenced_local(
+ loader_ctx, opcode, local_offset, local_type,
+ &preserve_local, error_buf, error_buf_size)))
+ goto fail;
+
+ if (local_offset < 256) {
+ skip_label();
+ if ((!preserve_local) && (LAST_OP_OUTPUT_I32())) {
+ if (loader_ctx->p_code_compiled)
+ STORE_U16(loader_ctx->p_code_compiled - 2,
+ local_offset);
+ loader_ctx->frame_offset--;
+ loader_ctx->dynamic_offset--;
+ }
+ else if ((!preserve_local) && (LAST_OP_OUTPUT_I64())) {
+ if (loader_ctx->p_code_compiled)
+ STORE_U16(loader_ctx->p_code_compiled - 2,
+ local_offset);
+ loader_ctx->frame_offset -= 2;
+ loader_ctx->dynamic_offset -= 2;
+ }
+ else {
+ if (is_32bit_type(local_type)) {
+ emit_label(EXT_OP_SET_LOCAL_FAST);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ else {
+ emit_label(EXT_OP_SET_LOCAL_FAST_I64);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ POP_OFFSET_TYPE(local_type);
+ }
+ }
+ else { /* local index larger than 255, reserve leb */
+ emit_uint32(loader_ctx, local_idx);
+ POP_OFFSET_TYPE(local_type);
+ }
+#else
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
+ && (WASM_ENABLE_FAST_JIT == 0)
+ if (local_offset < 0x80) {
+ *p_org++ = EXT_OP_SET_LOCAL_FAST;
+ if (is_32bit_type(local_type))
+ *p_org++ = (uint8)local_offset;
+ else
+ *p_org++ = (uint8)(local_offset | 0x80);
+ while (p_org < p)
+ *p_org++ = WASM_OP_NOP;
+ }
+#endif
+#endif
+ break;
+ }
+
+ case WASM_OP_TEE_LOCAL:
+ {
+ p_org = p - 1;
+ GET_LOCAL_INDEX_TYPE_AND_OFFSET();
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* If the stack is in polymorphic state, do fake pop and push on
+ offset stack to keep the depth of offset stack to be the
+ same with ref stack */
+ BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+ if (cur_block->is_stack_polymorphic) {
+ POP_OFFSET_TYPE(local_type);
+ PUSH_OFFSET_TYPE(local_type);
+ }
+#endif
+ POP_TYPE(local_type);
+ PUSH_TYPE(local_type);
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (!(preserve_referenced_local(
+ loader_ctx, opcode, local_offset, local_type,
+ &preserve_local, error_buf, error_buf_size)))
+ goto fail;
+
+ if (local_offset < 256) {
+ skip_label();
+ if (is_32bit_type(local_type)) {
+ emit_label(EXT_OP_TEE_LOCAL_FAST);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ else {
+ emit_label(EXT_OP_TEE_LOCAL_FAST_I64);
+ emit_byte(loader_ctx, (uint8)local_offset);
+ }
+ }
+ else { /* local index larger than 255, reserve leb */
+ emit_uint32(loader_ctx, local_idx);
+ }
+ emit_operand(loader_ctx,
+ *(loader_ctx->frame_offset
+ - wasm_value_type_cell_num(local_type)));
+#else
+#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
+ && (WASM_ENABLE_FAST_JIT == 0)
+ if (local_offset < 0x80) {
+ *p_org++ = EXT_OP_TEE_LOCAL_FAST;
+ if (is_32bit_type(local_type))
+ *p_org++ = (uint8)local_offset;
+ else
+ *p_org++ = (uint8)(local_offset | 0x80);
+ while (p_org < p)
+ *p_org++ = WASM_OP_NOP;
+ }
+#endif
+#endif
+ break;
+ }
+
+ case WASM_OP_GET_GLOBAL:
+ {
+ p_org = p - 1;
+ read_leb_uint32(p, p_end, global_idx);
+ bh_assert(global_idx < global_count);
+
+ global_type =
+ global_idx < module->import_global_count
+ ? module->import_globals[global_idx].u.global.type
+ : module
+ ->globals[global_idx
+ - module->import_global_count]
+ .type;
+
+ PUSH_TYPE(global_type);
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ if (global_type == VALUE_TYPE_I64
+ || global_type == VALUE_TYPE_F64) {
+ *p_org = WASM_OP_GET_GLOBAL_64;
+ }
+#else /* else of WASM_ENABLE_FAST_INTERP */
+ if (is_64bit_type(global_type)) {
+ skip_label();
+ emit_label(WASM_OP_GET_GLOBAL_64);
+ }
+ emit_uint32(loader_ctx, global_idx);
+ PUSH_OFFSET_TYPE(global_type);
+#endif /* end of WASM_ENABLE_FAST_INTERP */
+ break;
+ }
+
+ case WASM_OP_SET_GLOBAL:
+ {
+ bool is_mutable = false;
+
+ p_org = p - 1;
+ read_leb_uint32(p, p_end, global_idx);
+ bh_assert(global_idx < global_count);
+
+ is_mutable =
+ global_idx < module->import_global_count
+ ? module->import_globals[global_idx].u.global.is_mutable
+ : module
+ ->globals[global_idx
+ - module->import_global_count]
+ .is_mutable;
+ bh_assert(is_mutable);
+
+ global_type =
+ global_idx < module->import_global_count
+ ? module->import_globals[global_idx].u.global.type
+ : module
+ ->globals[global_idx
+ - module->import_global_count]
+ .type;
+
+ POP_TYPE(global_type);
+
+#if WASM_ENABLE_FAST_INTERP == 0
+ if (is_64bit_type(global_type)) {
+ *p_org = WASM_OP_SET_GLOBAL_64;
+ }
+ else if (module->aux_stack_size > 0
+ && global_idx == module->aux_stack_top_global_index) {
+ *p_org = WASM_OP_SET_GLOBAL_AUX_STACK;
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_set_global_aux_stack = true;
+#endif
+ }
+#else /* else of WASM_ENABLE_FAST_INTERP */
+ if (is_64bit_type(global_type)) {
+ skip_label();
+ emit_label(WASM_OP_SET_GLOBAL_64);
+ }
+ else if (module->aux_stack_size > 0
+ && global_idx == module->aux_stack_top_global_index) {
+ skip_label();
+ emit_label(WASM_OP_SET_GLOBAL_AUX_STACK);
+ }
+ emit_uint32(loader_ctx, global_idx);
+ POP_OFFSET_TYPE(global_type);
+#endif /* end of WASM_ENABLE_FAST_INTERP */
+
+ (void)is_mutable;
+ break;
+ }
+
+ /* load */
+ case WASM_OP_I32_LOAD:
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ case WASM_OP_I64_LOAD:
+ case WASM_OP_I64_LOAD8_S:
+ case WASM_OP_I64_LOAD8_U:
+ case WASM_OP_I64_LOAD16_S:
+ case WASM_OP_I64_LOAD16_U:
+ case WASM_OP_I64_LOAD32_S:
+ case WASM_OP_I64_LOAD32_U:
+ case WASM_OP_F32_LOAD:
+ case WASM_OP_F64_LOAD:
+ /* store */
+ case WASM_OP_I32_STORE:
+ case WASM_OP_I32_STORE8:
+ case WASM_OP_I32_STORE16:
+ case WASM_OP_I64_STORE:
+ case WASM_OP_I64_STORE8:
+ case WASM_OP_I64_STORE16:
+ case WASM_OP_I64_STORE32:
+ case WASM_OP_F32_STORE:
+ case WASM_OP_F64_STORE:
+ {
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* change F32/F64 into I32/I64 */
+ if (opcode == WASM_OP_F32_LOAD) {
+ skip_label();
+ emit_label(WASM_OP_I32_LOAD);
+ }
+ else if (opcode == WASM_OP_F64_LOAD) {
+ skip_label();
+ emit_label(WASM_OP_I64_LOAD);
+ }
+ else if (opcode == WASM_OP_F32_STORE) {
+ skip_label();
+ emit_label(WASM_OP_I32_STORE);
+ }
+ else if (opcode == WASM_OP_F64_STORE) {
+ skip_label();
+ emit_label(WASM_OP_I64_STORE);
+ }
+#endif
+ CHECK_MEMORY();
+ read_leb_uint32(p, p_end, align); /* align */
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, mem_offset);
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ switch (opcode) {
+ /* load */
+ case WASM_OP_I32_LOAD:
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_I64_LOAD:
+ case WASM_OP_I64_LOAD8_S:
+ case WASM_OP_I64_LOAD8_U:
+ case WASM_OP_I64_LOAD16_S:
+ case WASM_OP_I64_LOAD16_U:
+ case WASM_OP_I64_LOAD32_S:
+ case WASM_OP_I64_LOAD32_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
+ break;
+ case WASM_OP_F32_LOAD:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
+ break;
+ case WASM_OP_F64_LOAD:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
+ break;
+ /* store */
+ case WASM_OP_I32_STORE:
+ case WASM_OP_I32_STORE8:
+ case WASM_OP_I32_STORE16:
+ POP_I32();
+ POP_I32();
+ break;
+ case WASM_OP_I64_STORE:
+ case WASM_OP_I64_STORE8:
+ case WASM_OP_I64_STORE16:
+ case WASM_OP_I64_STORE32:
+ POP_I64();
+ POP_I32();
+ break;
+ case WASM_OP_F32_STORE:
+ POP_F32();
+ POP_I32();
+ break;
+ case WASM_OP_F64_STORE:
+ POP_F64();
+ POP_I32();
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case WASM_OP_MEMORY_SIZE:
+ CHECK_MEMORY();
+ /* reserved byte 0x00 */
+ bh_assert(*p == 0x00);
+ p++;
+ PUSH_I32();
+
+ module->possible_memory_grow = true;
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+
+ case WASM_OP_MEMORY_GROW:
+ CHECK_MEMORY();
+ /* reserved byte 0x00 */
+ bh_assert(*p == 0x00);
+ p++;
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+
+ module->possible_memory_grow = true;
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_op_memory_grow = true;
+#endif
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+
+ case WASM_OP_I32_CONST:
+ read_leb_int32(p, p_end, i32_const);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ GET_CONST_OFFSET(VALUE_TYPE_I32, i32_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_I32_CONST);
+ emit_uint32(loader_ctx, i32_const);
+ }
+#else
+ (void)i32_const;
+#endif
+ PUSH_I32();
+ break;
+
+ case WASM_OP_I64_CONST:
+ read_leb_int64(p, p_end, i64_const);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ GET_CONST_OFFSET(VALUE_TYPE_I64, i64_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_I64_CONST);
+ emit_uint64(loader_ctx, i64_const);
+ }
+#endif
+ PUSH_I64();
+ break;
+
+ case WASM_OP_F32_CONST:
+ p += sizeof(float32);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ bh_memcpy_s((uint8 *)&f32_const, sizeof(float32), p_org,
+ sizeof(float32));
+ GET_CONST_F32_OFFSET(VALUE_TYPE_F32, f32_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_F32_CONST);
+ emit_float32(loader_ctx, f32_const);
+ }
+#endif
+ PUSH_F32();
+ break;
+
+ case WASM_OP_F64_CONST:
+ p += sizeof(float64);
+#if WASM_ENABLE_FAST_INTERP != 0
+ skip_label();
+ disable_emit = true;
+ /* Some MCU may require 8-byte align */
+ bh_memcpy_s((uint8 *)&f64_const, sizeof(float64), p_org,
+ sizeof(float64));
+ GET_CONST_F64_OFFSET(VALUE_TYPE_F64, f64_const);
+
+ if (operand_offset == 0) {
+ disable_emit = false;
+ emit_label(WASM_OP_F64_CONST);
+ emit_float64(loader_ctx, f64_const);
+ }
+#endif
+ PUSH_F64();
+ break;
+
+ case WASM_OP_I32_EQZ:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_EQZ:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
+ break;
+
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I32_CLZ:
+ case WASM_OP_I32_CTZ:
+ case WASM_OP_I32_POPCNT:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ 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:
+ case WASM_OP_I32_AND:
+ case WASM_OP_I32_OR:
+ case WASM_OP_I32_XOR:
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_CLZ:
+ case WASM_OP_I64_CTZ:
+ case WASM_OP_I64_POPCNT:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
+ 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:
+ case WASM_OP_I64_AND:
+ case WASM_OP_I64_OR:
+ case WASM_OP_I64_XOR:
+ 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:
+ POP2_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
+ 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:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F32);
+ 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:
+ case WASM_OP_F32_COPYSIGN:
+ POP2_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F32);
+ 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:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F64);
+ 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:
+ case WASM_OP_F64_COPYSIGN:
+ POP2_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_I32_WRAP_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I32_TRUNC_S_F32:
+ case WASM_OP_I32_TRUNC_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I32_TRUNC_S_F64:
+ case WASM_OP_I32_TRUNC_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_EXTEND_S_I32:
+ case WASM_OP_I64_EXTEND_U_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_I64_TRUNC_S_F32:
+ case WASM_OP_I64_TRUNC_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_I64_TRUNC_S_F64:
+ case WASM_OP_I64_TRUNC_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_F32_CONVERT_S_I32:
+ case WASM_OP_F32_CONVERT_U_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F32_CONVERT_S_I64:
+ case WASM_OP_F32_CONVERT_U_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F32_DEMOTE_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F64_CONVERT_S_I32:
+ case WASM_OP_F64_CONVERT_U_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_F64_CONVERT_S_I64:
+ case WASM_OP_F64_CONVERT_U_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_F64_PROMOTE_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_I32_REINTERPRET_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_REINTERPRET_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_F32_REINTERPRET_I32:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
+ break;
+
+ case WASM_OP_F64_REINTERPRET_I64:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F64);
+ break;
+
+ case WASM_OP_I32_EXTEND8_S:
+ case WASM_OP_I32_EXTEND16_S:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+
+ case WASM_OP_I64_EXTEND8_S:
+ case WASM_OP_I64_EXTEND16_S:
+ case WASM_OP_I64_EXTEND32_S:
+ POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
+ break;
+
+ case WASM_OP_MISC_PREFIX:
+ {
+ uint32 opcode1;
+
+ read_leb_uint32(p, p_end, opcode1);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_byte(loader_ctx, ((uint8)opcode1));
+#endif
+ switch (opcode1) {
+ case WASM_OP_I32_TRUNC_SAT_S_F32:
+ case WASM_OP_I32_TRUNC_SAT_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_I32_TRUNC_SAT_S_F64:
+ case WASM_OP_I32_TRUNC_SAT_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F32:
+ case WASM_OP_I64_TRUNC_SAT_U_F32:
+ POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64);
+ break;
+ case WASM_OP_I64_TRUNC_SAT_S_F64:
+ case WASM_OP_I64_TRUNC_SAT_U_F64:
+ POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
+ break;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ case WASM_OP_MEMORY_INIT:
+ {
+ read_leb_uint32(p, p_end, segment_index);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, segment_index);
+#endif
+ bh_assert(module->import_memory_count
+ + module->memory_count
+ > 0);
+
+ bh_assert(*p == 0x00);
+ p++;
+
+ bh_assert(segment_index < module->data_seg_count);
+ bh_assert(module->data_seg_count1 > 0);
+
+ POP_I32();
+ POP_I32();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ case WASM_OP_DATA_DROP:
+ {
+ read_leb_uint32(p, p_end, segment_index);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, segment_index);
+#endif
+ bh_assert(segment_index < module->data_seg_count);
+ bh_assert(module->data_seg_count1 > 0);
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ case WASM_OP_MEMORY_COPY:
+ {
+ /* both src and dst memory index should be 0 */
+ bh_assert(*(int16 *)p == 0x0000);
+ p += 2;
+
+ bh_assert(module->import_memory_count
+ + module->memory_count
+ > 0);
+
+ POP_I32();
+ POP_I32();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+ case WASM_OP_MEMORY_FILL:
+ {
+ bh_assert(*p == 0);
+ p++;
+
+ bh_assert(module->import_memory_count
+ + module->memory_count
+ > 0);
+
+ POP_I32();
+ POP_I32();
+ POP_I32();
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ break;
+ }
+#endif /* WASM_ENABLE_BULK_MEMORY */
+#if WASM_ENABLE_REF_TYPES != 0
+ case WASM_OP_TABLE_INIT:
+ {
+ uint8 seg_ref_type, tbl_ref_type;
+ uint32 table_seg_idx, table_idx;
+
+ read_leb_uint32(p, p_end, table_seg_idx);
+ read_leb_uint32(p, p_end, table_idx);
+
+ if (!get_table_elem_type(module, table_idx,
+ &tbl_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (!get_table_seg_elem_type(module, table_seg_idx,
+ &seg_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (seg_ref_type != tbl_ref_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch");
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_seg_idx);
+ emit_uint32(loader_ctx, table_idx);
+#endif
+ POP_I32();
+ POP_I32();
+ POP_I32();
+ break;
+ }
+ case WASM_OP_ELEM_DROP:
+ {
+ uint32 table_seg_idx;
+ read_leb_uint32(p, p_end, table_seg_idx);
+ if (!get_table_seg_elem_type(module, table_seg_idx,
+ NULL, error_buf,
+ error_buf_size))
+ goto fail;
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_seg_idx);
+#endif
+ break;
+ }
+ case WASM_OP_TABLE_COPY:
+ {
+ uint8 src_ref_type, dst_ref_type;
+ uint32 src_tbl_idx, dst_tbl_idx;
+
+ read_leb_uint32(p, p_end, src_tbl_idx);
+ if (!get_table_elem_type(module, src_tbl_idx,
+ &src_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ read_leb_uint32(p, p_end, dst_tbl_idx);
+ if (!get_table_elem_type(module, dst_tbl_idx,
+ &dst_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (src_ref_type != dst_ref_type) {
+ set_error_buf(error_buf, error_buf_size,
+ "type mismatch");
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, src_tbl_idx);
+ emit_uint32(loader_ctx, dst_tbl_idx);
+#endif
+ POP_I32();
+ POP_I32();
+ POP_I32();
+ break;
+ }
+ case WASM_OP_TABLE_SIZE:
+ {
+ uint32 table_idx;
+
+ read_leb_uint32(p, p_end, table_idx);
+ /* TODO: shall we create a new function to check
+ table idx instead of using below function? */
+ if (!get_table_elem_type(module, table_idx, NULL,
+ error_buf, error_buf_size))
+ goto fail;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ PUSH_I32();
+ break;
+ }
+ case WASM_OP_TABLE_GROW:
+ case WASM_OP_TABLE_FILL:
+ {
+ uint8 decl_ref_type;
+ uint32 table_idx;
+
+ read_leb_uint32(p, p_end, table_idx);
+ if (!get_table_elem_type(module, table_idx,
+ &decl_ref_type, error_buf,
+ error_buf_size))
+ goto fail;
+
+ if (opcode1 == WASM_OP_TABLE_GROW) {
+ if (table_idx < module->import_table_count) {
+ module->import_tables[table_idx]
+ .u.table.possible_grow = true;
+ }
+ else {
+ module
+ ->tables[table_idx
+ - module->import_table_count]
+ .possible_grow = true;
+ }
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, table_idx);
+#endif
+
+ POP_I32();
+#if WASM_ENABLE_FAST_INTERP != 0
+ POP_OFFSET_TYPE(decl_ref_type);
+#endif
+ POP_TYPE(decl_ref_type);
+ if (opcode1 == WASM_OP_TABLE_GROW)
+ PUSH_I32();
+ else
+ POP_I32();
+ break;
+ }
+#endif /* WASM_ENABLE_REF_TYPES */
+ default:
+ bh_assert(0);
+ break;
+ }
+ break;
+ }
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ case WASM_OP_ATOMIC_PREFIX:
+ {
+ opcode = read_uint8(p);
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_byte(loader_ctx, opcode);
+#endif
+ if (opcode != WASM_OP_ATOMIC_FENCE) {
+ CHECK_MEMORY();
+ read_leb_uint32(p, p_end, align); /* align */
+ read_leb_uint32(p, p_end, mem_offset); /* offset */
+#if WASM_ENABLE_FAST_INTERP != 0
+ emit_uint32(loader_ctx, mem_offset);
+#endif
+ }
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+ func->has_memory_operations = true;
+#endif
+ switch (opcode) {
+ case WASM_OP_ATOMIC_NOTIFY:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_ATOMIC_WAIT32:
+ POP_I64();
+ POP_I32();
+ POP_I32();
+ PUSH_I32();
+ break;
+ case WASM_OP_ATOMIC_WAIT64:
+ POP_I64();
+ POP_I64();
+ POP_I32();
+ PUSH_I32();
+ break;
+ case WASM_OP_ATOMIC_FENCE:
+ /* reserved byte 0x00 */
+ bh_assert(*p == 0x00);
+ p++;
+ break;
+ case WASM_OP_ATOMIC_I32_LOAD:
+ case WASM_OP_ATOMIC_I32_LOAD8_U:
+ case WASM_OP_ATOMIC_I32_LOAD16_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_ATOMIC_I32_STORE:
+ case WASM_OP_ATOMIC_I32_STORE8:
+ case WASM_OP_ATOMIC_I32_STORE16:
+ POP_I32();
+ POP_I32();
+ break;
+ case WASM_OP_ATOMIC_I64_LOAD:
+ case WASM_OP_ATOMIC_I64_LOAD8_U:
+ case WASM_OP_ATOMIC_I64_LOAD16_U:
+ case WASM_OP_ATOMIC_I64_LOAD32_U:
+ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
+ break;
+ case WASM_OP_ATOMIC_I64_STORE:
+ case WASM_OP_ATOMIC_I64_STORE8:
+ case WASM_OP_ATOMIC_I64_STORE16:
+ case WASM_OP_ATOMIC_I64_STORE32:
+ POP_I64();
+ POP_I32();
+ break;
+ case WASM_OP_ATOMIC_RMW_I32_ADD:
+ case WASM_OP_ATOMIC_RMW_I32_ADD8_U:
+ case WASM_OP_ATOMIC_RMW_I32_ADD16_U:
+ case WASM_OP_ATOMIC_RMW_I32_SUB:
+ case WASM_OP_ATOMIC_RMW_I32_SUB8_U:
+ case WASM_OP_ATOMIC_RMW_I32_SUB16_U:
+ case WASM_OP_ATOMIC_RMW_I32_AND:
+ case WASM_OP_ATOMIC_RMW_I32_AND8_U:
+ case WASM_OP_ATOMIC_RMW_I32_AND16_U:
+ case WASM_OP_ATOMIC_RMW_I32_OR:
+ case WASM_OP_ATOMIC_RMW_I32_OR8_U:
+ case WASM_OP_ATOMIC_RMW_I32_OR16_U:
+ case WASM_OP_ATOMIC_RMW_I32_XOR:
+ case WASM_OP_ATOMIC_RMW_I32_XOR8_U:
+ case WASM_OP_ATOMIC_RMW_I32_XOR16_U:
+ case WASM_OP_ATOMIC_RMW_I32_XCHG:
+ case WASM_OP_ATOMIC_RMW_I32_XCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I32_XCHG16_U:
+ POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
+ break;
+ case WASM_OP_ATOMIC_RMW_I64_ADD:
+ case WASM_OP_ATOMIC_RMW_I64_ADD8_U:
+ case WASM_OP_ATOMIC_RMW_I64_ADD16_U:
+ case WASM_OP_ATOMIC_RMW_I64_ADD32_U:
+ case WASM_OP_ATOMIC_RMW_I64_SUB:
+ case WASM_OP_ATOMIC_RMW_I64_SUB8_U:
+ case WASM_OP_ATOMIC_RMW_I64_SUB16_U:
+ case WASM_OP_ATOMIC_RMW_I64_SUB32_U:
+ case WASM_OP_ATOMIC_RMW_I64_AND:
+ case WASM_OP_ATOMIC_RMW_I64_AND8_U:
+ case WASM_OP_ATOMIC_RMW_I64_AND16_U:
+ case WASM_OP_ATOMIC_RMW_I64_AND32_U:
+ case WASM_OP_ATOMIC_RMW_I64_OR:
+ case WASM_OP_ATOMIC_RMW_I64_OR8_U:
+ case WASM_OP_ATOMIC_RMW_I64_OR16_U:
+ case WASM_OP_ATOMIC_RMW_I64_OR32_U:
+ case WASM_OP_ATOMIC_RMW_I64_XOR:
+ case WASM_OP_ATOMIC_RMW_I64_XOR8_U:
+ case WASM_OP_ATOMIC_RMW_I64_XOR16_U:
+ case WASM_OP_ATOMIC_RMW_I64_XOR32_U:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG16_U:
+ case WASM_OP_ATOMIC_RMW_I64_XCHG32_U:
+ POP_I64();
+ POP_I32();
+ PUSH_I64();
+ break;
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
+ POP_I32();
+ POP_I32();
+ POP_I32();
+ PUSH_I32();
+ break;
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U:
+ case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
+ POP_I64();
+ POP_I64();
+ POP_I32();
+ PUSH_I64();
+ break;
+ default:
+ bh_assert(0);
+ break;
+ }
+ break;
+ }
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
+
+ default:
+ bh_assert(0);
+ break;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ last_op = opcode;
+#endif
+ }
+
+ if (loader_ctx->csp_num > 0) {
+ set_error_buf(error_buf, error_buf_size,
+ "function body must end with END opcode");
+ goto fail;
+ }
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ if (loader_ctx->p_code_compiled == NULL)
+ goto re_scan;
+
+ func->const_cell_num = loader_ctx->const_cell_num;
+ if (func->const_cell_num > 0) {
+ int32 j;
+
+ if (!(func->consts = func_const = loader_malloc(
+ func->const_cell_num * 4, error_buf, error_buf_size)))
+ goto fail;
+
+ func_const_end = func->consts + func->const_cell_num * 4;
+ /* reverse the const buf */
+ for (j = loader_ctx->num_const - 1; j >= 0; j--) {
+ Const *c = (Const *)(loader_ctx->const_buf + j * sizeof(Const));
+ if (c->value_type == VALUE_TYPE_F64
+ || c->value_type == VALUE_TYPE_I64) {
+ bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
+ &(c->value.f64), (uint32)sizeof(int64));
+ func_const += sizeof(int64);
+ }
+ else {
+ bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
+ &(c->value.f32), (uint32)sizeof(int32));
+ func_const += sizeof(int32);
+ }
+ }
+ }
+
+ func->max_stack_cell_num = loader_ctx->preserved_local_offset
+ - loader_ctx->start_dynamic_offset + 1;
+#else
+ func->max_stack_cell_num = loader_ctx->max_stack_cell_num;
+#endif
+ func->max_block_num = loader_ctx->max_csp_num;
+ return_value = true;
+
+fail:
+ wasm_loader_ctx_destroy(loader_ctx);
+
+ (void)u8;
+ (void)u32;
+ (void)i32;
+ (void)i64_const;
+ (void)global_count;
+ (void)local_count;
+ (void)local_offset;
+ (void)p_org;
+ (void)mem_offset;
+ (void)align;
+#if WASM_ENABLE_BULK_MEMORY != 0
+ (void)segment_index;
+#endif
+ return return_value;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_opcode.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_opcode.h
new file mode 100644
index 000000000..ce5e358a2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_opcode.h
@@ -0,0 +1,917 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_OPCODE_H
+#define _WASM_OPCODE_H
+
+#include "wasm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum WASMOpcode {
+ /* control instructions */
+ WASM_OP_UNREACHABLE = 0x00, /* unreachable */
+ WASM_OP_NOP = 0x01, /* nop */
+ WASM_OP_BLOCK = 0x02, /* block */
+ WASM_OP_LOOP = 0x03, /* loop */
+ WASM_OP_IF = 0x04, /* if */
+ WASM_OP_ELSE = 0x05, /* else */
+
+ WASM_OP_UNUSED_0x06 = 0x06,
+ WASM_OP_UNUSED_0x07 = 0x07,
+ WASM_OP_UNUSED_0x08 = 0x08,
+ WASM_OP_UNUSED_0x09 = 0x09,
+ WASM_OP_UNUSED_0x0a = 0x0a,
+
+ WASM_OP_END = 0x0b, /* end */
+ WASM_OP_BR = 0x0c, /* br */
+ WASM_OP_BR_IF = 0x0d, /* br if */
+ WASM_OP_BR_TABLE = 0x0e, /* br table */
+ WASM_OP_RETURN = 0x0f, /* return */
+ WASM_OP_CALL = 0x10, /* call */
+ WASM_OP_CALL_INDIRECT = 0x11, /* call_indirect */
+ WASM_OP_RETURN_CALL = 0x12, /* return_call */
+ WASM_OP_RETURN_CALL_INDIRECT = 0x13, /* return_call_indirect */
+
+ WASM_OP_UNUSED_0x14 = 0x14,
+ WASM_OP_UNUSED_0x15 = 0x15,
+ WASM_OP_UNUSED_0x16 = 0x16,
+ WASM_OP_UNUSED_0x17 = 0x17,
+ WASM_OP_UNUSED_0x18 = 0x18,
+ WASM_OP_UNUSED_0x19 = 0x19,
+
+ /* parametric instructions */
+ WASM_OP_DROP = 0x1a, /* drop */
+ WASM_OP_SELECT = 0x1b, /* select */
+ WASM_OP_SELECT_T = 0x1c, /* select t */
+
+ WASM_OP_GET_GLOBAL_64 = 0x1d,
+ WASM_OP_SET_GLOBAL_64 = 0x1e,
+ WASM_OP_SET_GLOBAL_AUX_STACK = 0x1f,
+
+ /* variable instructions */
+ WASM_OP_GET_LOCAL = 0x20, /* get_local */
+ WASM_OP_SET_LOCAL = 0x21, /* set_local */
+ WASM_OP_TEE_LOCAL = 0x22, /* tee_local */
+ WASM_OP_GET_GLOBAL = 0x23, /* get_global */
+ WASM_OP_SET_GLOBAL = 0x24, /* set_global */
+
+ WASM_OP_TABLE_GET = 0x25, /* table.get */
+ WASM_OP_TABLE_SET = 0x26, /* table.set */
+ WASM_OP_UNUSED_0x27 = 0x27,
+
+ /* memory instructions */
+ WASM_OP_I32_LOAD = 0x28, /* i32.load */
+ WASM_OP_I64_LOAD = 0x29, /* i64.load */
+ WASM_OP_F32_LOAD = 0x2a, /* f32.load */
+ WASM_OP_F64_LOAD = 0x2b, /* f64.load */
+ WASM_OP_I32_LOAD8_S = 0x2c, /* i32.load8_s */
+ WASM_OP_I32_LOAD8_U = 0x2d, /* i32.load8_u */
+ WASM_OP_I32_LOAD16_S = 0x2e, /* i32.load16_s */
+ WASM_OP_I32_LOAD16_U = 0x2f, /* i32.load16_u */
+ WASM_OP_I64_LOAD8_S = 0x30, /* i64.load8_s */
+ WASM_OP_I64_LOAD8_U = 0x31, /* i64.load8_u */
+ WASM_OP_I64_LOAD16_S = 0x32, /* i64.load16_s */
+ WASM_OP_I64_LOAD16_U = 0x33, /* i64.load16_u */
+ WASM_OP_I64_LOAD32_S = 0x34, /* i32.load32_s */
+ WASM_OP_I64_LOAD32_U = 0x35, /* i32.load32_u */
+ WASM_OP_I32_STORE = 0x36, /* i32.store */
+ WASM_OP_I64_STORE = 0x37, /* i64.store */
+ WASM_OP_F32_STORE = 0x38, /* f32.store */
+ WASM_OP_F64_STORE = 0x39, /* f64.store */
+ WASM_OP_I32_STORE8 = 0x3a, /* i32.store8 */
+ WASM_OP_I32_STORE16 = 0x3b, /* i32.store16 */
+ WASM_OP_I64_STORE8 = 0x3c, /* i64.store8 */
+ WASM_OP_I64_STORE16 = 0x3d, /* i64.sotre16 */
+ WASM_OP_I64_STORE32 = 0x3e, /* i64.store32 */
+ WASM_OP_MEMORY_SIZE = 0x3f, /* memory.size */
+ WASM_OP_MEMORY_GROW = 0x40, /* memory.grow */
+
+ /* constant instructions */
+ WASM_OP_I32_CONST = 0x41, /* i32.const */
+ WASM_OP_I64_CONST = 0x42, /* i64.const */
+ WASM_OP_F32_CONST = 0x43, /* f32.const */
+ WASM_OP_F64_CONST = 0x44, /* f64.const */
+
+ /* comparison instructions */
+ WASM_OP_I32_EQZ = 0x45, /* i32.eqz */
+ WASM_OP_I32_EQ = 0x46, /* i32.eq */
+ WASM_OP_I32_NE = 0x47, /* i32.ne */
+ WASM_OP_I32_LT_S = 0x48, /* i32.lt_s */
+ WASM_OP_I32_LT_U = 0x49, /* i32.lt_u */
+ WASM_OP_I32_GT_S = 0x4a, /* i32.gt_s */
+ WASM_OP_I32_GT_U = 0x4b, /* i32.gt_u */
+ WASM_OP_I32_LE_S = 0x4c, /* i32.le_s */
+ WASM_OP_I32_LE_U = 0x4d, /* i32.le_u */
+ WASM_OP_I32_GE_S = 0x4e, /* i32.ge_s */
+ WASM_OP_I32_GE_U = 0x4f, /* i32.ge_u */
+
+ WASM_OP_I64_EQZ = 0x50, /* i64.eqz */
+ WASM_OP_I64_EQ = 0x51, /* i64.eq */
+ WASM_OP_I64_NE = 0x52, /* i64.ne */
+ WASM_OP_I64_LT_S = 0x53, /* i64.lt_s */
+ WASM_OP_I64_LT_U = 0x54, /* i64.lt_u */
+ WASM_OP_I64_GT_S = 0x55, /* i64.gt_s */
+ WASM_OP_I64_GT_U = 0x56, /* i64.gt_u */
+ WASM_OP_I64_LE_S = 0x57, /* i64.le_s */
+ WASM_OP_I64_LE_U = 0x58, /* i64.le_u */
+ WASM_OP_I64_GE_S = 0x59, /* i64.ge_s */
+ WASM_OP_I64_GE_U = 0x5a, /* i64.ge_u */
+
+ WASM_OP_F32_EQ = 0x5b, /* f32.eq */
+ WASM_OP_F32_NE = 0x5c, /* f32.ne */
+ WASM_OP_F32_LT = 0x5d, /* f32.lt */
+ WASM_OP_F32_GT = 0x5e, /* f32.gt */
+ WASM_OP_F32_LE = 0x5f, /* f32.le */
+ WASM_OP_F32_GE = 0x60, /* f32.ge */
+
+ WASM_OP_F64_EQ = 0x61, /* f64.eq */
+ WASM_OP_F64_NE = 0x62, /* f64.ne */
+ WASM_OP_F64_LT = 0x63, /* f64.lt */
+ WASM_OP_F64_GT = 0x64, /* f64.gt */
+ WASM_OP_F64_LE = 0x65, /* f64.le */
+ WASM_OP_F64_GE = 0x66, /* f64.ge */
+
+ /* numeric operators */
+ WASM_OP_I32_CLZ = 0x67, /* i32.clz */
+ WASM_OP_I32_CTZ = 0x68, /* i32.ctz */
+ WASM_OP_I32_POPCNT = 0x69, /* i32.popcnt */
+ WASM_OP_I32_ADD = 0x6a, /* i32.add */
+ WASM_OP_I32_SUB = 0x6b, /* i32.sub */
+ WASM_OP_I32_MUL = 0x6c, /* i32.mul */
+ WASM_OP_I32_DIV_S = 0x6d, /* i32.div_s */
+ WASM_OP_I32_DIV_U = 0x6e, /* i32.div_u */
+ WASM_OP_I32_REM_S = 0x6f, /* i32.rem_s */
+ WASM_OP_I32_REM_U = 0x70, /* i32.rem_u */
+ WASM_OP_I32_AND = 0x71, /* i32.and */
+ WASM_OP_I32_OR = 0x72, /* i32.or */
+ WASM_OP_I32_XOR = 0x73, /* i32.xor */
+ WASM_OP_I32_SHL = 0x74, /* i32.shl */
+ WASM_OP_I32_SHR_S = 0x75, /* i32.shr_s */
+ WASM_OP_I32_SHR_U = 0x76, /* i32.shr_u */
+ WASM_OP_I32_ROTL = 0x77, /* i32.rotl */
+ WASM_OP_I32_ROTR = 0x78, /* i32.rotr */
+
+ WASM_OP_I64_CLZ = 0x79, /* i64.clz */
+ WASM_OP_I64_CTZ = 0x7a, /* i64.ctz */
+ WASM_OP_I64_POPCNT = 0x7b, /* i64.popcnt */
+ WASM_OP_I64_ADD = 0x7c, /* i64.add */
+ WASM_OP_I64_SUB = 0x7d, /* i64.sub */
+ WASM_OP_I64_MUL = 0x7e, /* i64.mul */
+ WASM_OP_I64_DIV_S = 0x7f, /* i64.div_s */
+ WASM_OP_I64_DIV_U = 0x80, /* i64.div_u */
+ WASM_OP_I64_REM_S = 0x81, /* i64.rem_s */
+ WASM_OP_I64_REM_U = 0x82, /* i64.rem_u */
+ WASM_OP_I64_AND = 0x83, /* i64.and */
+ WASM_OP_I64_OR = 0x84, /* i64.or */
+ WASM_OP_I64_XOR = 0x85, /* i64.xor */
+ WASM_OP_I64_SHL = 0x86, /* i64.shl */
+ WASM_OP_I64_SHR_S = 0x87, /* i64.shr_s */
+ WASM_OP_I64_SHR_U = 0x88, /* i64.shr_u */
+ WASM_OP_I64_ROTL = 0x89, /* i64.rotl */
+ WASM_OP_I64_ROTR = 0x8a, /* i64.rotr */
+
+ WASM_OP_F32_ABS = 0x8b, /* f32.abs */
+ WASM_OP_F32_NEG = 0x8c, /* f32.neg */
+ WASM_OP_F32_CEIL = 0x8d, /* f32.ceil */
+ WASM_OP_F32_FLOOR = 0x8e, /* f32.floor */
+ WASM_OP_F32_TRUNC = 0x8f, /* f32.trunc */
+ WASM_OP_F32_NEAREST = 0x90, /* f32.nearest */
+ WASM_OP_F32_SQRT = 0x91, /* f32.sqrt */
+ WASM_OP_F32_ADD = 0x92, /* f32.add */
+ WASM_OP_F32_SUB = 0x93, /* f32.sub */
+ WASM_OP_F32_MUL = 0x94, /* f32.mul */
+ WASM_OP_F32_DIV = 0x95, /* f32.div */
+ WASM_OP_F32_MIN = 0x96, /* f32.min */
+ WASM_OP_F32_MAX = 0x97, /* f32.max */
+ WASM_OP_F32_COPYSIGN = 0x98, /* f32.copysign */
+
+ WASM_OP_F64_ABS = 0x99, /* f64.abs */
+ WASM_OP_F64_NEG = 0x9a, /* f64.neg */
+ WASM_OP_F64_CEIL = 0x9b, /* f64.ceil */
+ WASM_OP_F64_FLOOR = 0x9c, /* f64.floor */
+ WASM_OP_F64_TRUNC = 0x9d, /* f64.trunc */
+ WASM_OP_F64_NEAREST = 0x9e, /* f64.nearest */
+ WASM_OP_F64_SQRT = 0x9f, /* f64.sqrt */
+ WASM_OP_F64_ADD = 0xa0, /* f64.add */
+ WASM_OP_F64_SUB = 0xa1, /* f64.sub */
+ WASM_OP_F64_MUL = 0xa2, /* f64.mul */
+ WASM_OP_F64_DIV = 0xa3, /* f64.div */
+ WASM_OP_F64_MIN = 0xa4, /* f64.min */
+ WASM_OP_F64_MAX = 0xa5, /* f64.max */
+ WASM_OP_F64_COPYSIGN = 0xa6, /* f64.copysign */
+
+ /* conversions */
+ WASM_OP_I32_WRAP_I64 = 0xa7, /* i32.wrap/i64 */
+ WASM_OP_I32_TRUNC_S_F32 = 0xa8, /* i32.trunc_s/f32 */
+ WASM_OP_I32_TRUNC_U_F32 = 0xa9, /* i32.trunc_u/f32 */
+ WASM_OP_I32_TRUNC_S_F64 = 0xaa, /* i32.trunc_s/f64 */
+ WASM_OP_I32_TRUNC_U_F64 = 0xab, /* i32.trunc_u/f64 */
+
+ WASM_OP_I64_EXTEND_S_I32 = 0xac, /* i64.extend_s/i32 */
+ WASM_OP_I64_EXTEND_U_I32 = 0xad, /* i64.extend_u/i32 */
+ WASM_OP_I64_TRUNC_S_F32 = 0xae, /* i64.trunc_s/f32 */
+ WASM_OP_I64_TRUNC_U_F32 = 0xaf, /* i64.trunc_u/f32 */
+ WASM_OP_I64_TRUNC_S_F64 = 0xb0, /* i64.trunc_s/f64 */
+ WASM_OP_I64_TRUNC_U_F64 = 0xb1, /* i64.trunc_u/f64 */
+
+ WASM_OP_F32_CONVERT_S_I32 = 0xb2, /* f32.convert_s/i32 */
+ WASM_OP_F32_CONVERT_U_I32 = 0xb3, /* f32.convert_u/i32 */
+ WASM_OP_F32_CONVERT_S_I64 = 0xb4, /* f32.convert_s/i64 */
+ WASM_OP_F32_CONVERT_U_I64 = 0xb5, /* f32.convert_u/i64 */
+ WASM_OP_F32_DEMOTE_F64 = 0xb6, /* f32.demote/f64 */
+
+ WASM_OP_F64_CONVERT_S_I32 = 0xb7, /* f64.convert_s/i32 */
+ WASM_OP_F64_CONVERT_U_I32 = 0xb8, /* f64.convert_u/i32 */
+ WASM_OP_F64_CONVERT_S_I64 = 0xb9, /* f64.convert_s/i64 */
+ WASM_OP_F64_CONVERT_U_I64 = 0xba, /* f64.convert_u/i64 */
+ WASM_OP_F64_PROMOTE_F32 = 0xbb, /* f64.promote/f32 */
+
+ /* reinterpretations */
+ WASM_OP_I32_REINTERPRET_F32 = 0xbc, /* i32.reinterpret/f32 */
+ WASM_OP_I64_REINTERPRET_F64 = 0xbd, /* i64.reinterpret/f64 */
+ WASM_OP_F32_REINTERPRET_I32 = 0xbe, /* f32.reinterpret/i32 */
+ WASM_OP_F64_REINTERPRET_I64 = 0xbf, /* f64.reinterpret/i64 */
+
+ WASM_OP_I32_EXTEND8_S = 0xc0, /* i32.extend8_s */
+ WASM_OP_I32_EXTEND16_S = 0xc1, /* i32.extend16_s */
+ WASM_OP_I64_EXTEND8_S = 0xc2, /* i64.extend8_s */
+ WASM_OP_I64_EXTEND16_S = 0xc3, /* i64.extend16_s */
+ WASM_OP_I64_EXTEND32_S = 0xc4, /* i64.extend32_s */
+
+ /* drop/select specified types*/
+ WASM_OP_DROP_64 = 0xc5,
+ WASM_OP_SELECT_64 = 0xc6,
+
+ /* extend op code */
+ EXT_OP_GET_LOCAL_FAST = 0xc7,
+ EXT_OP_SET_LOCAL_FAST_I64 = 0xc8,
+ EXT_OP_SET_LOCAL_FAST = 0xc9,
+ EXT_OP_TEE_LOCAL_FAST = 0xca,
+ EXT_OP_TEE_LOCAL_FAST_I64 = 0xcb,
+ EXT_OP_COPY_STACK_TOP = 0xcc,
+ EXT_OP_COPY_STACK_TOP_I64 = 0xcd,
+ EXT_OP_COPY_STACK_VALUES = 0xce,
+
+ WASM_OP_IMPDEP = 0xcf,
+
+ WASM_OP_REF_NULL = 0xd0, /* ref.null */
+ WASM_OP_REF_IS_NULL = 0xd1, /* ref.is_null */
+ WASM_OP_REF_FUNC = 0xd2, /* ref.func */
+
+ EXT_OP_BLOCK = 0xd3, /* block with blocktype */
+ EXT_OP_LOOP = 0xd4, /* loop with blocktype */
+ EXT_OP_IF = 0xd5, /* if with blocktype */
+ EXT_OP_BR_TABLE_CACHE = 0xd6, /* br_table from cache */
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ DEBUG_OP_BREAK = 0xd7, /* debug break point */
+#endif
+
+ /* Post-MVP extend op prefix */
+ WASM_OP_MISC_PREFIX = 0xfc,
+ WASM_OP_SIMD_PREFIX = 0xfd,
+ WASM_OP_ATOMIC_PREFIX = 0xfe,
+} WASMOpcode;
+
+typedef enum WASMMiscEXTOpcode {
+ WASM_OP_I32_TRUNC_SAT_S_F32 = 0x00,
+ WASM_OP_I32_TRUNC_SAT_U_F32 = 0x01,
+ WASM_OP_I32_TRUNC_SAT_S_F64 = 0x02,
+ WASM_OP_I32_TRUNC_SAT_U_F64 = 0x03,
+ WASM_OP_I64_TRUNC_SAT_S_F32 = 0x04,
+ WASM_OP_I64_TRUNC_SAT_U_F32 = 0x05,
+ WASM_OP_I64_TRUNC_SAT_S_F64 = 0x06,
+ WASM_OP_I64_TRUNC_SAT_U_F64 = 0x07,
+ WASM_OP_MEMORY_INIT = 0x08,
+ WASM_OP_DATA_DROP = 0x09,
+ WASM_OP_MEMORY_COPY = 0x0a,
+ WASM_OP_MEMORY_FILL = 0x0b,
+ WASM_OP_TABLE_INIT = 0x0c,
+ WASM_OP_ELEM_DROP = 0x0d,
+ WASM_OP_TABLE_COPY = 0x0e,
+ WASM_OP_TABLE_GROW = 0x0f,
+ WASM_OP_TABLE_SIZE = 0x10,
+ WASM_OP_TABLE_FILL = 0x11,
+} WASMMiscEXTOpcode;
+
+typedef enum WASMSimdEXTOpcode {
+ /* memory instruction */
+ SIMD_v128_load = 0x00,
+ SIMD_v128_load8x8_s = 0x01,
+ SIMD_v128_load8x8_u = 0x02,
+ SIMD_v128_load16x4_s = 0x03,
+ SIMD_v128_load16x4_u = 0x04,
+ SIMD_v128_load32x2_s = 0x05,
+ SIMD_v128_load32x2_u = 0x06,
+ SIMD_v128_load8_splat = 0x07,
+ SIMD_v128_load16_splat = 0x08,
+ SIMD_v128_load32_splat = 0x09,
+ SIMD_v128_load64_splat = 0x0a,
+ SIMD_v128_store = 0x0b,
+
+ /* basic operation */
+ SIMD_v128_const = 0x0c,
+ SIMD_v8x16_shuffle = 0x0d,
+ SIMD_v8x16_swizzle = 0x0e,
+
+ /* splat operation */
+ SIMD_i8x16_splat = 0x0f,
+ SIMD_i16x8_splat = 0x10,
+ SIMD_i32x4_splat = 0x11,
+ SIMD_i64x2_splat = 0x12,
+ SIMD_f32x4_splat = 0x13,
+ SIMD_f64x2_splat = 0x14,
+
+ /* lane operation */
+ SIMD_i8x16_extract_lane_s = 0x15,
+ SIMD_i8x16_extract_lane_u = 0x16,
+ SIMD_i8x16_replace_lane = 0x17,
+ SIMD_i16x8_extract_lane_s = 0x18,
+ SIMD_i16x8_extract_lane_u = 0x19,
+ SIMD_i16x8_replace_lane = 0x1a,
+ SIMD_i32x4_extract_lane = 0x1b,
+ SIMD_i32x4_replace_lane = 0x1c,
+ SIMD_i64x2_extract_lane = 0x1d,
+ SIMD_i64x2_replace_lane = 0x1e,
+ SIMD_f32x4_extract_lane = 0x1f,
+ SIMD_f32x4_replace_lane = 0x20,
+ SIMD_f64x2_extract_lane = 0x21,
+ SIMD_f64x2_replace_lane = 0x22,
+
+ /* i8x16 compare operation */
+ SIMD_i8x16_eq = 0x23,
+ SIMD_i8x16_ne = 0x24,
+ SIMD_i8x16_lt_s = 0x25,
+ SIMD_i8x16_lt_u = 0x26,
+ SIMD_i8x16_gt_s = 0x27,
+ SIMD_i8x16_gt_u = 0x28,
+ SIMD_i8x16_le_s = 0x29,
+ SIMD_i8x16_le_u = 0x2a,
+ SIMD_i8x16_ge_s = 0x2b,
+ SIMD_i8x16_ge_u = 0x2c,
+
+ /* i16x8 compare operation */
+ SIMD_i16x8_eq = 0x2d,
+ SIMD_i16x8_ne = 0x2e,
+ SIMD_i16x8_lt_s = 0x2f,
+ SIMD_i16x8_lt_u = 0x30,
+ SIMD_i16x8_gt_s = 0x31,
+ SIMD_i16x8_gt_u = 0x32,
+ SIMD_i16x8_le_s = 0x33,
+ SIMD_i16x8_le_u = 0x34,
+ SIMD_i16x8_ge_s = 0x35,
+ SIMD_i16x8_ge_u = 0x36,
+
+ /* i32x4 compare operation */
+ SIMD_i32x4_eq = 0x37,
+ SIMD_i32x4_ne = 0x38,
+ SIMD_i32x4_lt_s = 0x39,
+ SIMD_i32x4_lt_u = 0x3a,
+ SIMD_i32x4_gt_s = 0x3b,
+ SIMD_i32x4_gt_u = 0x3c,
+ SIMD_i32x4_le_s = 0x3d,
+ SIMD_i32x4_le_u = 0x3e,
+ SIMD_i32x4_ge_s = 0x3f,
+ SIMD_i32x4_ge_u = 0x40,
+
+ /* f32x4 compare operation */
+ SIMD_f32x4_eq = 0x41,
+ SIMD_f32x4_ne = 0x42,
+ SIMD_f32x4_lt = 0x43,
+ SIMD_f32x4_gt = 0x44,
+ SIMD_f32x4_le = 0x45,
+ SIMD_f32x4_ge = 0x46,
+
+ /* f64x2 compare operation */
+ SIMD_f64x2_eq = 0x47,
+ SIMD_f64x2_ne = 0x48,
+ SIMD_f64x2_lt = 0x49,
+ SIMD_f64x2_gt = 0x4a,
+ SIMD_f64x2_le = 0x4b,
+ SIMD_f64x2_ge = 0x4c,
+
+ /* v128 operation */
+ SIMD_v128_not = 0x4d,
+ SIMD_v128_and = 0x4e,
+ SIMD_v128_andnot = 0x4f,
+ SIMD_v128_or = 0x50,
+ SIMD_v128_xor = 0x51,
+ SIMD_v128_bitselect = 0x52,
+ SIMD_v128_any_true = 0x53,
+
+ /* Load Lane Operation */
+ SIMD_v128_load8_lane = 0x54,
+ SIMD_v128_load16_lane = 0x55,
+ SIMD_v128_load32_lane = 0x56,
+ SIMD_v128_load64_lane = 0x57,
+ SIMD_v128_store8_lane = 0x58,
+ SIMD_v128_store16_lane = 0x59,
+ SIMD_v128_store32_lane = 0x5a,
+ SIMD_v128_store64_lane = 0x5b,
+ SIMD_v128_load32_zero = 0x5c,
+ SIMD_v128_load64_zero = 0x5d,
+
+ /* Float conversion */
+ SIMD_f32x4_demote_f64x2_zero = 0x5e,
+ SIMD_f64x2_promote_low_f32x4_zero = 0x5f,
+
+ /* i8x16 Operation */
+ SIMD_i8x16_abs = 0x60,
+ SIMD_i8x16_neg = 0x61,
+ SIMD_i8x16_popcnt = 0x62,
+ SIMD_i8x16_all_true = 0x63,
+ SIMD_i8x16_bitmask = 0x64,
+ SIMD_i8x16_narrow_i16x8_s = 0x65,
+ SIMD_i8x16_narrow_i16x8_u = 0x66,
+ SIMD_f32x4_ceil = 0x67,
+ SIMD_f32x4_floor = 0x68,
+ SIMD_f32x4_trunc = 0x69,
+ SIMD_f32x4_nearest = 0x6a,
+ SIMD_i8x16_shl = 0x6b,
+ SIMD_i8x16_shr_s = 0x6c,
+ SIMD_i8x16_shr_u = 0x6d,
+ SIMD_i8x16_add = 0x6e,
+ SIMD_i8x16_add_sat_s = 0x6f,
+ SIMD_i8x16_add_sat_u = 0x70,
+ SIMD_i8x16_sub = 0x71,
+ SIMD_i8x16_sub_sat_s = 0x72,
+ SIMD_i8x16_sub_sat_u = 0x73,
+ SIMD_f64x2_ceil = 0x74,
+ SIMD_f64x2_floor = 0x75,
+ SIMD_i8x16_min_s = 0x76,
+ SIMD_i8x16_min_u = 0x77,
+ SIMD_i8x16_max_s = 0x78,
+ SIMD_i8x16_max_u = 0x79,
+ SIMD_f64x2_trunc = 0x7a,
+ SIMD_i8x16_avgr_u = 0x7b,
+ SIMD_i16x8_extadd_pairwise_i8x16_s = 0x7c,
+ SIMD_i16x8_extadd_pairwise_i8x16_u = 0x7d,
+ SIMD_i32x4_extadd_pairwise_i16x8_s = 0x7e,
+ SIMD_i32x4_extadd_pairwise_i16x8_u = 0x7f,
+
+ /* i16x8 operation */
+ SIMD_i16x8_abs = 0x80,
+ SIMD_i16x8_neg = 0x81,
+ SIMD_i16x8_q15mulr_sat_s = 0x82,
+ SIMD_i16x8_all_true = 0x83,
+ SIMD_i16x8_bitmask = 0x84,
+ SIMD_i16x8_narrow_i32x4_s = 0x85,
+ SIMD_i16x8_narrow_i32x4_u = 0x86,
+ SIMD_i16x8_extend_low_i8x16_s = 0x87,
+ SIMD_i16x8_extend_high_i8x16_s = 0x88,
+ SIMD_i16x8_extend_low_i8x16_u = 0x89,
+ SIMD_i16x8_extend_high_i8x16_u = 0x8a,
+ SIMD_i16x8_shl = 0x8b,
+ SIMD_i16x8_shr_s = 0x8c,
+ SIMD_i16x8_shr_u = 0x8d,
+ SIMD_i16x8_add = 0x8e,
+ SIMD_i16x8_add_sat_s = 0x8f,
+ SIMD_i16x8_add_sat_u = 0x90,
+ SIMD_i16x8_sub = 0x91,
+ SIMD_i16x8_sub_sat_s = 0x92,
+ SIMD_i16x8_sub_sat_u = 0x93,
+ SIMD_f64x2_nearest = 0x94,
+ SIMD_i16x8_mul = 0x95,
+ SIMD_i16x8_min_s = 0x96,
+ SIMD_i16x8_min_u = 0x97,
+ SIMD_i16x8_max_s = 0x98,
+ SIMD_i16x8_max_u = 0x99,
+ /* placeholder = 0x9a */
+ SIMD_i16x8_avgr_u = 0x9b,
+ SIMD_i16x8_extmul_low_i8x16_s = 0x9c,
+ SIMD_i16x8_extmul_high_i8x16_s = 0x9d,
+ SIMD_i16x8_extmul_low_i8x16_u = 0x9e,
+ SIMD_i16x8_extmul_high_i8x16_u = 0x9f,
+
+ /* i32x4 operation */
+ SIMD_i32x4_abs = 0xa0,
+ SIMD_i32x4_neg = 0xa1,
+ /* placeholder = 0xa2 */
+ SIMD_i32x4_all_true = 0xa3,
+ SIMD_i32x4_bitmask = 0xa4,
+ SIMD_i32x4_narrow_i64x2_s = 0xa5,
+ SIMD_i32x4_narrow_i64x2_u = 0xa6,
+ SIMD_i32x4_extend_low_i16x8_s = 0xa7,
+ SIMD_i32x4_extend_high_i16x8_s = 0xa8,
+ SIMD_i32x4_extend_low_i16x8_u = 0xa9,
+ SIMD_i32x4_extend_high_i16x8_u = 0xaa,
+ SIMD_i32x4_shl = 0xab,
+ SIMD_i32x4_shr_s = 0xac,
+ SIMD_i32x4_shr_u = 0xad,
+ SIMD_i32x4_add = 0xae,
+ SIMD_i32x4_add_sat_s = 0xaf,
+ SIMD_i32x4_add_sat_u = 0xb0,
+ SIMD_i32x4_sub = 0xb1,
+ SIMD_i32x4_sub_sat_s = 0xb2,
+ SIMD_i32x4_sub_sat_u = 0xb3,
+ /* placeholder = 0xb4 */
+ SIMD_i32x4_mul = 0xb5,
+ SIMD_i32x4_min_s = 0xb6,
+ SIMD_i32x4_min_u = 0xb7,
+ SIMD_i32x4_max_s = 0xb8,
+ SIMD_i32x4_max_u = 0xb9,
+ SIMD_i32x4_dot_i16x8_s = 0xba,
+ SIMD_i32x4_avgr_u = 0xbb,
+ SIMD_i32x4_extmul_low_i16x8_s = 0xbc,
+ SIMD_i32x4_extmul_high_i16x8_s = 0xbd,
+ SIMD_i32x4_extmul_low_i16x8_u = 0xbe,
+ SIMD_i32x4_extmul_high_i16x8_u = 0xbf,
+
+ /* i64x2 operation */
+ SIMD_i64x2_abs = 0xc0,
+ SIMD_i64x2_neg = 0xc1,
+ /* placeholder = 0xc2 */
+ SIMD_i64x2_all_true = 0xc3,
+ SIMD_i64x2_bitmask = 0xc4,
+ /* placeholder = 0xc5 */
+ /* placeholder = 0xc6 */
+ SIMD_i64x2_extend_low_i32x4_s = 0xc7,
+ SIMD_i64x2_extend_high_i32x4_s = 0xc8,
+ SIMD_i64x2_extend_low_i32x4_u = 0xc9,
+ SIMD_i64x2_extend_high_i32x4_u = 0xca,
+ SIMD_i64x2_shl = 0xcb,
+ SIMD_i64x2_shr_s = 0xcc,
+ SIMD_i64x2_shr_u = 0xcd,
+ SIMD_i64x2_add = 0xce,
+ /* placeholder = 0xcf */
+ /* placeholder = 0xd0 */
+ SIMD_i64x2_sub = 0xd1,
+ /* placeholder = 0xd2 */
+ /* placeholder = 0xd3 */
+ /* placeholder = 0xd4 */
+ SIMD_i64x2_mul = 0xd5,
+ SIMD_i64x2_eq = 0xd6,
+ SIMD_i64x2_ne = 0xd7,
+ SIMD_i64x2_lt_s = 0xd8,
+ SIMD_i64x2_gt_s = 0xd9,
+ SIMD_i64x2_le_s = 0xda,
+ SIMD_i64x2_ge_s = 0xdb,
+ SIMD_i64x2_extmul_low_i32x4_s = 0xdc,
+ SIMD_i64x2_extmul_high_i32x4_s = 0xdd,
+ SIMD_i64x2_extmul_low_i32x4_u = 0xde,
+ SIMD_i64x2_extmul_high_i32x4_u = 0xdf,
+
+ /* f32x4 operation */
+ SIMD_f32x4_abs = 0xe0,
+ SIMD_f32x4_neg = 0xe1,
+ SIMD_f32x4_round = 0xe2,
+ SIMD_f32x4_sqrt = 0xe3,
+ SIMD_f32x4_add = 0xe4,
+ SIMD_f32x4_sub = 0xe5,
+ SIMD_f32x4_mul = 0xe6,
+ SIMD_f32x4_div = 0xe7,
+ SIMD_f32x4_min = 0xe8,
+ SIMD_f32x4_max = 0xe9,
+ SIMD_f32x4_pmin = 0xea,
+ SIMD_f32x4_pmax = 0xeb,
+
+ /* f64x2 operation */
+ SIMD_f64x2_abs = 0xec,
+ SIMD_f64x2_neg = 0xed,
+ SIMD_f64x2_round = 0xee,
+ SIMD_f64x2_sqrt = 0xef,
+ SIMD_f64x2_add = 0xf0,
+ SIMD_f64x2_sub = 0xf1,
+ SIMD_f64x2_mul = 0xf2,
+ SIMD_f64x2_div = 0xf3,
+ SIMD_f64x2_min = 0xf4,
+ SIMD_f64x2_max = 0xf5,
+ SIMD_f64x2_pmin = 0xf6,
+ SIMD_f64x2_pmax = 0xf7,
+
+ /* conversion operation */
+ SIMD_i32x4_trunc_sat_f32x4_s = 0xf8,
+ SIMD_i32x4_trunc_sat_f32x4_u = 0xf9,
+ SIMD_f32x4_convert_i32x4_s = 0xfa,
+ SIMD_f32x4_convert_i32x4_u = 0xfb,
+ SIMD_i32x4_trunc_sat_f64x2_s_zero = 0xfc,
+ SIMD_i32x4_trunc_sat_f64x2_u_zero = 0xfd,
+ SIMD_f64x2_convert_low_i32x4_s = 0xfe,
+ SIMD_f64x2_convert_low_i32x4_u = 0xff,
+} WASMSimdEXTOpcode;
+
+typedef enum WASMAtomicEXTOpcode {
+ /* atomic wait and notify */
+ WASM_OP_ATOMIC_NOTIFY = 0x00,
+ WASM_OP_ATOMIC_WAIT32 = 0x01,
+ WASM_OP_ATOMIC_WAIT64 = 0x02,
+ WASM_OP_ATOMIC_FENCE = 0x03,
+ /* atomic load and store */
+ WASM_OP_ATOMIC_I32_LOAD = 0x10,
+ WASM_OP_ATOMIC_I64_LOAD = 0x11,
+ WASM_OP_ATOMIC_I32_LOAD8_U = 0x12,
+ WASM_OP_ATOMIC_I32_LOAD16_U = 0x13,
+ WASM_OP_ATOMIC_I64_LOAD8_U = 0x14,
+ WASM_OP_ATOMIC_I64_LOAD16_U = 0x15,
+ WASM_OP_ATOMIC_I64_LOAD32_U = 0x16,
+ WASM_OP_ATOMIC_I32_STORE = 0x17,
+ WASM_OP_ATOMIC_I64_STORE = 0x18,
+ WASM_OP_ATOMIC_I32_STORE8 = 0x19,
+ WASM_OP_ATOMIC_I32_STORE16 = 0x1a,
+ WASM_OP_ATOMIC_I64_STORE8 = 0x1b,
+ WASM_OP_ATOMIC_I64_STORE16 = 0x1c,
+ WASM_OP_ATOMIC_I64_STORE32 = 0x1d,
+ /* atomic add */
+ WASM_OP_ATOMIC_RMW_I32_ADD = 0x1e,
+ WASM_OP_ATOMIC_RMW_I64_ADD = 0x1f,
+ WASM_OP_ATOMIC_RMW_I32_ADD8_U = 0x20,
+ WASM_OP_ATOMIC_RMW_I32_ADD16_U = 0x21,
+ WASM_OP_ATOMIC_RMW_I64_ADD8_U = 0x22,
+ WASM_OP_ATOMIC_RMW_I64_ADD16_U = 0x23,
+ WASM_OP_ATOMIC_RMW_I64_ADD32_U = 0x24,
+ /* atomic sub */
+ WASM_OP_ATOMIC_RMW_I32_SUB = 0x25,
+ WASM_OP_ATOMIC_RMW_I64_SUB = 0x26,
+ WASM_OP_ATOMIC_RMW_I32_SUB8_U = 0x27,
+ WASM_OP_ATOMIC_RMW_I32_SUB16_U = 0x28,
+ WASM_OP_ATOMIC_RMW_I64_SUB8_U = 0x29,
+ WASM_OP_ATOMIC_RMW_I64_SUB16_U = 0x2a,
+ WASM_OP_ATOMIC_RMW_I64_SUB32_U = 0x2b,
+ /* atomic and */
+ WASM_OP_ATOMIC_RMW_I32_AND = 0x2c,
+ WASM_OP_ATOMIC_RMW_I64_AND = 0x2d,
+ WASM_OP_ATOMIC_RMW_I32_AND8_U = 0x2e,
+ WASM_OP_ATOMIC_RMW_I32_AND16_U = 0x2f,
+ WASM_OP_ATOMIC_RMW_I64_AND8_U = 0x30,
+ WASM_OP_ATOMIC_RMW_I64_AND16_U = 0x31,
+ WASM_OP_ATOMIC_RMW_I64_AND32_U = 0x32,
+ /* atomic or */
+ WASM_OP_ATOMIC_RMW_I32_OR = 0x33,
+ WASM_OP_ATOMIC_RMW_I64_OR = 0x34,
+ WASM_OP_ATOMIC_RMW_I32_OR8_U = 0x35,
+ WASM_OP_ATOMIC_RMW_I32_OR16_U = 0x36,
+ WASM_OP_ATOMIC_RMW_I64_OR8_U = 0x37,
+ WASM_OP_ATOMIC_RMW_I64_OR16_U = 0x38,
+ WASM_OP_ATOMIC_RMW_I64_OR32_U = 0x39,
+ /* atomic xor */
+ WASM_OP_ATOMIC_RMW_I32_XOR = 0x3a,
+ WASM_OP_ATOMIC_RMW_I64_XOR = 0x3b,
+ WASM_OP_ATOMIC_RMW_I32_XOR8_U = 0x3c,
+ WASM_OP_ATOMIC_RMW_I32_XOR16_U = 0x3d,
+ WASM_OP_ATOMIC_RMW_I64_XOR8_U = 0x3e,
+ WASM_OP_ATOMIC_RMW_I64_XOR16_U = 0x3f,
+ WASM_OP_ATOMIC_RMW_I64_XOR32_U = 0x40,
+ /* atomic xchg */
+ WASM_OP_ATOMIC_RMW_I32_XCHG = 0x41,
+ WASM_OP_ATOMIC_RMW_I64_XCHG = 0x42,
+ WASM_OP_ATOMIC_RMW_I32_XCHG8_U = 0x43,
+ WASM_OP_ATOMIC_RMW_I32_XCHG16_U = 0x44,
+ WASM_OP_ATOMIC_RMW_I64_XCHG8_U = 0x45,
+ WASM_OP_ATOMIC_RMW_I64_XCHG16_U = 0x46,
+ WASM_OP_ATOMIC_RMW_I64_XCHG32_U = 0x47,
+ /* atomic cmpxchg */
+ WASM_OP_ATOMIC_RMW_I32_CMPXCHG = 0x48,
+ WASM_OP_ATOMIC_RMW_I64_CMPXCHG = 0x49,
+ WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U = 0x4a,
+ WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U = 0x4b,
+ WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U = 0x4c,
+ WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U = 0x4d,
+ WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U = 0x4e,
+} WASMAtomicEXTOpcode;
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#define DEF_DEBUG_BREAK_HANDLE() \
+ [DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK), /* 0xd7 */
+#else
+#define DEF_DEBUG_BREAK_HANDLE()
+#endif
+
+#define SET_GOTO_TABLE_ELEM(opcode) [opcode] = HANDLE_OPCODE(opcode)
+
+/*
+ * Macro used to generate computed goto tables for the C interpreter.
+ */
+#define WASM_INSTRUCTION_NUM 256
+
+#define DEFINE_GOTO_TABLE(type, _name) \
+ static type _name[WASM_INSTRUCTION_NUM] = { \
+ HANDLE_OPCODE(WASM_OP_UNREACHABLE), /* 0x00 */ \
+ HANDLE_OPCODE(WASM_OP_NOP), /* 0x01 */ \
+ HANDLE_OPCODE(WASM_OP_BLOCK), /* 0x02 */ \
+ HANDLE_OPCODE(WASM_OP_LOOP), /* 0x03 */ \
+ HANDLE_OPCODE(WASM_OP_IF), /* 0x04 */ \
+ HANDLE_OPCODE(WASM_OP_ELSE), /* 0x05 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x06), /* 0x06 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x07), /* 0x07 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x08), /* 0x08 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x09), /* 0x09 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x0a), /* 0x0a */ \
+ HANDLE_OPCODE(WASM_OP_END), /* 0x0b */ \
+ HANDLE_OPCODE(WASM_OP_BR), /* 0x0c */ \
+ HANDLE_OPCODE(WASM_OP_BR_IF), /* 0x0d */ \
+ HANDLE_OPCODE(WASM_OP_BR_TABLE), /* 0x0e */ \
+ HANDLE_OPCODE(WASM_OP_RETURN), /* 0x0f */ \
+ HANDLE_OPCODE(WASM_OP_CALL), /* 0x10 */ \
+ HANDLE_OPCODE(WASM_OP_CALL_INDIRECT), /* 0x11 */ \
+ HANDLE_OPCODE(WASM_OP_RETURN_CALL), /* 0x12 */ \
+ HANDLE_OPCODE(WASM_OP_RETURN_CALL_INDIRECT), /* 0x13 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x14), /* 0x14 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x15), /* 0x15 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x16), /* 0x16 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x17), /* 0x17 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x18), /* 0x18 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x19), /* 0x19 */ \
+ HANDLE_OPCODE(WASM_OP_DROP), /* 0x1a */ \
+ HANDLE_OPCODE(WASM_OP_SELECT), /* 0x1b */ \
+ HANDLE_OPCODE(WASM_OP_SELECT_T), /* 0x1c */ \
+ HANDLE_OPCODE(WASM_OP_GET_GLOBAL_64), /* 0x1d */ \
+ HANDLE_OPCODE(WASM_OP_SET_GLOBAL_64), /* 0x1e */ \
+ HANDLE_OPCODE(WASM_OP_SET_GLOBAL_AUX_STACK), /* 0x1f */ \
+ HANDLE_OPCODE(WASM_OP_GET_LOCAL), /* 0x20 */ \
+ HANDLE_OPCODE(WASM_OP_SET_LOCAL), /* 0x21 */ \
+ HANDLE_OPCODE(WASM_OP_TEE_LOCAL), /* 0x22 */ \
+ HANDLE_OPCODE(WASM_OP_GET_GLOBAL), /* 0x23 */ \
+ HANDLE_OPCODE(WASM_OP_SET_GLOBAL), /* 0x24 */ \
+ HANDLE_OPCODE(WASM_OP_TABLE_GET), /* 0x25 */ \
+ HANDLE_OPCODE(WASM_OP_TABLE_SET), /* 0x26 */ \
+ HANDLE_OPCODE(WASM_OP_UNUSED_0x27), /* 0x27 */ \
+ HANDLE_OPCODE(WASM_OP_I32_LOAD), /* 0x28 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD), /* 0x29 */ \
+ HANDLE_OPCODE(WASM_OP_F32_LOAD), /* 0x2a */ \
+ HANDLE_OPCODE(WASM_OP_F64_LOAD), /* 0x2b */ \
+ HANDLE_OPCODE(WASM_OP_I32_LOAD8_S), /* 0x2c */ \
+ HANDLE_OPCODE(WASM_OP_I32_LOAD8_U), /* 0x2d */ \
+ HANDLE_OPCODE(WASM_OP_I32_LOAD16_S), /* 0x2e */ \
+ HANDLE_OPCODE(WASM_OP_I32_LOAD16_U), /* 0x2f */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD8_S), /* 0x30 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD8_U), /* 0x31 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD16_S), /* 0x32 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD16_U), /* 0x33 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD32_S), /* 0x34 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LOAD32_U), /* 0x35 */ \
+ HANDLE_OPCODE(WASM_OP_I32_STORE), /* 0x36 */ \
+ HANDLE_OPCODE(WASM_OP_I64_STORE), /* 0x37 */ \
+ HANDLE_OPCODE(WASM_OP_F32_STORE), /* 0x38 */ \
+ HANDLE_OPCODE(WASM_OP_F64_STORE), /* 0x39 */ \
+ HANDLE_OPCODE(WASM_OP_I32_STORE8), /* 0x3a */ \
+ HANDLE_OPCODE(WASM_OP_I32_STORE16), /* 0x3b */ \
+ HANDLE_OPCODE(WASM_OP_I64_STORE8), /* 0x3c */ \
+ HANDLE_OPCODE(WASM_OP_I64_STORE16), /* 0x3d */ \
+ HANDLE_OPCODE(WASM_OP_I64_STORE32), /* 0x3e */ \
+ HANDLE_OPCODE(WASM_OP_MEMORY_SIZE), /* 0x3f */ \
+ HANDLE_OPCODE(WASM_OP_MEMORY_GROW), /* 0x40 */ \
+ HANDLE_OPCODE(WASM_OP_I32_CONST), /* 0x41 */ \
+ HANDLE_OPCODE(WASM_OP_I64_CONST), /* 0x42 */ \
+ HANDLE_OPCODE(WASM_OP_F32_CONST), /* 0x43 */ \
+ HANDLE_OPCODE(WASM_OP_F64_CONST), /* 0x44 */ \
+ HANDLE_OPCODE(WASM_OP_I32_EQZ), /* 0x45 */ \
+ HANDLE_OPCODE(WASM_OP_I32_EQ), /* 0x46 */ \
+ HANDLE_OPCODE(WASM_OP_I32_NE), /* 0x47 */ \
+ HANDLE_OPCODE(WASM_OP_I32_LT_S), /* 0x48 */ \
+ HANDLE_OPCODE(WASM_OP_I32_LT_U), /* 0x49 */ \
+ HANDLE_OPCODE(WASM_OP_I32_GT_S), /* 0x4a */ \
+ HANDLE_OPCODE(WASM_OP_I32_GT_U), /* 0x4b */ \
+ HANDLE_OPCODE(WASM_OP_I32_LE_S), /* 0x4c */ \
+ HANDLE_OPCODE(WASM_OP_I32_LE_U), /* 0x4d */ \
+ HANDLE_OPCODE(WASM_OP_I32_GE_S), /* 0x4e */ \
+ HANDLE_OPCODE(WASM_OP_I32_GE_U), /* 0x4f */ \
+ HANDLE_OPCODE(WASM_OP_I64_EQZ), /* 0x50 */ \
+ HANDLE_OPCODE(WASM_OP_I64_EQ), /* 0x51 */ \
+ HANDLE_OPCODE(WASM_OP_I64_NE), /* 0x52 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LT_S), /* 0x53 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LT_U), /* 0x54 */ \
+ HANDLE_OPCODE(WASM_OP_I64_GT_S), /* 0x55 */ \
+ HANDLE_OPCODE(WASM_OP_I64_GT_U), /* 0x56 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LE_S), /* 0x57 */ \
+ HANDLE_OPCODE(WASM_OP_I64_LE_U), /* 0x58 */ \
+ HANDLE_OPCODE(WASM_OP_I64_GE_S), /* 0x59 */ \
+ HANDLE_OPCODE(WASM_OP_I64_GE_U), /* 0x5a */ \
+ HANDLE_OPCODE(WASM_OP_F32_EQ), /* 0x5b */ \
+ HANDLE_OPCODE(WASM_OP_F32_NE), /* 0x5c */ \
+ HANDLE_OPCODE(WASM_OP_F32_LT), /* 0x5d */ \
+ HANDLE_OPCODE(WASM_OP_F32_GT), /* 0x5e */ \
+ HANDLE_OPCODE(WASM_OP_F32_LE), /* 0x5f */ \
+ HANDLE_OPCODE(WASM_OP_F32_GE), /* 0x60 */ \
+ HANDLE_OPCODE(WASM_OP_F64_EQ), /* 0x61 */ \
+ HANDLE_OPCODE(WASM_OP_F64_NE), /* 0x62 */ \
+ HANDLE_OPCODE(WASM_OP_F64_LT), /* 0x63 */ \
+ HANDLE_OPCODE(WASM_OP_F64_GT), /* 0x64 */ \
+ HANDLE_OPCODE(WASM_OP_F64_LE), /* 0x65 */ \
+ HANDLE_OPCODE(WASM_OP_F64_GE), /* 0x66 */ \
+ HANDLE_OPCODE(WASM_OP_I32_CLZ), /* 0x67 */ \
+ HANDLE_OPCODE(WASM_OP_I32_CTZ), /* 0x68 */ \
+ HANDLE_OPCODE(WASM_OP_I32_POPCNT), /* 0x69 */ \
+ HANDLE_OPCODE(WASM_OP_I32_ADD), /* 0x6a */ \
+ HANDLE_OPCODE(WASM_OP_I32_SUB), /* 0x6b */ \
+ HANDLE_OPCODE(WASM_OP_I32_MUL), /* 0x6c */ \
+ HANDLE_OPCODE(WASM_OP_I32_DIV_S), /* 0x6d */ \
+ HANDLE_OPCODE(WASM_OP_I32_DIV_U), /* 0x6e */ \
+ HANDLE_OPCODE(WASM_OP_I32_REM_S), /* 0x6f */ \
+ HANDLE_OPCODE(WASM_OP_I32_REM_U), /* 0x70 */ \
+ HANDLE_OPCODE(WASM_OP_I32_AND), /* 0x71 */ \
+ HANDLE_OPCODE(WASM_OP_I32_OR), /* 0x72 */ \
+ HANDLE_OPCODE(WASM_OP_I32_XOR), /* 0x73 */ \
+ HANDLE_OPCODE(WASM_OP_I32_SHL), /* 0x74 */ \
+ HANDLE_OPCODE(WASM_OP_I32_SHR_S), /* 0x75 */ \
+ HANDLE_OPCODE(WASM_OP_I32_SHR_U), /* 0x76 */ \
+ HANDLE_OPCODE(WASM_OP_I32_ROTL), /* 0x77 */ \
+ HANDLE_OPCODE(WASM_OP_I32_ROTR), /* 0x78 */ \
+ HANDLE_OPCODE(WASM_OP_I64_CLZ), /* 0x79 */ \
+ HANDLE_OPCODE(WASM_OP_I64_CTZ), /* 0x7a */ \
+ HANDLE_OPCODE(WASM_OP_I64_POPCNT), /* 0x7b */ \
+ HANDLE_OPCODE(WASM_OP_I64_ADD), /* 0x7c */ \
+ HANDLE_OPCODE(WASM_OP_I64_SUB), /* 0x7d */ \
+ HANDLE_OPCODE(WASM_OP_I64_MUL), /* 0x7e */ \
+ HANDLE_OPCODE(WASM_OP_I64_DIV_S), /* 0x7f */ \
+ HANDLE_OPCODE(WASM_OP_I64_DIV_U), /* 0x80 */ \
+ HANDLE_OPCODE(WASM_OP_I64_REM_S), /* 0x81 */ \
+ HANDLE_OPCODE(WASM_OP_I64_REM_U), /* 0x82 */ \
+ HANDLE_OPCODE(WASM_OP_I64_AND), /* 0x83 */ \
+ HANDLE_OPCODE(WASM_OP_I64_OR), /* 0x84 */ \
+ HANDLE_OPCODE(WASM_OP_I64_XOR), /* 0x85 */ \
+ HANDLE_OPCODE(WASM_OP_I64_SHL), /* 0x86 */ \
+ HANDLE_OPCODE(WASM_OP_I64_SHR_S), /* 0x87 */ \
+ HANDLE_OPCODE(WASM_OP_I64_SHR_U), /* 0x88 */ \
+ HANDLE_OPCODE(WASM_OP_I64_ROTL), /* 0x89 */ \
+ HANDLE_OPCODE(WASM_OP_I64_ROTR), /* 0x8a */ \
+ HANDLE_OPCODE(WASM_OP_F32_ABS), /* 0x8b */ \
+ HANDLE_OPCODE(WASM_OP_F32_NEG), /* 0x8c */ \
+ HANDLE_OPCODE(WASM_OP_F32_CEIL), /* 0x8d */ \
+ HANDLE_OPCODE(WASM_OP_F32_FLOOR), /* 0x8e */ \
+ HANDLE_OPCODE(WASM_OP_F32_TRUNC), /* 0x8f */ \
+ HANDLE_OPCODE(WASM_OP_F32_NEAREST), /* 0x90 */ \
+ HANDLE_OPCODE(WASM_OP_F32_SQRT), /* 0x91 */ \
+ HANDLE_OPCODE(WASM_OP_F32_ADD), /* 0x92 */ \
+ HANDLE_OPCODE(WASM_OP_F32_SUB), /* 0x93 */ \
+ HANDLE_OPCODE(WASM_OP_F32_MUL), /* 0x94 */ \
+ HANDLE_OPCODE(WASM_OP_F32_DIV), /* 0x95 */ \
+ HANDLE_OPCODE(WASM_OP_F32_MIN), /* 0x96 */ \
+ HANDLE_OPCODE(WASM_OP_F32_MAX), /* 0x97 */ \
+ HANDLE_OPCODE(WASM_OP_F32_COPYSIGN), /* 0x98 */ \
+ HANDLE_OPCODE(WASM_OP_F64_ABS), /* 0x99 */ \
+ HANDLE_OPCODE(WASM_OP_F64_NEG), /* 0x9a */ \
+ HANDLE_OPCODE(WASM_OP_F64_CEIL), /* 0x9b */ \
+ HANDLE_OPCODE(WASM_OP_F64_FLOOR), /* 0x9c */ \
+ HANDLE_OPCODE(WASM_OP_F64_TRUNC), /* 0x9d */ \
+ HANDLE_OPCODE(WASM_OP_F64_NEAREST), /* 0x9e */ \
+ HANDLE_OPCODE(WASM_OP_F64_SQRT), /* 0x9f */ \
+ HANDLE_OPCODE(WASM_OP_F64_ADD), /* 0xa0 */ \
+ HANDLE_OPCODE(WASM_OP_F64_SUB), /* 0xa1 */ \
+ HANDLE_OPCODE(WASM_OP_F64_MUL), /* 0xa2 */ \
+ HANDLE_OPCODE(WASM_OP_F64_DIV), /* 0xa3 */ \
+ HANDLE_OPCODE(WASM_OP_F64_MIN), /* 0xa4 */ \
+ HANDLE_OPCODE(WASM_OP_F64_MAX), /* 0xa5 */ \
+ HANDLE_OPCODE(WASM_OP_F64_COPYSIGN), /* 0xa6 */ \
+ HANDLE_OPCODE(WASM_OP_I32_WRAP_I64), /* 0xa7 */ \
+ HANDLE_OPCODE(WASM_OP_I32_TRUNC_S_F32), /* 0xa8 */ \
+ HANDLE_OPCODE(WASM_OP_I32_TRUNC_U_F32), /* 0xa9 */ \
+ HANDLE_OPCODE(WASM_OP_I32_TRUNC_S_F64), /* 0xaa */ \
+ HANDLE_OPCODE(WASM_OP_I32_TRUNC_U_F64), /* 0xab */ \
+ HANDLE_OPCODE(WASM_OP_I64_EXTEND_S_I32), /* 0xac */ \
+ HANDLE_OPCODE(WASM_OP_I64_EXTEND_U_I32), /* 0xad */ \
+ HANDLE_OPCODE(WASM_OP_I64_TRUNC_S_F32), /* 0xae */ \
+ HANDLE_OPCODE(WASM_OP_I64_TRUNC_U_F32), /* 0xaf */ \
+ HANDLE_OPCODE(WASM_OP_I64_TRUNC_S_F64), /* 0xb0 */ \
+ HANDLE_OPCODE(WASM_OP_I64_TRUNC_U_F64), /* 0xb1 */ \
+ HANDLE_OPCODE(WASM_OP_F32_CONVERT_S_I32), /* 0xb2 */ \
+ HANDLE_OPCODE(WASM_OP_F32_CONVERT_U_I32), /* 0xb3 */ \
+ HANDLE_OPCODE(WASM_OP_F32_CONVERT_S_I64), /* 0xb4 */ \
+ HANDLE_OPCODE(WASM_OP_F32_CONVERT_U_I64), /* 0xb5 */ \
+ HANDLE_OPCODE(WASM_OP_F32_DEMOTE_F64), /* 0xb6 */ \
+ HANDLE_OPCODE(WASM_OP_F64_CONVERT_S_I32), /* 0xb7 */ \
+ HANDLE_OPCODE(WASM_OP_F64_CONVERT_U_I32), /* 0xb8 */ \
+ HANDLE_OPCODE(WASM_OP_F64_CONVERT_S_I64), /* 0xb9 */ \
+ HANDLE_OPCODE(WASM_OP_F64_CONVERT_U_I64), /* 0xba */ \
+ HANDLE_OPCODE(WASM_OP_F64_PROMOTE_F32), /* 0xbb */ \
+ HANDLE_OPCODE(WASM_OP_I32_REINTERPRET_F32), /* 0xbc */ \
+ HANDLE_OPCODE(WASM_OP_I64_REINTERPRET_F64), /* 0xbd */ \
+ HANDLE_OPCODE(WASM_OP_F32_REINTERPRET_I32), /* 0xbe */ \
+ HANDLE_OPCODE(WASM_OP_F64_REINTERPRET_I64), /* 0xbf */ \
+ HANDLE_OPCODE(WASM_OP_I32_EXTEND8_S), /* 0xc0 */ \
+ HANDLE_OPCODE(WASM_OP_I32_EXTEND16_S), /* 0xc1 */ \
+ HANDLE_OPCODE(WASM_OP_I64_EXTEND8_S), /* 0xc2 */ \
+ HANDLE_OPCODE(WASM_OP_I64_EXTEND16_S), /* 0xc3 */ \
+ HANDLE_OPCODE(WASM_OP_I64_EXTEND32_S), /* 0xc4 */ \
+ HANDLE_OPCODE(WASM_OP_DROP_64), /* 0xc5 */ \
+ HANDLE_OPCODE(WASM_OP_SELECT_64), /* 0xc6 */ \
+ HANDLE_OPCODE(EXT_OP_GET_LOCAL_FAST), /* 0xc7 */ \
+ HANDLE_OPCODE(EXT_OP_SET_LOCAL_FAST_I64), /* 0xc8 */ \
+ HANDLE_OPCODE(EXT_OP_SET_LOCAL_FAST), /* 0xc9 */ \
+ HANDLE_OPCODE(EXT_OP_TEE_LOCAL_FAST), /* 0xca */ \
+ HANDLE_OPCODE(EXT_OP_TEE_LOCAL_FAST_I64), /* 0xcb */ \
+ HANDLE_OPCODE(EXT_OP_COPY_STACK_TOP), /* 0xcc */ \
+ HANDLE_OPCODE(EXT_OP_COPY_STACK_TOP_I64), /* 0xcd */ \
+ HANDLE_OPCODE(EXT_OP_COPY_STACK_VALUES), /* 0xce */ \
+ HANDLE_OPCODE(WASM_OP_IMPDEP), /* 0xcf */ \
+ HANDLE_OPCODE(WASM_OP_REF_NULL), /* 0xd0 */ \
+ HANDLE_OPCODE(WASM_OP_REF_IS_NULL), /* 0xd1 */ \
+ HANDLE_OPCODE(WASM_OP_REF_FUNC), /* 0xd2 */ \
+ HANDLE_OPCODE(EXT_OP_BLOCK), /* 0xd3 */ \
+ HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \
+ HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \
+ HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \
+ SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \
+ SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \
+ DEF_DEBUG_BREAK_HANDLE() \
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_OPCODE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.c
new file mode 100644
index 000000000..29365024d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.c
@@ -0,0 +1,3532 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_runtime.h"
+#include "wasm_loader.h"
+#include "wasm_interp.h"
+#include "bh_common.h"
+#include "bh_log.h"
+#include "mem_alloc.h"
+#include "../common/wasm_runtime_common.h"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "../common/wasm_shared_memory.h"
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#endif
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#include "../libraries/debug-engine/debug_engine.h"
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+#include "../fast-jit/jit_compiler.h"
+#endif
+#if WASM_ENABLE_JIT != 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,
+ "WASM module instantiate failed: %s", string);
+ }
+}
+
+static void
+set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
+{
+ va_list args;
+ char buf[128];
+
+ if (error_buf != NULL) {
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ snprintf(error_buf, error_buf_size,
+ "WASM module instantiate failed: %s", buf);
+ }
+}
+
+WASMModule *
+wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size)
+{
+ return wasm_loader_load(buf, size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+ true,
+#endif
+ error_buf, error_buf_size);
+}
+
+WASMModule *
+wasm_load_from_sections(WASMSection *section_list, char *error_buf,
+ uint32 error_buf_size)
+{
+ return wasm_loader_load_from_sections(section_list, error_buf,
+ error_buf_size);
+}
+
+void
+wasm_unload(WASMModule *module)
+{
+ wasm_loader_unload(module);
+}
+
+static void *
+runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
+{
+ void *mem;
+
+ if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ return NULL;
+ }
+
+ memset(mem, 0, (uint32)size);
+ return mem;
+}
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static WASMModuleInstance *
+get_sub_module_inst(const WASMModuleInstance *parent_module_inst,
+ const WASMModule *sub_module)
+{
+ bh_list *sub_module_inst_list = parent_module_inst->e->sub_module_inst_list;
+ WASMSubModInstNode *node = bh_list_first_elem(sub_module_inst_list);
+
+ while (node && sub_module != node->module_inst->module) {
+ node = bh_list_elem_next(node);
+ }
+ return node ? node->module_inst : NULL;
+}
+#endif
+
+/**
+ * Destroy memory instances.
+ */
+static void
+memories_deinstantiate(WASMModuleInstance *module_inst,
+ WASMMemoryInstance **memories, uint32 count)
+{
+ uint32 i;
+ if (memories) {
+ for (i = 0; i < count; i++) {
+ if (memories[i]) {
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModule *module = module_inst->module;
+ if (i < module->import_memory_count
+ && module->import_memories[i].u.memory.import_module) {
+ continue;
+ }
+#endif
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (memories[i]->is_shared) {
+ int32 ref_count = shared_memory_dec_reference(
+ (WASMModuleCommon *)module_inst->module);
+ bh_assert(ref_count >= 0);
+
+ /* if the reference count is not zero,
+ don't free the memory */
+ if (ref_count > 0)
+ continue;
+ }
+#endif
+ if (memories[i]->heap_handle) {
+ mem_allocator_destroy(memories[i]->heap_handle);
+ wasm_runtime_free(memories[i]->heap_handle);
+ memories[i]->heap_handle = NULL;
+ }
+ if (memories[i]->memory_data) {
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ wasm_runtime_free(memories[i]->memory_data);
+#else
+#ifdef BH_PLATFORM_WINDOWS
+ os_mem_decommit(memories[i]->memory_data,
+ memories[i]->num_bytes_per_page
+ * memories[i]->cur_page_count);
+#endif
+ os_munmap((uint8 *)memories[i]->memory_data,
+ 8 * (uint64)BH_GB);
+#endif
+ }
+ }
+ }
+ wasm_runtime_free(memories);
+ }
+ (void)module_inst;
+}
+
+static WASMMemoryInstance *
+memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
+ uint32 num_bytes_per_page, uint32 init_page_count,
+ uint32 max_page_count, uint32 heap_size, uint32 flags,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMModule *module = module_inst->module;
+ uint64 memory_data_size;
+ uint32 heap_offset = num_bytes_per_page * init_page_count;
+ uint32 inc_page_count, aux_heap_base, global_idx;
+ uint32 bytes_of_last_page, bytes_to_page_end;
+ uint8 *global_addr;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ uint8 *mapped_mem;
+ uint64 map_size = 8 * (uint64)BH_GB;
+ uint64 page_size = os_getpagesize();
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ bool is_shared_memory = flags & 0x02 ? true : false;
+
+ /* shared memory */
+ if (is_shared_memory) {
+ WASMSharedMemNode *node = wasm_module_get_shared_memory(
+ (WASMModuleCommon *)module_inst->module);
+ /* If the memory of this module has been instantiated,
+ return the memory instance directly */
+ if (node) {
+ uint32 ref_count;
+ ref_count = shared_memory_inc_reference(
+ (WASMModuleCommon *)module_inst->module);
+ bh_assert(ref_count > 0);
+ memory = (WASMMemoryInstance *)shared_memory_get_memory_inst(node);
+ bh_assert(memory);
+
+ (void)ref_count;
+ return memory;
+ }
+ }
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */
+
+ if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1
+ && module_inst->module->free_function != (uint32)-1) {
+ /* Disable app heap, use malloc/free function exported
+ by wasm app to allocate/free memory instead */
+ heap_size = 0;
+ }
+
+ if (init_page_count == max_page_count && init_page_count == 1) {
+ /* If only one page and at most one page, we just append
+ the app heap to the end of linear memory, enlarge the
+ num_bytes_per_page, and don't change the page count */
+ heap_offset = num_bytes_per_page;
+ num_bytes_per_page += heap_size;
+ if (num_bytes_per_page < heap_size) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to insert app heap into linear memory, "
+ "try using `--heap_size=0` option");
+ return NULL;
+ }
+ }
+ else if (heap_size > 0) {
+ if (init_page_count == max_page_count && init_page_count == 0) {
+ /* If the memory data size is always 0, we resize it to
+ one page for app heap */
+ num_bytes_per_page = heap_size;
+ heap_offset = 0;
+ inc_page_count = 1;
+ }
+ else if (module->aux_heap_base_global_index != (uint32)-1
+ && module->aux_heap_base
+ < num_bytes_per_page * init_page_count) {
+ /* Insert app heap before __heap_base */
+ aux_heap_base = module->aux_heap_base;
+ bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+ if (bytes_of_last_page == 0)
+ bytes_of_last_page = num_bytes_per_page;
+ bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
+ inc_page_count =
+ (heap_size - bytes_to_page_end + num_bytes_per_page - 1)
+ / num_bytes_per_page;
+ heap_offset = aux_heap_base;
+ aux_heap_base += heap_size;
+
+ bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+ if (bytes_of_last_page == 0)
+ bytes_of_last_page = num_bytes_per_page;
+ bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
+ if (bytes_to_page_end < 1 * BH_KB) {
+ aux_heap_base += 1 * BH_KB;
+ inc_page_count++;
+ }
+
+ /* Adjust __heap_base global value */
+ global_idx = module->aux_heap_base_global_index;
+ bh_assert(module_inst->e->globals
+ && global_idx < module_inst->e->global_count);
+ global_addr = module_inst->global_data
+ + module_inst->e->globals[global_idx].data_offset;
+ *(uint32 *)global_addr = aux_heap_base;
+ LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base);
+ }
+ else {
+ /* Insert app heap before new page */
+ inc_page_count =
+ (heap_size + num_bytes_per_page - 1) / num_bytes_per_page;
+ heap_offset = num_bytes_per_page * init_page_count;
+ heap_size = num_bytes_per_page * inc_page_count;
+ if (heap_size > 0)
+ heap_size -= 1 * BH_KB;
+ }
+ init_page_count += inc_page_count;
+ max_page_count += inc_page_count;
+ if (init_page_count > DEFAULT_MAX_PAGES) {
+ set_error_buf(error_buf, error_buf_size,
+ "failed to insert app heap into linear memory, "
+ "try using `--heap_size=0` option");
+ return NULL;
+ }
+ else if (init_page_count == DEFAULT_MAX_PAGES) {
+ num_bytes_per_page = UINT32_MAX;
+ init_page_count = max_page_count = 1;
+ }
+ if (max_page_count > DEFAULT_MAX_PAGES)
+ max_page_count = DEFAULT_MAX_PAGES;
+ }
+
+ LOG_VERBOSE("Memory instantiate:");
+ LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u",
+ num_bytes_per_page, init_page_count, max_page_count);
+ LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size);
+
+ memory_data_size = (uint64)num_bytes_per_page * init_page_count;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (is_shared_memory) {
+ /* Allocate max page for shared memory */
+ memory_data_size = (uint64)num_bytes_per_page * max_page_count;
+ }
+#endif
+ bh_assert(memory_data_size <= 4 * (uint64)BH_GB);
+
+ bh_assert(memory != NULL);
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ if (memory_data_size > 0
+ && !(memory->memory_data =
+ runtime_malloc(memory_data_size, error_buf, error_buf_size))) {
+ goto fail1;
+ }
+#else
+ memory_data_size = (memory_data_size + page_size - 1) & ~(page_size - 1);
+
+ /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G:
+ * ea = i + memarg.offset
+ * both i and memarg.offset are u32 in range 0 to 4G
+ * so the range of ea is 0 to 8G
+ */
+ if (!(memory->memory_data = mapped_mem =
+ os_mmap(NULL, map_size, MMAP_PROT_NONE, MMAP_MAP_NONE))) {
+ set_error_buf(error_buf, error_buf_size, "mmap memory failed");
+ goto fail1;
+ }
+
+#ifdef BH_PLATFORM_WINDOWS
+ if (!os_mem_commit(mapped_mem, memory_data_size,
+ MMAP_PROT_READ | MMAP_PROT_WRITE)) {
+ set_error_buf(error_buf, error_buf_size, "commit memory failed");
+ os_munmap(mapped_mem, map_size);
+ goto fail1;
+ }
+#endif
+
+ if (os_mprotect(mapped_mem, memory_data_size,
+ MMAP_PROT_READ | MMAP_PROT_WRITE)
+ != 0) {
+ set_error_buf(error_buf, error_buf_size, "mprotect memory failed");
+ goto fail2;
+ }
+ /* Newly allocated pages are filled with zero by the OS, we don't fill it
+ * again here */
+#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
+
+ if (memory_data_size > UINT32_MAX)
+ memory_data_size = (uint32)memory_data_size;
+
+ memory->module_type = Wasm_Module_Bytecode;
+ memory->num_bytes_per_page = num_bytes_per_page;
+ memory->cur_page_count = init_page_count;
+ memory->max_page_count = max_page_count;
+ memory->memory_data_size = (uint32)memory_data_size;
+
+ memory->heap_data = memory->memory_data + heap_offset;
+ memory->heap_data_end = memory->heap_data + heap_size;
+ memory->memory_data_end = memory->memory_data + (uint32)memory_data_size;
+
+ /* Initialize heap */
+ if (heap_size > 0) {
+ uint32 heap_struct_size = mem_allocator_get_heap_struct_size();
+
+ if (!(memory->heap_handle = runtime_malloc(
+ (uint64)heap_struct_size, error_buf, error_buf_size))) {
+ goto fail2;
+ }
+ if (!mem_allocator_create_with_struct_and_pool(
+ memory->heap_handle, heap_struct_size, memory->heap_data,
+ heap_size)) {
+ set_error_buf(error_buf, error_buf_size, "init app heap failed");
+ goto fail3;
+ }
+ }
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ if (memory_data_size > 0) {
+#if UINTPTR_MAX == UINT64_MAX
+ memory->mem_bound_check_1byte.u64 = memory_data_size - 1;
+ memory->mem_bound_check_2bytes.u64 = memory_data_size - 2;
+ memory->mem_bound_check_4bytes.u64 = memory_data_size - 4;
+ memory->mem_bound_check_8bytes.u64 = memory_data_size - 8;
+ memory->mem_bound_check_16bytes.u64 = memory_data_size - 16;
+#else
+ memory->mem_bound_check_1byte.u32[0] = (uint32)memory_data_size - 1;
+ memory->mem_bound_check_2bytes.u32[0] = (uint32)memory_data_size - 2;
+ memory->mem_bound_check_4bytes.u32[0] = (uint32)memory_data_size - 4;
+ memory->mem_bound_check_8bytes.u32[0] = (uint32)memory_data_size - 8;
+ memory->mem_bound_check_16bytes.u32[0] = (uint32)memory_data_size - 16;
+#endif
+ }
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (is_shared_memory) {
+ memory->is_shared = true;
+ if (!shared_memory_set_memory_inst(
+ (WASMModuleCommon *)module_inst->module,
+ (WASMMemoryInstanceCommon *)memory)) {
+ set_error_buf(error_buf, error_buf_size, "allocate memory failed");
+ goto fail4;
+ }
+ }
+#endif
+
+ LOG_VERBOSE("Memory instantiate success.");
+ return memory;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+fail4:
+ if (heap_size > 0)
+ mem_allocator_destroy(memory->heap_handle);
+#endif
+fail3:
+ if (heap_size > 0)
+ wasm_runtime_free(memory->heap_handle);
+fail2:
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+ if (memory->memory_data)
+ wasm_runtime_free(memory->memory_data);
+#else
+#ifdef BH_PLATFORM_WINDOWS
+ os_mem_decommit(mapped_mem, memory_data_size);
+#endif
+ os_munmap(mapped_mem, map_size);
+#endif
+fail1:
+ return NULL;
+}
+
+/**
+ * Instantiate memories in a module.
+ */
+static WASMMemoryInstance **
+memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
+ uint32 heap_size, char *error_buf, uint32 error_buf_size)
+{
+ WASMImport *import;
+ uint32 mem_index = 0, i,
+ memory_count = module->import_memory_count + module->memory_count;
+ uint64 total_size;
+ WASMMemoryInstance **memories, *memory;
+
+ total_size = sizeof(WASMMemoryInstance *) * (uint64)memory_count;
+
+ if (!(memories = runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ memory = module_inst->global_table_data.memory_instances;
+
+ /* instantiate memories from import section */
+ import = module->import_memories;
+ for (i = 0; i < module->import_memory_count; i++, import++, memory++) {
+ uint32 num_bytes_per_page = import->u.memory.num_bytes_per_page;
+ uint32 init_page_count = import->u.memory.init_page_count;
+ uint32 max_page_count = import->u.memory.max_page_count;
+ uint32 flags = import->u.memory.flags;
+ uint32 actual_heap_size = heap_size;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (import->u.memory.import_module != NULL) {
+ WASMModuleInstance *module_inst_linked;
+
+ if (!(module_inst_linked = get_sub_module_inst(
+ module_inst, import->u.memory.import_module))) {
+ set_error_buf(error_buf, error_buf_size, "unknown memory");
+ memories_deinstantiate(module_inst, memories, memory_count);
+ return NULL;
+ }
+
+ if (!(memories[mem_index++] = wasm_lookup_memory(
+ module_inst_linked, import->u.memory.field_name))) {
+ set_error_buf(error_buf, error_buf_size, "unknown memory");
+ memories_deinstantiate(module_inst, memories, memory_count);
+ return NULL;
+ }
+ }
+ else
+#endif
+ {
+ if (!(memories[mem_index++] = memory_instantiate(
+ module_inst, memory, num_bytes_per_page, init_page_count,
+ max_page_count, actual_heap_size, flags, error_buf,
+ error_buf_size))) {
+ memories_deinstantiate(module_inst, memories, memory_count);
+ return NULL;
+ }
+ }
+ }
+
+ /* instantiate memories from memory section */
+ for (i = 0; i < module->memory_count; i++, memory++) {
+ if (!(memories[mem_index++] = memory_instantiate(
+ module_inst, memory, module->memories[i].num_bytes_per_page,
+ module->memories[i].init_page_count,
+ module->memories[i].max_page_count, heap_size,
+ module->memories[i].flags, error_buf, error_buf_size))) {
+ memories_deinstantiate(module_inst, memories, memory_count);
+ return NULL;
+ }
+ }
+
+ bh_assert(mem_index == memory_count);
+ (void)module_inst;
+ return memories;
+}
+
+/**
+ * Destroy table instances.
+ */
+static void
+tables_deinstantiate(WASMModuleInstance *module_inst)
+{
+ if (module_inst->tables) {
+ wasm_runtime_free(module_inst->tables);
+ }
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (module_inst->e->table_insts_linked) {
+ wasm_runtime_free(module_inst->e->table_insts_linked);
+ }
+#endif
+}
+
+/**
+ * Instantiate tables in a module.
+ */
+static WASMTableInstance **
+tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
+ WASMTableInstance *first_table, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMImport *import;
+ uint32 table_index = 0, i;
+ uint32 table_count = module->import_table_count + module->table_count;
+ uint64 total_size = (uint64)sizeof(WASMTableInstance *) * table_count;
+ WASMTableInstance **tables, *table = first_table;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ uint64 total_size_of_tables_linked =
+ (uint64)sizeof(WASMTableInstance *) * module->import_table_count;
+ WASMTableInstance **table_linked = NULL;
+#endif
+
+ if (!(tables = runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (module->import_table_count > 0
+ && !(module_inst->e->table_insts_linked = table_linked = runtime_malloc(
+ total_size_of_tables_linked, error_buf, error_buf_size))) {
+ goto fail;
+ }
+#endif
+
+ /* instantiate tables from import section */
+ import = module->import_tables;
+ for (i = 0; i < module->import_table_count; i++, import++) {
+ uint32 max_size_fixed = 0;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMTableInstance *table_inst_linked = NULL;
+ WASMModuleInstance *module_inst_linked = NULL;
+
+ if (import->u.table.import_module) {
+ if (!(module_inst_linked = get_sub_module_inst(
+ module_inst, import->u.table.import_module))) {
+ set_error_buf(error_buf, error_buf_size, "unknown table");
+ goto fail;
+ }
+
+ if (!(table_inst_linked = wasm_lookup_table(
+ module_inst_linked, import->u.table.field_name))) {
+ set_error_buf(error_buf, error_buf_size, "unknown table");
+ goto fail;
+ }
+
+ total_size = offsetof(WASMTableInstance, elems);
+ }
+ else
+#endif
+ {
+ /* in order to save memory, alloc resource as few as possible */
+ max_size_fixed = import->u.table.possible_grow
+ ? import->u.table.max_size
+ : import->u.table.init_size;
+
+ /* it is a built-in table, every module has its own */
+ total_size = offsetof(WASMTableInstance, elems);
+ total_size += (uint64)max_size_fixed * sizeof(uint32);
+ }
+
+ tables[table_index++] = table;
+
+ /* Set all elements to -1 to mark them as uninitialized elements */
+ memset(table, -1, (uint32)total_size);
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ *table_linked = table_inst_linked;
+ if (table_inst_linked != NULL) {
+ table->cur_size = table_inst_linked->cur_size;
+ table->max_size = table_inst_linked->max_size;
+ }
+ else
+#endif
+ {
+ table->cur_size = import->u.table.init_size;
+ table->max_size = max_size_fixed;
+ }
+
+ table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ table_linked++;
+#endif
+ }
+
+ /* instantiate tables from table section */
+ for (i = 0; i < module->table_count; i++) {
+ uint32 max_size_fixed = 0;
+
+ total_size = offsetof(WASMTableInstance, elems);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /* in case, a module which imports this table will grow it */
+ max_size_fixed = module->tables[i].max_size;
+#else
+ max_size_fixed = module->tables[i].possible_grow
+ ? module->tables[i].max_size
+ : module->tables[i].init_size;
+#endif
+ total_size += sizeof(uint32) * (uint64)max_size_fixed;
+
+ tables[table_index++] = table;
+
+ /* Set all elements to -1 to mark them as uninitialized elements */
+ memset(table, -1, (uint32)total_size);
+ table->cur_size = module->tables[i].init_size;
+ table->max_size = max_size_fixed;
+
+ table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size);
+ }
+
+ bh_assert(table_index == table_count);
+ (void)module_inst;
+ return tables;
+#if WASM_ENABLE_MULTI_MODULE != 0
+fail:
+ wasm_runtime_free(tables);
+ return NULL;
+#endif
+}
+
+/**
+ * Destroy function instances.
+ */
+static void
+functions_deinstantiate(WASMFunctionInstance *functions, uint32 count)
+{
+ if (functions) {
+ wasm_runtime_free(functions);
+ }
+}
+
+/**
+ * Instantiate functions in a module.
+ */
+static WASMFunctionInstance *
+functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMImport *import;
+ uint32 i,
+ function_count = module->import_function_count + module->function_count;
+ uint64 total_size = sizeof(WASMFunctionInstance) * (uint64)function_count;
+ WASMFunctionInstance *functions, *function;
+
+ if (!(functions = runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ total_size = sizeof(void *) * (uint64)module->import_function_count;
+ if (total_size > 0
+ && !(module_inst->import_func_ptrs =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ wasm_runtime_free(functions);
+ return NULL;
+ }
+
+ /* instantiate functions from import section */
+ function = functions;
+ import = module->import_functions;
+ for (i = 0; i < module->import_function_count; i++, import++) {
+ function->is_import_func = true;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (import->u.function.import_module) {
+ function->import_module_inst = get_sub_module_inst(
+ module_inst, import->u.function.import_module);
+
+ if (function->import_module_inst) {
+ function->import_func_inst =
+ wasm_lookup_function(function->import_module_inst,
+ import->u.function.field_name, NULL);
+ }
+ }
+#endif /* WASM_ENABLE_MULTI_MODULE */
+ function->u.func_import = &import->u.function;
+ function->param_cell_num = import->u.function.func_type->param_cell_num;
+ function->ret_cell_num = import->u.function.func_type->ret_cell_num;
+ function->param_count =
+ (uint16)function->u.func_import->func_type->param_count;
+ function->param_types = function->u.func_import->func_type->types;
+ function->local_cell_num = 0;
+ function->local_count = 0;
+ function->local_types = NULL;
+
+ /* Copy the function pointer to current instance */
+ module_inst->import_func_ptrs[i] =
+ function->u.func_import->func_ptr_linked;
+
+ function++;
+ }
+
+ /* instantiate functions from function section */
+ for (i = 0; i < module->function_count; i++) {
+ function->is_import_func = false;
+ function->u.func = module->functions[i];
+
+ function->param_cell_num = function->u.func->param_cell_num;
+ function->ret_cell_num = function->u.func->ret_cell_num;
+ function->local_cell_num = function->u.func->local_cell_num;
+
+ function->param_count =
+ (uint16)function->u.func->func_type->param_count;
+ function->local_count = (uint16)function->u.func->local_count;
+ function->param_types = function->u.func->func_type->types;
+ function->local_types = function->u.func->local_types;
+
+ function->local_offsets = function->u.func->local_offsets;
+
+#if WASM_ENABLE_FAST_INTERP != 0
+ function->const_cell_num = function->u.func->const_cell_num;
+#endif
+
+ function++;
+ }
+ bh_assert((uint32)(function - functions) == function_count);
+
+#if WASM_ENABLE_FAST_JIT != 0
+ module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
+#endif
+
+ return functions;
+}
+
+/**
+ * Destroy global instances.
+ */
+static void
+globals_deinstantiate(WASMGlobalInstance *globals)
+{
+ if (globals)
+ wasm_runtime_free(globals);
+}
+
+static bool
+check_global_init_expr(const WASMModule *module, uint32 global_index,
+ char *error_buf, uint32 error_buf_size)
+{
+ if (global_index >= module->import_global_count + module->global_count) {
+ set_error_buf_v(error_buf, error_buf_size, "unknown global %d",
+ global_index);
+ return false;
+ }
+
+ /**
+ * Currently, constant expressions occurring as initializers of
+ * globals are further constrained in that contained global.get
+ * instructions are only allowed to refer to imported globals.
+ *
+ * And initializer expression cannot reference a mutable global.
+ */
+ if (global_index >= module->import_global_count
+ || (module->import_globals + global_index)->u.global.is_mutable) {
+ set_error_buf(error_buf, error_buf_size,
+ "constant expression required");
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Instantiate globals in a module.
+ */
+static WASMGlobalInstance *
+globals_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
+ char *error_buf, uint32 error_buf_size)
+{
+ WASMImport *import;
+ uint32 global_data_offset = 0;
+ uint32 i, global_count = module->import_global_count + module->global_count;
+ uint64 total_size = sizeof(WASMGlobalInstance) * (uint64)global_count;
+ WASMGlobalInstance *globals, *global;
+
+ if (!(globals = runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ /* instantiate globals from import section */
+ global = globals;
+ import = module->import_globals;
+ for (i = 0; i < module->import_global_count; i++, import++) {
+ WASMGlobalImport *global_import = &import->u.global;
+ global->type = global_import->type;
+ global->is_mutable = global_import->is_mutable;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (global_import->import_module) {
+ if (!(global->import_module_inst = get_sub_module_inst(
+ module_inst, global_import->import_module))) {
+ set_error_buf(error_buf, error_buf_size, "unknown global");
+ goto fail;
+ }
+
+ if (!(global->import_global_inst = wasm_lookup_global(
+ global->import_module_inst, global_import->field_name))) {
+ set_error_buf(error_buf, error_buf_size, "unknown global");
+ goto fail;
+ }
+
+ /* The linked global instance has been initialized, we
+ just need to copy the value. */
+ bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
+ &(global_import->import_global_linked->init_expr),
+ sizeof(WASMValue));
+ }
+ else
+#endif
+ {
+ /* native globals share their initial_values in one module */
+ bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
+ &(global_import->global_data_linked),
+ sizeof(WASMValue));
+ }
+#if WASM_ENABLE_FAST_JIT != 0
+ bh_assert(global_data_offset == global_import->data_offset);
+#endif
+ global->data_offset = global_data_offset;
+ global_data_offset += wasm_value_type_size(global->type);
+
+ global++;
+ }
+
+ /* instantiate globals from global section */
+ for (i = 0; i < module->global_count; i++) {
+ InitializerExpression *init_expr = &(module->globals[i].init_expr);
+
+ global->type = module->globals[i].type;
+ global->is_mutable = module->globals[i].is_mutable;
+#if WASM_ENABLE_FAST_JIT != 0
+ bh_assert(global_data_offset == module->globals[i].data_offset);
+#endif
+ global->data_offset = global_data_offset;
+ global_data_offset += wasm_value_type_size(global->type);
+
+ if (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
+ if (!check_global_init_expr(module, init_expr->u.global_index,
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ bh_memcpy_s(
+ &(global->initial_value), sizeof(WASMValue),
+ &(globals[init_expr->u.global_index].initial_value),
+ sizeof(globals[init_expr->u.global_index].initial_value));
+ }
+#if WASM_ENABLE_REF_TYPES != 0
+ else if (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST) {
+ global->initial_value.u32 = (uint32)NULL_REF;
+ }
+#endif
+ else {
+ bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
+ &(init_expr->u), sizeof(init_expr->u));
+ }
+ global++;
+ }
+
+ bh_assert((uint32)(global - globals) == global_count);
+ bh_assert(global_data_offset == module->global_data_size);
+ (void)module_inst;
+ return globals;
+fail:
+ wasm_runtime_free(globals);
+ return NULL;
+}
+
+/**
+ * Return export function count in module export section.
+ */
+static uint32
+get_export_count(const WASMModule *module, uint8 kind)
+{
+ WASMExport *export = module->exports;
+ uint32 count = 0, i;
+
+ for (i = 0; i < module->export_count; i++, export ++)
+ if (export->kind == kind)
+ count++;
+
+ return count;
+}
+
+/**
+ * Destroy export function instances.
+ */
+static void
+export_functions_deinstantiate(WASMExportFuncInstance *functions)
+{
+ if (functions)
+ wasm_runtime_free(functions);
+}
+
+/**
+ * Instantiate export functions in a module.
+ */
+static WASMExportFuncInstance *
+export_functions_instantiate(const WASMModule *module,
+ WASMModuleInstance *module_inst,
+ uint32 export_func_count, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMExportFuncInstance *export_funcs, *export_func;
+ WASMExport *export = module->exports;
+ uint32 i;
+ uint64 total_size =
+ sizeof(WASMExportFuncInstance) * (uint64)export_func_count;
+
+ if (!(export_func = export_funcs =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ for (i = 0; i < module->export_count; i++, export ++)
+ if (export->kind == EXPORT_KIND_FUNC) {
+ export_func->name = export->name;
+ export_func->function = &module_inst->e->functions[export->index];
+ export_func++;
+ }
+
+ bh_assert((uint32)(export_func - export_funcs) == export_func_count);
+ return export_funcs;
+}
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static void
+export_globals_deinstantiate(WASMExportGlobInstance *globals)
+{
+ if (globals)
+ wasm_runtime_free(globals);
+}
+
+static WASMExportGlobInstance *
+export_globals_instantiate(const WASMModule *module,
+ WASMModuleInstance *module_inst,
+ uint32 export_glob_count, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMExportGlobInstance *export_globals, *export_global;
+ WASMExport *export = module->exports;
+ uint32 i;
+ uint64 total_size =
+ sizeof(WASMExportGlobInstance) * (uint64)export_glob_count;
+
+ if (!(export_global = export_globals =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ for (i = 0; i < module->export_count; i++, export ++)
+ if (export->kind == EXPORT_KIND_GLOBAL) {
+ export_global->name = export->name;
+ export_global->global = &module_inst->e->globals[export->index];
+ export_global++;
+ }
+
+ bh_assert((uint32)(export_global - export_globals) == export_glob_count);
+ return export_globals;
+}
+#endif
+
+static WASMFunctionInstance *
+lookup_post_instantiate_func(WASMModuleInstance *module_inst,
+ const char *func_name)
+{
+ WASMFunctionInstance *func;
+ WASMType *func_type;
+
+ if (!(func = wasm_lookup_function(module_inst, func_name, NULL)))
+ /* Not found */
+ return NULL;
+
+ func_type = func->u.func->func_type;
+ if (!(func_type->param_count == 0 && func_type->result_count == 0))
+ /* Not a valid function type, ignore it */
+ return NULL;
+
+ return func;
+}
+
+static bool
+execute_post_instantiate_functions(WASMModuleInstance *module_inst,
+ bool is_sub_inst, WASMExecEnv *exec_env_main)
+{
+ WASMFunctionInstance *start_func = module_inst->e->start_function;
+ WASMFunctionInstance *initialize_func = NULL;
+ WASMFunctionInstance *post_inst_func = NULL;
+ WASMFunctionInstance *call_ctors_func = NULL;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASMModule *module = module_inst->module;
+#endif
+ WASMModuleInstanceCommon *module_inst_main = NULL;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+#endif
+ WASMExecEnv *exec_env = NULL, *exec_env_created = NULL;
+ bool ret = false;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ /*
+ * WASI reactor instances may assume that _initialize will be called by
+ * the environment at most once, and that none of their other exports
+ * are accessed before that call.
+ */
+ if (!is_sub_inst && module->import_wasi_api) {
+ initialize_func =
+ lookup_post_instantiate_func(module_inst, "_initialize");
+ }
+#endif
+
+ /* Execute possible "__post_instantiate" function if wasm app is
+ compiled by emsdk's early version */
+ if (!is_sub_inst) {
+ post_inst_func =
+ lookup_post_instantiate_func(module_inst, "__post_instantiate");
+ }
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ /* Only execute the memory init function for main instance since
+ the data segments will be dropped once initialized */
+ if (!is_sub_inst
+#if WASM_ENABLE_LIBC_WASI != 0
+ && !module->import_wasi_api
+#endif
+ ) {
+ call_ctors_func =
+ lookup_post_instantiate_func(module_inst, "__wasm_call_ctors");
+ }
+#endif
+
+ if (!start_func && !initialize_func && !post_inst_func
+ && !call_ctors_func) {
+ /* No post instantiation functions to call */
+ return true;
+ }
+
+ if (is_sub_inst) {
+ bh_assert(exec_env_main);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ bh_assert(exec_env_tls == exec_env_main);
+ (void)exec_env_tls;
+#endif
+ exec_env = exec_env_main;
+
+ /* Temporarily replace parent exec_env's module inst to current
+ module inst to avoid checking failure when calling the
+ wasm functions, and ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_main = exec_env_main->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ else {
+ /* Try using the existing exec_env */
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = exec_env_tls;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env)
+ exec_env = wasm_clusters_search_exec_env(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+ if (!exec_env) {
+ if (!(exec_env = exec_env_created = wasm_exec_env_create(
+ (WASMModuleInstanceCommon *)module_inst,
+ module_inst->default_wasm_stack_size))) {
+ wasm_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+ else {
+ /* Temporarily replace exec_env's module inst with current
+ module inst to ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_main = exec_env->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ }
+
+ /* Execute start function for both main insance and sub instance */
+ if (start_func && !wasm_call_function(exec_env, start_func, 0, NULL)) {
+ goto fail;
+ }
+
+ if (initialize_func
+ && !wasm_call_function(exec_env, initialize_func, 0, NULL)) {
+ goto fail;
+ }
+
+ if (post_inst_func
+ && !wasm_call_function(exec_env, post_inst_func, 0, NULL)) {
+ goto fail;
+ }
+
+ if (call_ctors_func
+ && !wasm_call_function(exec_env, call_ctors_func, 0, NULL)) {
+ goto fail;
+ }
+
+ ret = true;
+
+fail:
+ if (is_sub_inst) {
+ /* Restore the parent exec_env's module inst */
+ exec_env_main->module_inst = module_inst_main;
+ }
+ else {
+ if (module_inst_main)
+ /* Restore the existing exec_env's module inst */
+ exec_env->module_inst = module_inst_main;
+ if (exec_env_created)
+ wasm_exec_env_destroy(exec_env_created);
+ }
+
+ return ret;
+}
+
+static bool
+execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
+ WASMFunctionInstance *malloc_func,
+ WASMFunctionInstance *retain_func, uint32 size,
+ uint32 *p_result)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+#endif
+ WASMExecEnv *exec_env_created = NULL;
+ WASMModuleInstanceCommon *module_inst_old = NULL;
+ uint32 argv[2], argc;
+ bool ret;
+
+ argv[0] = size;
+ argc = 1;
+
+ /* if __retain is exported, then this module is compiled by
+ assemblyscript, the memory should be managed by as's runtime,
+ in this case we need to call the retain function after malloc
+ the memory */
+ if (retain_func) {
+ /* the malloc functino from assemblyscript is:
+ function __new(size: usize, id: u32)
+ id = 0 means this is an ArrayBuffer object */
+ argv[1] = 0;
+ argc = 2;
+ }
+
+ if (exec_env) {
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env_tls) {
+ bh_assert(exec_env_tls == exec_env);
+ }
+#endif
+ bh_assert(exec_env->module_inst
+ == (WASMModuleInstanceCommon *)module_inst);
+ }
+ else {
+ /* Try using the existing exec_env */
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = exec_env_tls;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env)
+ exec_env = wasm_clusters_search_exec_env(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+ if (!exec_env) {
+ if (!(exec_env = exec_env_created = wasm_exec_env_create(
+ (WASMModuleInstanceCommon *)module_inst,
+ module_inst->default_wasm_stack_size))) {
+ wasm_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+ else {
+ /* Temporarily replace exec_env's module inst with current
+ module inst to ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_old = exec_env->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ }
+
+ ret = wasm_call_function(exec_env, malloc_func, argc, argv);
+
+ if (retain_func && ret)
+ ret = wasm_call_function(exec_env, retain_func, 1, argv);
+
+ if (module_inst_old)
+ /* Restore the existing exec_env's module inst */
+ exec_env->module_inst = module_inst_old;
+
+ if (exec_env_created)
+ wasm_exec_env_destroy(exec_env_created);
+
+ if (ret)
+ *p_result = argv[0];
+ return ret;
+}
+
+static bool
+execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
+ WASMFunctionInstance *free_func, uint32 offset)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+#endif
+ WASMExecEnv *exec_env_created = NULL;
+ WASMModuleInstanceCommon *module_inst_old = NULL;
+ uint32 argv[2];
+ bool ret;
+
+ argv[0] = offset;
+
+ if (exec_env) {
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env_tls) {
+ bh_assert(exec_env_tls == exec_env);
+ }
+#endif
+ bh_assert(exec_env->module_inst
+ == (WASMModuleInstanceCommon *)module_inst);
+ }
+ else {
+ /* Try using the existing exec_env */
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ exec_env = exec_env_tls;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+ if (!exec_env)
+ exec_env = wasm_clusters_search_exec_env(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+ if (!exec_env) {
+ if (!(exec_env = exec_env_created = wasm_exec_env_create(
+ (WASMModuleInstanceCommon *)module_inst,
+ module_inst->default_wasm_stack_size))) {
+ wasm_set_exception(module_inst, "allocate memory failed");
+ return false;
+ }
+ }
+ else {
+ /* Temporarily replace exec_env's module inst with current
+ module inst to ensure that the exec_env's module inst
+ is the correct one. */
+ module_inst_old = exec_env->module_inst;
+ exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
+ }
+ }
+
+ ret = wasm_call_function(exec_env, free_func, 1, argv);
+
+ if (module_inst_old)
+ /* Restore the existing exec_env's module inst */
+ exec_env->module_inst = module_inst_old;
+
+ if (exec_env_created)
+ wasm_exec_env_destroy(exec_env_created);
+
+ return ret;
+}
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static bool
+sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
+ uint32 stack_size, uint32 heap_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ bh_list *sub_module_inst_list = module_inst->e->sub_module_inst_list;
+ WASMRegisteredModule *sub_module_list_node =
+ bh_list_first_elem(module->import_module_list);
+
+ while (sub_module_list_node) {
+ WASMSubModInstNode *sub_module_inst_list_node = NULL;
+ WASMModule *sub_module = (WASMModule *)sub_module_list_node->module;
+ WASMModuleInstance *sub_module_inst = NULL;
+
+ sub_module_inst =
+ wasm_instantiate(sub_module, false, NULL, stack_size, heap_size,
+ error_buf, error_buf_size);
+ if (!sub_module_inst) {
+ LOG_DEBUG("instantiate %s failed",
+ sub_module_list_node->module_name);
+ goto failed;
+ }
+
+ sub_module_inst_list_node = runtime_malloc(sizeof(WASMSubModInstNode),
+ error_buf, error_buf_size);
+ if (!sub_module_inst_list_node) {
+ LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
+ sizeof(WASMSubModInstNode));
+ goto failed;
+ }
+
+ sub_module_inst_list_node->module_inst = sub_module_inst;
+ sub_module_inst_list_node->module_name =
+ sub_module_list_node->module_name;
+ bh_list_status ret =
+ bh_list_insert(sub_module_inst_list, sub_module_inst_list_node);
+ bh_assert(BH_LIST_SUCCESS == ret);
+ (void)ret;
+
+ sub_module_list_node = bh_list_elem_next(sub_module_list_node);
+
+ continue;
+ failed:
+ if (sub_module_inst_list_node) {
+ bh_list_remove(sub_module_inst_list, sub_module_inst_list_node);
+ wasm_runtime_free(sub_module_inst_list_node);
+ }
+
+ if (sub_module_inst)
+ wasm_deinstantiate(sub_module_inst, false);
+ return false;
+ }
+
+ return true;
+}
+
+static void
+sub_module_deinstantiate(WASMModuleInstance *module_inst)
+{
+ bh_list *list = module_inst->e->sub_module_inst_list;
+ WASMSubModInstNode *node = bh_list_first_elem(list);
+ while (node) {
+ WASMSubModInstNode *next_node = bh_list_elem_next(node);
+ bh_list_remove(list, node);
+ wasm_deinstantiate(node->module_inst, false);
+ wasm_runtime_free(node);
+ node = next_node;
+ }
+}
+#endif
+
+static bool
+check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
+ uint32 error_buf_size)
+{
+ WASMModule *module = module_inst->module;
+ uint32 i;
+
+ for (i = 0; i < module->import_function_count; i++) {
+ WASMFunctionImport *func =
+ &((module->import_functions + i)->u.function);
+ if (!func->func_ptr_linked
+#if WASM_ENABLE_MULTI_MODULE != 0
+ && !func->import_func_linked
+#endif
+ ) {
+#if WASM_ENABLE_WAMR_COMPILER == 0
+ LOG_WARNING("warning: failed to link import function (%s, %s)",
+ func->module_name, func->field_name);
+ /* will throw exception only if calling */
+#else
+ /* do nothing to avoid confused message */
+#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */
+ }
+ }
+
+ for (i = 0; i < module->import_global_count; i++) {
+ WASMGlobalImport *global = &((module->import_globals + i)->u.global);
+ if (!global->is_linked) {
+#if WASM_ENABLE_SPEC_TEST != 0
+ set_error_buf(error_buf, error_buf_size,
+ "unknown import or incompatible import type");
+ return false;
+#else
+#if WASM_ENABLE_WAMR_COMPILER == 0
+ set_error_buf_v(error_buf, error_buf_size,
+ "failed to link import global (%s, %s)",
+ global->module_name, global->field_name);
+ return false;
+#else
+ /* do nothing to avoid confused message */
+#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */
+#endif /* WASM_ENABLE_SPEC_TEST != 0 */
+ }
+ }
+
+ return true;
+}
+
+#if WASM_ENABLE_JIT != 0
+static bool
+init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module,
+ char *error_buf, uint32 error_buf_size)
+{
+ uint32 i;
+ void **func_ptrs;
+ uint64 total_size = (uint64)sizeof(void *) * module_inst->e->function_count;
+
+ /* Allocate memory */
+ if (!(func_ptrs = module_inst->func_ptrs =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ /* Set import function pointers */
+ for (i = 0; i < module->import_function_count; i++, func_ptrs++) {
+ WASMFunctionImport *import_func =
+ &module->import_functions[i].u.function;
+ /* TODO: handle multi module */
+ *func_ptrs = import_func->func_ptr_linked;
+ }
+
+ /* The defined function pointers will be set in
+ wasm_runtime_set_running_mode, no need to set them here */
+ return true;
+}
+#endif /* end of WASM_ENABLE_JIT != 0 */
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+static uint32
+get_smallest_type_idx(WASMModule *module, WASMType *func_type)
+{
+ uint32 i;
+
+ for (i = 0; i < module->type_count; i++) {
+ if (func_type == module->types[i])
+ return i;
+ }
+
+ bh_assert(0);
+ return -1;
+}
+
+static bool
+init_func_type_indexes(WASMModuleInstance *module_inst, char *error_buf,
+ uint32 error_buf_size)
+{
+ uint32 i;
+ uint64 total_size = (uint64)sizeof(uint32) * module_inst->e->function_count;
+
+ /* Allocate memory */
+ if (!(module_inst->func_type_indexes =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return false;
+ }
+
+ for (i = 0; i < module_inst->e->function_count; i++) {
+ WASMFunctionInstance *func_inst = module_inst->e->functions + i;
+ WASMType *func_type = func_inst->is_import_func
+ ? func_inst->u.func_import->func_type
+ : func_inst->u.func->func_type;
+ module_inst->func_type_indexes[i] =
+ get_smallest_type_idx(module_inst->module, func_type);
+ }
+
+ return true;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
+
+static bool
+set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode,
+ bool first_time_set)
+{
+ WASMModule *module = module_inst->module;
+
+ if (running_mode == Mode_Default) {
+#if WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT == 0
+ running_mode = Mode_Interp;
+#elif WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT == 0
+ running_mode = Mode_Fast_JIT;
+#elif WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT != 0
+ running_mode = Mode_LLVM_JIT;
+#else /* WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 */
+#if WASM_ENABLE_LAZY_JIT == 0
+ running_mode = Mode_LLVM_JIT;
+#else
+ running_mode = Mode_Multi_Tier_JIT;
+#endif
+#endif
+ }
+
+ if (!wasm_runtime_is_running_mode_supported(running_mode))
+ return false;
+
+#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0) /* No possible multi-tier JIT */
+ module_inst->e->running_mode = running_mode;
+
+ if (running_mode == Mode_Interp) {
+ /* Do nothing for Mode_Interp */
+ }
+ else if (running_mode == Mode_Fast_JIT) {
+ /* Do nothing for Mode_Fast_JIT since
+ module_inst->fast_jit_func_ptrs is same as
+ module->fast_jit_func_ptrs */
+ }
+#if WASM_ENABLE_JIT != 0
+ else if (running_mode == Mode_LLVM_JIT) {
+ /* Set defined function pointers */
+ bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
+ sizeof(void *) * module->function_count, module->func_ptrs,
+ sizeof(void *) * module->function_count);
+ }
+#endif
+ else {
+ bh_assert(0);
+ }
+#else /* Possible multi-tier JIT */
+ os_mutex_lock(&module->instance_list_lock);
+
+ module_inst->e->running_mode = running_mode;
+
+ if (running_mode == Mode_Interp) {
+ /* Do nothing for Mode_Interp */
+ }
+#if WASM_ENABLE_FAST_JIT != 0
+ else if (running_mode == Mode_Fast_JIT) {
+ JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+ uint32 i;
+
+ /* Allocate memory for fast_jit_func_ptrs if needed */
+ if (!module_inst->fast_jit_func_ptrs
+ || module_inst->fast_jit_func_ptrs == module->fast_jit_func_ptrs) {
+ uint64 total_size = (uint64)sizeof(void *) * module->function_count;
+ if (!(module_inst->fast_jit_func_ptrs =
+ runtime_malloc(total_size, NULL, 0))) {
+ os_mutex_unlock(&module->instance_list_lock);
+ return false;
+ }
+ }
+
+ for (i = 0; i < module->function_count; i++) {
+ if (module->functions[i]->fast_jit_jitted_code) {
+ /* current fast jit function has been compiled */
+ module_inst->fast_jit_func_ptrs[i] =
+ module->functions[i]->fast_jit_jitted_code;
+ }
+ else {
+ module_inst->fast_jit_func_ptrs[i] =
+ jit_globals->compile_fast_jit_and_then_call;
+ }
+ }
+ }
+#endif
+#if WASM_ENABLE_JIT != 0
+ else if (running_mode == Mode_LLVM_JIT) {
+ void **llvm_jit_func_ptrs;
+ uint32 i;
+
+ /* Notify backend threads to start llvm jit compilation */
+ module->enable_llvm_jit_compilation = true;
+
+ /* Wait until llvm jit finishes initialization */
+ os_mutex_lock(&module->tierup_wait_lock);
+ while (!module->llvm_jit_inited) {
+ os_cond_reltimedwait(&module->tierup_wait_cond,
+ &module->tierup_wait_lock, 10000);
+ if (module->orcjit_stop_compiling) {
+ /* init_llvm_jit_functions_stage2 failed */
+ os_mutex_unlock(&module->tierup_wait_lock);
+ os_mutex_unlock(&module->instance_list_lock);
+ return false;
+ }
+ }
+ os_mutex_unlock(&module->tierup_wait_lock);
+
+ llvm_jit_func_ptrs =
+ module_inst->func_ptrs + module->import_function_count;
+ for (i = 0; i < module->function_count; i++) {
+ llvm_jit_func_ptrs[i] = module->functions[i]->llvm_jit_func_ptr;
+ }
+ }
+#endif
+ else if (running_mode == Mode_Multi_Tier_JIT) {
+ /* Notify backend threads to start llvm jit compilation */
+ module->enable_llvm_jit_compilation = true;
+
+ /* Free fast_jit_func_ptrs if it is allocated before */
+ if (module_inst->fast_jit_func_ptrs
+ && module_inst->fast_jit_func_ptrs != module->fast_jit_func_ptrs) {
+ wasm_runtime_free(module_inst->fast_jit_func_ptrs);
+ }
+ module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
+
+ /* Copy all llvm jit func ptrs from the module */
+ bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
+ sizeof(void *) * module->function_count, module->func_ptrs,
+ sizeof(void *) * module->function_count);
+ }
+ else {
+ bh_assert(0);
+ }
+
+ /* Add module instance into module's instance list if not added */
+ if (first_time_set) {
+ bool found = false;
+ WASMModuleInstance *node = module->instance_list;
+
+ while (node) {
+ if (node == module_inst) {
+ found = true;
+ break;
+ }
+ node = node->e->next;
+ }
+
+ if (!found) {
+ module_inst->e->next = module->instance_list;
+ module->instance_list = module_inst;
+ }
+ }
+
+ os_mutex_unlock(&module->instance_list_lock);
+#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0) */
+
+ (void)module;
+ return true;
+}
+
+bool
+wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
+{
+ return set_running_mode(module_inst, running_mode, false);
+}
+
+/**
+ * Instantiate module
+ */
+WASMModuleInstance *
+wasm_instantiate(WASMModule *module, bool is_sub_inst,
+ WASMExecEnv *exec_env_main, uint32 stack_size,
+ uint32 heap_size, char *error_buf, uint32 error_buf_size)
+{
+ WASMModuleInstance *module_inst;
+ WASMGlobalInstance *globals = NULL, *global;
+ WASMTableInstance *first_table;
+ uint32 global_count, i;
+ uint32 base_offset, length, extra_info_offset;
+ uint32 module_inst_struct_size =
+ offsetof(WASMModuleInstance, global_table_data.bytes);
+ uint64 module_inst_mem_inst_size;
+ uint64 total_size, table_size = 0;
+ uint8 *global_data, *global_data_end;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ bool ret = false;
+#endif
+
+ if (!module)
+ return NULL;
+
+ /* Check the heap size */
+ heap_size = align_uint(heap_size, 8);
+ if (heap_size > APP_HEAP_SIZE_MAX)
+ heap_size = APP_HEAP_SIZE_MAX;
+
+ module_inst_mem_inst_size =
+ (uint64)sizeof(WASMMemoryInstance)
+ * (module->import_memory_count + module->memory_count);
+
+#if WASM_ENABLE_JIT != 0
+ /* If the module dosen't have memory, reserve one mem_info space
+ with empty content to align with llvm jit compiler */
+ if (module_inst_mem_inst_size == 0)
+ module_inst_mem_inst_size = (uint64)sizeof(WASMMemoryInstance);
+#endif
+
+ /* Size of module inst, memory instances and global data */
+ total_size = (uint64)module_inst_struct_size + module_inst_mem_inst_size
+ + module->global_data_size;
+
+ /* Calculate the size of table data */
+ for (i = 0; i < module->import_table_count; i++) {
+ WASMTableImport *import_table = &module->import_tables[i].u.table;
+ table_size += offsetof(WASMTableInstance, elems);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ table_size += (uint64)sizeof(uint32) * import_table->max_size;
+#else
+ table_size += (uint64)sizeof(uint32)
+ * (import_table->possible_grow ? import_table->max_size
+ : import_table->init_size);
+#endif
+ }
+ for (i = 0; i < module->table_count; i++) {
+ WASMTable *table = module->tables + i;
+ table_size += offsetof(WASMTableInstance, elems);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ table_size += (uint64)sizeof(uint32) * table->max_size;
+#else
+ table_size +=
+ (uint64)sizeof(uint32)
+ * (table->possible_grow ? table->max_size : table->init_size);
+#endif
+ }
+ total_size += table_size;
+
+ /* The offset of WASMModuleInstanceExtra, make it 8-byte aligned */
+ total_size = (total_size + 7LL) & ~7LL;
+ extra_info_offset = (uint32)total_size;
+ total_size += sizeof(WASMModuleInstanceExtra);
+
+ /* Allocate the memory for module instance with memory instances,
+ global data, table data appended at the end */
+ if (!(module_inst =
+ runtime_malloc(total_size, error_buf, error_buf_size))) {
+ return NULL;
+ }
+
+ module_inst->module_type = Wasm_Module_Bytecode;
+ module_inst->module = module;
+ module_inst->e =
+ (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ module_inst->e->sub_module_inst_list =
+ &module_inst->e->sub_module_inst_list_head;
+ ret = sub_module_instantiate(module, module_inst, stack_size, heap_size,
+ error_buf, error_buf_size);
+ if (!ret) {
+ LOG_DEBUG("build a sub module list failed");
+ goto fail;
+ }
+#endif
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (!(module_inst->frames = runtime_malloc((uint64)sizeof(Vector),
+ error_buf, error_buf_size))) {
+ goto fail;
+ }
+#endif
+
+ /* Instantiate global firstly to get the mutable data size */
+ global_count = module->import_global_count + module->global_count;
+ if (global_count
+ && !(globals = globals_instantiate(module, module_inst, error_buf,
+ error_buf_size))) {
+ goto fail;
+ }
+ module_inst->e->global_count = global_count;
+ module_inst->e->globals = globals;
+ module_inst->global_data = (uint8 *)module_inst + module_inst_struct_size
+ + module_inst_mem_inst_size;
+ module_inst->global_data_size = module->global_data_size;
+ first_table = (WASMTableInstance *)(module_inst->global_data
+ + module->global_data_size);
+
+ module_inst->memory_count =
+ module->import_memory_count + module->memory_count;
+ module_inst->table_count = module->import_table_count + module->table_count;
+ module_inst->e->function_count =
+ module->import_function_count + module->function_count;
+
+ /* export */
+ module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ module_inst->export_table_count =
+ get_export_count(module, EXPORT_KIND_TABLE);
+ module_inst->export_memory_count =
+ get_export_count(module, EXPORT_KIND_MEMORY);
+ module_inst->export_global_count =
+ get_export_count(module, EXPORT_KIND_GLOBAL);
+#endif
+
+ /* Instantiate memories/tables/functions */
+ if ((module_inst->memory_count > 0
+ && !(module_inst->memories = memories_instantiate(
+ module, module_inst, heap_size, error_buf, error_buf_size)))
+ || (module_inst->table_count > 0
+ && !(module_inst->tables =
+ tables_instantiate(module, module_inst, first_table,
+ error_buf, error_buf_size)))
+ || (module_inst->e->function_count > 0
+ && !(module_inst->e->functions = functions_instantiate(
+ module, module_inst, error_buf, error_buf_size)))
+ || (module_inst->export_func_count > 0
+ && !(module_inst->export_functions = export_functions_instantiate(
+ module, module_inst, module_inst->export_func_count,
+ error_buf, error_buf_size)))
+#if WASM_ENABLE_MULTI_MODULE != 0
+ || (module_inst->export_global_count > 0
+ && !(module_inst->export_globals = export_globals_instantiate(
+ module, module_inst, module_inst->export_global_count,
+ error_buf, error_buf_size)))
+#endif
+#if WASM_ENABLE_JIT != 0
+ || (module_inst->e->function_count > 0
+ && !init_func_ptrs(module_inst, module, error_buf, error_buf_size))
+#endif
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ || (module_inst->e->function_count > 0
+ && !init_func_type_indexes(module_inst, error_buf, error_buf_size))
+#endif
+ ) {
+ goto fail;
+ }
+
+ if (global_count > 0) {
+ /* Initialize the global data */
+ global_data = module_inst->global_data;
+ global_data_end = global_data + module->global_data_size;
+ global = globals;
+ for (i = 0; i < global_count; i++, global++) {
+ switch (global->type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+#if WASM_ENABLE_REF_TYPES != 0
+ case VALUE_TYPE_FUNCREF:
+ case VALUE_TYPE_EXTERNREF:
+#endif
+ *(int32 *)global_data = global->initial_value.i32;
+ global_data += sizeof(int32);
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ bh_memcpy_s(global_data,
+ (uint32)(global_data_end - global_data),
+ &global->initial_value.i64, sizeof(int64));
+ global_data += sizeof(int64);
+ break;
+#if WASM_ENABLE_SIMD != 0
+ case VALUE_TYPE_V128:
+ bh_memcpy_s(global_data, (uint32)sizeof(V128),
+ &global->initial_value.v128, sizeof(V128));
+ global_data += sizeof(V128);
+ break;
+#endif
+ default:
+ bh_assert(0);
+ }
+ }
+ bh_assert(global_data == global_data_end);
+ }
+
+ if (!check_linked_symbol(module_inst, error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ /* Initialize the memory data with data segment section */
+ for (i = 0; i < module->data_seg_count; i++) {
+ WASMMemoryInstance *memory = NULL;
+ uint8 *memory_data = NULL;
+ uint32 memory_size = 0;
+ WASMDataSeg *data_seg = module->data_segments[i];
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+ if (data_seg->is_passive)
+ continue;
+#endif
+
+ /* has check it in loader */
+ memory = module_inst->memories[data_seg->memory_index];
+ bh_assert(memory);
+
+ memory_data = memory->memory_data;
+ memory_size = memory->num_bytes_per_page * memory->cur_page_count;
+ bh_assert(memory_data || memory_size == 0);
+
+ bh_assert(data_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST
+ || 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) {
+ if (!check_global_init_expr(module,
+ data_seg->base_offset.u.global_index,
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ if (!globals
+ || globals[data_seg->base_offset.u.global_index].type
+ != VALUE_TYPE_I32) {
+ set_error_buf(error_buf, error_buf_size,
+ "data segment does not fit");
+ goto fail;
+ }
+
+ base_offset =
+ globals[data_seg->base_offset.u.global_index].initial_value.i32;
+ }
+ else {
+ base_offset = (uint32)data_seg->base_offset.u.i32;
+ }
+
+ /* check offset */
+ if (base_offset > memory_size) {
+ LOG_DEBUG("base_offset(%d) > memory_size(%d)", base_offset,
+ memory_size);
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds memory access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "data segment does not fit");
+#endif
+ goto fail;
+ }
+
+ /* check offset + length(could be zero) */
+ length = data_seg->data_length;
+ if (base_offset + length > memory_size) {
+ LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)",
+ base_offset, length, memory_size);
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds memory access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "data segment does not fit");
+#endif
+ goto fail;
+ }
+
+ if (memory_data) {
+ bh_memcpy_s(memory_data + base_offset, memory_size - base_offset,
+ data_seg->data, length);
+ }
+ }
+
+ /* Initialize the table data with table segment section */
+ for (i = 0; module_inst->table_count > 0 && i < module->table_seg_count;
+ i++) {
+ WASMTableSeg *table_seg = module->table_segments + i;
+ /* has check it in loader */
+ WASMTableInstance *table = module_inst->tables[table_seg->table_index];
+ uint32 *table_data;
+#if WASM_ENABLE_REF_TYPES != 0
+ uint8 tbl_elem_type;
+ uint32 tbl_init_size, tbl_max_size;
+#endif
+
+ bh_assert(table);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ (void)wasm_runtime_get_table_inst_elem_type(
+ (WASMModuleInstanceCommon *)module_inst, table_seg->table_index,
+ &tbl_elem_type, &tbl_init_size, &tbl_max_size);
+ if (tbl_elem_type != VALUE_TYPE_FUNCREF
+ && tbl_elem_type != VALUE_TYPE_EXTERNREF) {
+ set_error_buf(error_buf, error_buf_size,
+ "elements segment does not fit");
+ goto fail;
+ }
+ (void)tbl_init_size;
+ (void)tbl_max_size;
+#endif
+
+ table_data = table->elems;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (table_seg->table_index < module->import_table_count
+ && module_inst->e->table_insts_linked[table_seg->table_index]) {
+ table_data =
+ module_inst->e->table_insts_linked[table_seg->table_index]
+ ->elems;
+ }
+#endif
+ bh_assert(table_data);
+
+#if WASM_ENABLE_REF_TYPES != 0
+ if (!wasm_elem_is_active(table_seg->mode))
+ continue;
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+ bh_assert(table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST
+ || table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_GET_GLOBAL
+ || table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_FUNCREF_CONST
+ || table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_REFNULL_CONST);
+#else
+ bh_assert(table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_I32_CONST
+ || table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_GET_GLOBAL);
+#endif
+
+ /* init vec(funcidx) or vec(expr) */
+ if (table_seg->base_offset.init_expr_type
+ == INIT_EXPR_TYPE_GET_GLOBAL) {
+ if (!check_global_init_expr(module,
+ table_seg->base_offset.u.global_index,
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+
+ if (!globals
+ || globals[table_seg->base_offset.u.global_index].type
+ != VALUE_TYPE_I32) {
+ set_error_buf(error_buf, error_buf_size,
+ "elements segment does not fit");
+ goto fail;
+ }
+
+ table_seg->base_offset.u.i32 =
+ globals[table_seg->base_offset.u.global_index]
+ .initial_value.i32;
+ }
+
+ /* check offset since length might negative */
+ if ((uint32)table_seg->base_offset.u.i32 > table->cur_size) {
+ LOG_DEBUG("base_offset(%d) > table->cur_size(%d)",
+ table_seg->base_offset.u.i32, table->cur_size);
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds table access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "elements segment does not fit");
+#endif
+ goto fail;
+ }
+
+ /* check offset + length(could be zero) */
+ length = table_seg->function_count;
+ if ((uint32)table_seg->base_offset.u.i32 + length > table->cur_size) {
+ LOG_DEBUG("base_offset(%d) + length(%d)> table->cur_size(%d)",
+ table_seg->base_offset.u.i32, length, table->cur_size);
+#if WASM_ENABLE_REF_TYPES != 0
+ set_error_buf(error_buf, error_buf_size,
+ "out of bounds table access");
+#else
+ set_error_buf(error_buf, error_buf_size,
+ "elements segment does not fit");
+#endif
+ goto fail;
+ }
+
+ /**
+ * Check function index in the current module inst for now.
+ * will check the linked table inst owner in future.
+ * so loader check is enough
+ */
+ bh_memcpy_s(
+ table_data + table_seg->base_offset.u.i32,
+ (uint32)((table->cur_size - (uint32)table_seg->base_offset.u.i32)
+ * sizeof(uint32)),
+ table_seg->func_indexes, (uint32)(length * sizeof(uint32)));
+ }
+
+ /* Initialize the thread related data */
+ if (stack_size == 0)
+ stack_size = DEFAULT_WASM_STACK_SIZE;
+#if WASM_ENABLE_SPEC_TEST != 0
+ if (stack_size < 128 * 1024)
+ stack_size = 128 * 1024;
+#endif
+ module_inst->default_wasm_stack_size = stack_size;
+
+ if (module->malloc_function != (uint32)-1) {
+ module_inst->e->malloc_function =
+ &module_inst->e->functions[module->malloc_function];
+ }
+
+ if (module->free_function != (uint32)-1) {
+ module_inst->e->free_function =
+ &module_inst->e->functions[module->free_function];
+ }
+
+ if (module->retain_function != (uint32)-1) {
+ module_inst->e->retain_function =
+ &module_inst->e->functions[module->retain_function];
+ }
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ /* The sub-instance will get the wasi_ctx from main-instance */
+ if (!is_sub_inst) {
+ 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.addr_pool, module->wasi_args.addr_count,
+ module->wasi_args.ns_lookup_pool,
+ module->wasi_args.ns_lookup_count, module->wasi_args.argv,
+ module->wasi_args.argc, module->wasi_args.stdio[0],
+ module->wasi_args.stdio[1], module->wasi_args.stdio[2],
+ error_buf, error_buf_size)) {
+ goto fail;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_WASI_NN != 0
+ if (!is_sub_inst) {
+ if (!(module_inst->e->wasi_nn_ctx = wasi_nn_initialize())) {
+ set_error_buf(error_buf, error_buf_size,
+ "wasi nn initialization failed");
+ goto fail;
+ }
+ }
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ if (!is_sub_inst) {
+ /* Add module instance into module's instance list */
+ os_mutex_lock(&module->instance_list_lock);
+ if (module->instance_list) {
+ LOG_WARNING(
+ "warning: multiple instances referencing to the same module "
+ "may cause unexpected behaviour during debugging");
+ }
+ module_inst->e->next = module->instance_list;
+ module->instance_list = module_inst;
+ os_mutex_unlock(&module->instance_list_lock);
+ }
+#endif
+
+ /* Set running mode before executing wasm functions */
+ if (!set_running_mode(module_inst, wasm_runtime_get_default_running_mode(),
+ true)) {
+ set_error_buf(error_buf, error_buf_size,
+ "set instance running mode failed");
+ goto fail;
+ }
+
+ if (module->start_function != (uint32)-1) {
+ /* TODO: fix start function can be import function issue */
+ if (module->start_function >= module->import_function_count)
+ module_inst->e->start_function =
+ &module_inst->e->functions[module->start_function];
+ }
+
+ if (!execute_post_instantiate_functions(module_inst, is_sub_inst,
+ exec_env_main)) {
+ set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
+ goto fail;
+ }
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ wasm_runtime_dump_module_inst_mem_consumption(
+ (WASMModuleInstanceCommon *)module_inst);
+#endif
+
+ (void)global_data_end;
+ return module_inst;
+
+fail:
+ wasm_deinstantiate(module_inst, false);
+ return NULL;
+}
+
+void
+wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
+{
+ if (!module_inst)
+ return;
+
+ if (module_inst->exec_env_singleton) {
+ /* wasm_exec_env_destroy will call
+ wasm_cluster_wait_for_all_except_self to wait for other
+ threads, so as to destroy their exec_envs and module
+ instances first, and avoid accessing the shared resources
+ of current module instance after it is deinstantiated. */
+ wasm_exec_env_destroy(module_inst->exec_env_singleton);
+ }
+
+#if WASM_ENABLE_DEBUG_INTERP != 0 \
+ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0)
+ /* Remove instance from module's instance list before freeing
+ func_ptrs and fast_jit_func_ptrs of the instance, to avoid
+ accessing the freed memory in the jit backend compilation
+ threads */
+ {
+ WASMModule *module = module_inst->module;
+ WASMModuleInstance *instance_prev = NULL, *instance;
+ os_mutex_lock(&module->instance_list_lock);
+
+ instance = module->instance_list;
+ while (instance) {
+ if (instance == module_inst) {
+ if (!instance_prev)
+ module->instance_list = instance->e->next;
+ else
+ instance_prev->e->next = instance->e->next;
+ break;
+ }
+ instance_prev = instance;
+ instance = instance->e->next;
+ }
+
+ os_mutex_unlock(&module->instance_list_lock);
+ }
+#endif
+
+#if WASM_ENABLE_JIT != 0
+ if (module_inst->func_ptrs)
+ wasm_runtime_free(module_inst->func_ptrs);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0
+ if (module_inst->fast_jit_func_ptrs
+ && module_inst->fast_jit_func_ptrs
+ != module_inst->module->fast_jit_func_ptrs)
+ wasm_runtime_free(module_inst->fast_jit_func_ptrs);
+#endif
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
+ if (module_inst->func_type_indexes)
+ wasm_runtime_free(module_inst->func_type_indexes);
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ sub_module_deinstantiate(module_inst);
+#endif
+
+#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. */
+ /* Only destroy wasi ctx in the main module instance */
+ if (!is_sub_inst)
+ wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
+#endif
+
+ if (module_inst->memory_count > 0)
+ memories_deinstantiate(module_inst, module_inst->memories,
+ module_inst->memory_count);
+
+ if (module_inst->import_func_ptrs) {
+ wasm_runtime_free(module_inst->import_func_ptrs);
+ }
+
+ tables_deinstantiate(module_inst);
+ functions_deinstantiate(module_inst->e->functions,
+ module_inst->e->function_count);
+ globals_deinstantiate(module_inst->e->globals);
+ export_functions_deinstantiate(module_inst->export_functions);
+#if WASM_ENABLE_MULTI_MODULE != 0
+ export_globals_deinstantiate(module_inst->export_globals);
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+ wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst);
+#endif
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (module_inst->frames) {
+ bh_vector_destroy(module_inst->frames);
+ wasm_runtime_free(module_inst->frames);
+ module_inst->frames = NULL;
+ }
+#endif
+
+ if (module_inst->e->c_api_func_imports)
+ wasm_runtime_free(module_inst->e->c_api_func_imports);
+
+#if WASM_ENABLE_WASI_NN != 0
+ if (!is_sub_inst) {
+ WASINNContext *wasi_nn_ctx = module_inst->e->wasi_nn_ctx;
+ if (wasi_nn_ctx)
+ wasi_nn_destroy(wasi_nn_ctx);
+ }
+#endif
+
+ wasm_runtime_free(module_inst);
+}
+
+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))
+ return module_inst->export_functions[i].function;
+ (void)signature;
+ return NULL;
+}
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+WASMGlobalInstance *
+wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name)
+{
+ uint32 i;
+ for (i = 0; i < module_inst->export_global_count; i++)
+ if (!strcmp(module_inst->export_globals[i].name, name))
+ return module_inst->export_globals[i].global;
+ return NULL;
+}
+
+WASMMemoryInstance *
+wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name)
+{
+ /**
+ * using a strong assumption that one module instance only has
+ * one memory instance
+ */
+ (void)module_inst->export_memories;
+ return module_inst->memories[0];
+}
+
+WASMTableInstance *
+wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
+{
+ /**
+ * using a strong assumption that one module instance only has
+ * one table instance
+ */
+ (void)module_inst->export_tables;
+ return module_inst->tables[0];
+}
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+
+static void
+call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env,
+ WASMFunctionInstance *function, unsigned argc,
+ uint32 argv[])
+{
+ WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
+ WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
+ uint32 page_size = os_getpagesize();
+ uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+ WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
+ uint8 *prev_top = exec_env->wasm_stack.s.top;
+#ifdef BH_PLATFORM_WINDOWS
+ int result;
+ bool has_exception;
+ char exception[EXCEPTION_BUF_LEN];
+#endif
+ bool ret = true;
+
+ /* Check native stack overflow firstly to ensure we have enough
+ native stack to run the following codes before actually calling
+ the aot function in invokeNative function. */
+ RECORD_STACK_USAGE(exec_env, (uint8 *)&exec_env_tls);
+ if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary
+ + page_size * (guard_page_count + 1)) {
+ wasm_set_exception(module_inst, "native stack overflow");
+ return;
+ }
+
+ if (exec_env_tls && (exec_env_tls != exec_env)) {
+ wasm_set_exception(module_inst, "invalid exec env");
+ return;
+ }
+
+ if (!os_thread_signal_inited()) {
+ wasm_set_exception(module_inst, "thread signal env not inited");
+ return;
+ }
+
+ wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
+
+ wasm_runtime_set_exec_env_tls(exec_env);
+ if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
+#ifndef BH_PLATFORM_WINDOWS
+ wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv);
+#else
+ __try {
+ wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv);
+ } __except (wasm_copy_exception(module_inst, NULL)
+ ? EXCEPTION_EXECUTE_HANDLER
+ : EXCEPTION_CONTINUE_SEARCH) {
+ /* exception was thrown in wasm_exception_handler */
+ ret = false;
+ }
+ has_exception = wasm_copy_exception(module_inst, exception);
+ if (has_exception && strstr(exception, "native stack overflow")) {
+ /* After a stack overflow, the stack was left
+ in a damaged state, let the CRT repair it */
+ result = _resetstkoflw();
+ bh_assert(result != 0);
+ }
+#endif
+ }
+ else {
+ /* Exception has been set in signal handler before calling longjmp */
+ ret = false;
+ }
+
+ /* Note: can't check wasm_get_exception(module_inst) here, there may be
+ * exception which is not caught by hardware (e.g. uninitialized elements),
+ * then the stack-frame is already freed inside wasm_interp_call_wasm */
+ if (!ret) {
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+ if (wasm_interp_create_call_stack(exec_env)) {
+ wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
+ }
+#endif
+ /* Restore operand frames */
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+ exec_env->wasm_stack.s.top = prev_top;
+ }
+
+ jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
+ bh_assert(&jmpbuf_node == jmpbuf_node_pop);
+ if (!exec_env->jmpbuf_stack_top) {
+ wasm_runtime_set_exec_env_tls(NULL);
+ }
+ if (!ret) {
+ os_sigreturn();
+ os_signal_unmask();
+ }
+ (void)jmpbuf_node_pop;
+}
+#define interp_call_wasm call_wasm_with_hw_bound_check
+#else
+#define interp_call_wasm wasm_interp_call_wasm
+#endif
+
+bool
+wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
+ unsigned argc, uint32 argv[])
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+
+ /* set thread handle and stack boundary */
+ wasm_exec_env_set_thread_info(exec_env);
+
+ interp_call_wasm(module_inst, exec_env, function, argc, argv);
+ return !wasm_copy_exception(module_inst, NULL);
+}
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+void
+wasm_dump_perf_profiling(const WASMModuleInstance *module_inst)
+{
+ WASMExportFuncInstance *export_func;
+ WASMFunctionInstance *func_inst;
+ char *func_name;
+ uint32 i, j;
+
+ os_printf("Performance profiler data:\n");
+ for (i = 0; i < module_inst->e->function_count; i++) {
+ func_inst = module_inst->e->functions + i;
+ if (func_inst->is_import_func) {
+ func_name = func_inst->u.func_import->field_name;
+ }
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ else if (func_inst->u.func->field_name) {
+ func_name = func_inst->u.func->field_name;
+ }
+#endif
+ else {
+ func_name = NULL;
+ for (j = 0; j < module_inst->export_func_count; j++) {
+ export_func = module_inst->export_functions + j;
+ if (export_func->function == func_inst) {
+ func_name = export_func->name;
+ break;
+ }
+ }
+ }
+
+ if (func_name)
+ os_printf(" func %s, execution time: %.3f ms, execution count: %d "
+ "times\n",
+ func_name,
+ module_inst->e->functions[i].total_exec_time / 1000.0f,
+ module_inst->e->functions[i].total_exec_cnt);
+ else
+ os_printf(" func %d, execution time: %.3f ms, execution count: %d "
+ "times\n",
+ i, module_inst->e->functions[i].total_exec_time / 1000.0f,
+ module_inst->e->functions[i].total_exec_cnt);
+ }
+}
+#endif
+
+uint32
+wasm_module_malloc_internal(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 size,
+ void **p_native_addr)
+{
+ WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
+ uint8 *addr = NULL;
+ uint32 offset = 0;
+
+ if (!memory) {
+ wasm_set_exception(module_inst, "uninitialized memory");
+ return 0;
+ }
+
+ if (memory->heap_handle) {
+ addr = mem_allocator_malloc(memory->heap_handle, size);
+ }
+ else if (module_inst->e->malloc_function && module_inst->e->free_function) {
+ if (!execute_malloc_function(
+ module_inst, exec_env, module_inst->e->malloc_function,
+ module_inst->e->retain_function, size, &offset)) {
+ return 0;
+ }
+ /* If we use app's malloc function,
+ the default memory may be changed while memory growing */
+ memory = wasm_get_default_memory(module_inst);
+ addr = offset ? memory->memory_data + offset : NULL;
+ }
+
+ if (!addr) {
+ if (memory->heap_handle
+ && mem_allocator_is_heap_corrupted(memory->heap_handle)) {
+ wasm_runtime_show_app_heap_corrupted_prompt();
+ wasm_set_exception(module_inst, "app heap corrupted");
+ }
+ else {
+ LOG_WARNING("warning: allocate %u bytes memory failed", size);
+ }
+ return 0;
+ }
+ if (p_native_addr)
+ *p_native_addr = addr;
+
+ return (uint32)(addr - memory->memory_data);
+}
+
+uint32
+wasm_module_realloc_internal(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr, uint32 size,
+ void **p_native_addr)
+{
+ WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
+ uint8 *addr = NULL;
+
+ if (!memory) {
+ wasm_set_exception(module_inst, "uninitialized memory");
+ return 0;
+ }
+
+ if (memory->heap_handle) {
+ addr = mem_allocator_realloc(
+ memory->heap_handle, ptr ? memory->memory_data + ptr : NULL, size);
+ }
+
+ /* Only support realloc in WAMR's app heap */
+ (void)exec_env;
+
+ if (!addr) {
+ if (memory->heap_handle
+ && mem_allocator_is_heap_corrupted(memory->heap_handle)) {
+ wasm_set_exception(module_inst, "app heap corrupted");
+ }
+ else {
+ wasm_set_exception(module_inst, "out of memory");
+ }
+ return 0;
+ }
+ if (p_native_addr)
+ *p_native_addr = addr;
+
+ return (uint32)(addr - memory->memory_data);
+}
+
+void
+wasm_module_free_internal(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr)
+{
+ if (ptr) {
+ WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
+ uint8 *addr;
+
+ if (!memory) {
+ return;
+ }
+
+ addr = memory->memory_data + ptr;
+
+ if (memory->heap_handle && memory->heap_data <= addr
+ && addr < memory->heap_data_end) {
+ mem_allocator_free(memory->heap_handle, addr);
+ }
+ else if (module_inst->e->malloc_function
+ && module_inst->e->free_function && memory->memory_data <= addr
+ && addr < memory->memory_data_end) {
+ execute_free_function(module_inst, exec_env,
+ module_inst->e->free_function, ptr);
+ }
+ }
+}
+
+uint32
+wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
+ void **p_native_addr)
+{
+ return wasm_module_malloc_internal(module_inst, NULL, size, p_native_addr);
+}
+
+uint32
+wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size,
+ void **p_native_addr)
+{
+ return wasm_module_realloc_internal(module_inst, NULL, ptr, size,
+ p_native_addr);
+}
+
+void
+wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr)
+{
+ wasm_module_free_internal(module_inst, NULL, ptr);
+}
+
+uint32
+wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src,
+ uint32 size)
+{
+ char *buffer;
+ uint32 buffer_offset =
+ wasm_module_malloc(module_inst, size, (void **)&buffer);
+ if (buffer_offset != 0) {
+ buffer = wasm_runtime_addr_app_to_native(
+ (WASMModuleInstanceCommon *)module_inst, buffer_offset);
+ bh_memcpy_s(buffer, size, src, size);
+ }
+ return buffer_offset;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+bool
+wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx,
+ uint32 inc_size, uint32 init_val)
+{
+ uint32 total_size, *new_table_data_start, i;
+ WASMTableInstance *table_inst;
+
+ if (!inc_size) {
+ return true;
+ }
+
+ bh_assert(table_idx < module_inst->table_count);
+ table_inst = wasm_get_table_inst(module_inst, table_idx);
+ if (!table_inst) {
+ return false;
+ }
+
+ if (inc_size > UINT32_MAX - table_inst->cur_size) {
+ return false;
+ }
+
+ total_size = table_inst->cur_size + inc_size;
+ if (total_size > table_inst->max_size) {
+ return false;
+ }
+
+ /* fill in */
+ new_table_data_start = table_inst->elems + table_inst->cur_size;
+ for (i = 0; i < inc_size; ++i) {
+ new_table_data_start[i] = init_val;
+ }
+
+ table_inst->cur_size = total_size;
+ return true;
+}
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+
+static bool
+call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 argc, uint32 argv[], bool check_type_idx, uint32 type_idx)
+{
+ WASMModuleInstance *module_inst = NULL;
+ WASMTableInstance *table_inst = NULL;
+ uint32 func_idx = 0;
+ WASMFunctionInstance *func_inst = NULL;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ bh_assert(module_inst);
+
+ table_inst = module_inst->tables[tbl_idx];
+ if (!table_inst) {
+ wasm_set_exception(module_inst, "unknown table");
+ goto got_exception;
+ }
+
+ if (elem_idx >= table_inst->cur_size) {
+ wasm_set_exception(module_inst, "undefined element");
+ goto got_exception;
+ }
+
+ func_idx = table_inst->elems[elem_idx];
+ if (func_idx == NULL_REF) {
+ wasm_set_exception(module_inst, "uninitialized element");
+ goto got_exception;
+ }
+
+ /**
+ * we insist to call functions owned by the module itself
+ **/
+ if (func_idx >= module_inst->e->function_count) {
+ wasm_set_exception(module_inst, "unknown function");
+ goto got_exception;
+ }
+
+ func_inst = module_inst->e->functions + func_idx;
+
+ if (check_type_idx) {
+ WASMType *cur_type = module_inst->module->types[type_idx];
+ WASMType *cur_func_type;
+
+ if (func_inst->is_import_func)
+ cur_func_type = func_inst->u.func_import->func_type;
+ else
+ cur_func_type = func_inst->u.func->func_type;
+
+ if (cur_type != cur_func_type) {
+ wasm_set_exception(module_inst, "indirect call type mismatch");
+ goto got_exception;
+ }
+ }
+
+ interp_call_wasm(module_inst, exec_env, func_inst, argc, argv);
+
+ return !wasm_copy_exception(module_inst, NULL);
+
+got_exception:
+ return false;
+}
+
+bool
+wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 argc, uint32 argv[])
+{
+ return call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0);
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size)
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ uint32 stack_top_idx = module_inst->module->aux_stack_top_global_index;
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ /* Check the aux stack space */
+ uint32 data_end = module_inst->module->aux_data_end;
+ uint32 stack_bottom = module_inst->module->aux_stack_bottom;
+ bool is_stack_before_data = stack_bottom < data_end ? true : false;
+ if ((is_stack_before_data && (size > start_offset))
+ || ((!is_stack_before_data) && (start_offset - data_end < size)))
+ return false;
+#endif
+
+ if (stack_top_idx != (uint32)-1) {
+ /* The aux stack top is a wasm global,
+ set the initial value for the global */
+ uint8 *global_addr =
+ module_inst->global_data
+ + module_inst->e->globals[stack_top_idx].data_offset;
+ *(int32 *)global_addr = start_offset;
+ /* The aux stack boundary is a constant value,
+ set the value to exec_env */
+ exec_env->aux_stack_boundary.boundary = start_offset - size;
+ exec_env->aux_stack_bottom.bottom = start_offset;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size)
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+
+ /* The aux stack information is resolved in loader
+ and store in module */
+ uint32 stack_bottom = module_inst->module->aux_stack_bottom;
+ uint32 total_aux_stack_size = module_inst->module->aux_stack_size;
+
+ if (stack_bottom != 0 && total_aux_stack_size != 0) {
+ if (start_offset)
+ *start_offset = stack_bottom;
+ if (size)
+ *size = total_aux_stack_size;
+ return true;
+ }
+ return false;
+}
+#endif
+
+#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0)
+void
+wasm_get_module_mem_consumption(const WASMModule *module,
+ WASMModuleMemConsumption *mem_conspn)
+{
+ uint32 i, size;
+
+ memset(mem_conspn, 0, sizeof(*mem_conspn));
+
+ mem_conspn->module_struct_size = sizeof(WASMModule);
+
+ mem_conspn->types_size = sizeof(WASMType *) * module->type_count;
+ for (i = 0; i < module->type_count; i++) {
+ WASMType *type = module->types[i];
+ size = offsetof(WASMType, types)
+ + sizeof(uint8) * (type->param_count + type->result_count);
+ mem_conspn->types_size += size;
+ }
+
+ mem_conspn->imports_size = sizeof(WASMImport) * module->import_count;
+
+ mem_conspn->functions_size =
+ sizeof(WASMFunction *) * module->function_count;
+ for (i = 0; i < module->function_count; i++) {
+ WASMFunction *func = module->functions[i];
+ WASMType *type = func->func_type;
+ size = sizeof(WASMFunction) + func->local_count
+ + sizeof(uint16) * (type->param_count + func->local_count);
+#if WASM_ENABLE_FAST_INTERP != 0
+ size +=
+ func->code_compiled_size + sizeof(uint32) * func->const_cell_num;
+#endif
+ mem_conspn->functions_size += size;
+ }
+
+ mem_conspn->tables_size = sizeof(WASMTable) * module->table_count;
+ mem_conspn->memories_size = sizeof(WASMMemory) * module->memory_count;
+ mem_conspn->globals_size = sizeof(WASMGlobal) * module->global_count;
+ mem_conspn->exports_size = sizeof(WASMExport) * module->export_count;
+
+ mem_conspn->table_segs_size =
+ sizeof(WASMTableSeg) * module->table_seg_count;
+ for (i = 0; i < module->table_seg_count; i++) {
+ WASMTableSeg *table_seg = &module->table_segments[i];
+ mem_conspn->tables_size += sizeof(uint32) * table_seg->function_count;
+ }
+
+ mem_conspn->data_segs_size = sizeof(WASMDataSeg *) * module->data_seg_count;
+ for (i = 0; i < module->data_seg_count; i++) {
+ mem_conspn->data_segs_size += sizeof(WASMDataSeg);
+ }
+
+ if (module->const_str_list) {
+ StringNode *node = module->const_str_list, *node_next;
+ while (node) {
+ node_next = node->next;
+ mem_conspn->const_strs_size +=
+ sizeof(StringNode) + strlen(node->str) + 1;
+ node = node_next;
+ }
+ }
+
+ mem_conspn->total_size += mem_conspn->module_struct_size;
+ mem_conspn->total_size += mem_conspn->types_size;
+ mem_conspn->total_size += mem_conspn->imports_size;
+ mem_conspn->total_size += mem_conspn->functions_size;
+ mem_conspn->total_size += mem_conspn->tables_size;
+ mem_conspn->total_size += mem_conspn->memories_size;
+ mem_conspn->total_size += mem_conspn->globals_size;
+ mem_conspn->total_size += mem_conspn->exports_size;
+ mem_conspn->total_size += mem_conspn->table_segs_size;
+ mem_conspn->total_size += mem_conspn->data_segs_size;
+ mem_conspn->total_size += mem_conspn->const_strs_size;
+}
+
+void
+wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst,
+ WASMModuleInstMemConsumption *mem_conspn)
+{
+ uint32 i, size;
+
+ memset(mem_conspn, 0, sizeof(*mem_conspn));
+
+ mem_conspn->module_inst_struct_size = (uint8 *)module_inst->e
+ - (uint8 *)module_inst
+ + sizeof(WASMModuleInstanceExtra);
+
+ mem_conspn->memories_size =
+ sizeof(WASMMemoryInstance *) * module_inst->memory_count;
+ for (i = 0; i < module_inst->memory_count; i++) {
+ WASMMemoryInstance *memory = module_inst->memories[i];
+ size = memory->num_bytes_per_page * memory->cur_page_count;
+ mem_conspn->memories_size += size;
+ mem_conspn->app_heap_size += memory->heap_data_end - memory->heap_data;
+ /* size of app heap structure */
+ mem_conspn->memories_size += mem_allocator_get_heap_struct_size();
+ /* Module instance structures have been appened into the end of
+ module instance */
+ }
+
+ mem_conspn->tables_size =
+ sizeof(WASMTableInstance *) * module_inst->table_count;
+ /* Table instance structures and table elements have been appened into
+ the end of module instance */
+
+ mem_conspn->functions_size =
+ sizeof(WASMFunctionInstance) * module_inst->e->function_count;
+
+ mem_conspn->globals_size =
+ sizeof(WASMGlobalInstance) * module_inst->e->global_count;
+ /* Global data has been appened into the end of module instance */
+
+ mem_conspn->exports_size =
+ sizeof(WASMExportFuncInstance) * module_inst->export_func_count;
+
+ mem_conspn->total_size += mem_conspn->module_inst_struct_size;
+ mem_conspn->total_size += mem_conspn->memories_size;
+ mem_conspn->total_size += mem_conspn->functions_size;
+ mem_conspn->total_size += mem_conspn->tables_size;
+ mem_conspn->total_size += mem_conspn->globals_size;
+ mem_conspn->total_size += mem_conspn->exports_size;
+}
+#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
+ || (WASM_ENABLE_MEMORY_TRACING != 0) */
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+bool
+wasm_interp_create_call_stack(struct WASMExecEnv *exec_env)
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
+ WASMInterpFrame *first_frame,
+ *cur_frame = wasm_exec_env_get_cur_frame(exec_env);
+ uint32 n = 0;
+
+ /* count frames includes a function */
+ first_frame = cur_frame;
+ while (cur_frame) {
+ if (cur_frame->function) {
+ n++;
+ }
+ cur_frame = cur_frame->prev_frame;
+ }
+
+ /* release previous stack frames and create new ones */
+ if (!bh_vector_destroy(module_inst->frames)
+ || !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame),
+ false)) {
+ return false;
+ }
+
+ cur_frame = first_frame;
+ n = 0;
+
+ while (cur_frame) {
+ WASMCApiFrame frame = { 0 };
+ WASMFunctionInstance *func_inst = cur_frame->function;
+ const char *func_name = NULL;
+ const uint8 *func_code_base = NULL;
+
+ if (!func_inst) {
+ cur_frame = cur_frame->prev_frame;
+ continue;
+ }
+
+ /* place holder, will overwrite it in wasm_c_api */
+ frame.instance = module_inst;
+ frame.module_offset = 0;
+ frame.func_index = (uint32)(func_inst - module_inst->e->functions);
+
+ func_code_base = wasm_get_func_code(func_inst);
+ if (!cur_frame->ip || !func_code_base) {
+ frame.func_offset = 0;
+ }
+ else {
+ frame.func_offset = (uint32)(cur_frame->ip - func_code_base);
+ }
+
+ /* look for the function name */
+ if (func_inst->is_import_func) {
+ func_name = func_inst->u.func_import->field_name;
+ }
+ else {
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+ func_name = func_inst->u.func->field_name;
+#endif
+ /* if custom name section is not generated,
+ search symbols from export table */
+ if (!func_name) {
+ uint32 i;
+ for (i = 0; i < module_inst->export_func_count; i++) {
+ WASMExportFuncInstance *export_func =
+ module_inst->export_functions + i;
+ if (export_func->function == func_inst) {
+ func_name = export_func->name;
+ break;
+ }
+ }
+ }
+ }
+
+ frame.func_name_wp = func_name;
+
+ if (!bh_vector_append(module_inst->frames, &frame)) {
+ bh_vector_destroy(module_inst->frames);
+ return false;
+ }
+
+ cur_frame = cur_frame->prev_frame;
+ n++;
+ }
+
+ return true;
+}
+
+#define PRINT_OR_DUMP() \
+ do { \
+ total_len += \
+ wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \
+ if ((!print) && buf && (len == 0)) { \
+ return total_len; \
+ } \
+ } while (0)
+
+uint32
+wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
+ uint32 len)
+{
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
+ uint32 n = 0, total_len = 0, total_frames;
+ /* reserve 256 bytes for line buffer, any line longer than 256 bytes
+ * will be truncated */
+ char line_buf[256];
+
+ if (!module_inst->frames) {
+ return 0;
+ }
+
+ total_frames = (uint32)bh_vector_size(module_inst->frames);
+ if (total_frames == 0) {
+ return 0;
+ }
+
+ snprintf(line_buf, sizeof(line_buf), "\n");
+ PRINT_OR_DUMP();
+
+ while (n < total_frames) {
+ WASMCApiFrame frame = { 0 };
+ uint32 line_length, i;
+
+ if (!bh_vector_get(module_inst->frames, n, &frame)) {
+ return 0;
+ }
+
+ /* function name not exported, print number instead */
+ if (frame.func_name_wp == NULL) {
+ line_length = snprintf(line_buf, sizeof(line_buf), "#%02d $f%d\n",
+ n, frame.func_index);
+ }
+ else {
+ line_length = snprintf(line_buf, sizeof(line_buf), "#%02d %s\n", n,
+ frame.func_name_wp);
+ }
+
+ if (line_length >= sizeof(line_buf)) {
+ uint32 line_buffer_len = sizeof(line_buf);
+ /* If line too long, ensure the last character is '\n' */
+ for (i = line_buffer_len - 5; i < line_buffer_len - 2; i++) {
+ line_buf[i] = '.';
+ }
+ line_buf[line_buffer_len - 2] = '\n';
+ }
+
+ PRINT_OR_DUMP();
+
+ n++;
+ }
+ snprintf(line_buf, sizeof(line_buf), "\n");
+ PRINT_OR_DUMP();
+
+ return total_len + 1;
+}
+#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+void
+jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id)
+{
+ if (id != EXCE_ALREADY_THROWN)
+ wasm_set_exception_with_id(module_inst, id);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+}
+
+bool
+jit_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
+ uint32 app_buf_addr, uint32 app_buf_size,
+ void **p_native_addr)
+{
+ bool ret = wasm_check_app_addr_and_convert(
+ module_inst, is_str, app_buf_addr, app_buf_size, p_native_addr);
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!ret)
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+
+ return ret;
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0 */
+
+#if WASM_ENABLE_FAST_JIT != 0
+bool
+fast_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 type_idx, uint32 argc, uint32 *argv)
+{
+ return call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, true,
+ type_idx);
+}
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 */
+
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+
+bool
+llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 argc, uint32 *argv)
+{
+ bool ret;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
+ return aot_call_indirect(exec_env, tbl_idx, elem_idx, argc, argv);
+ }
+#endif
+
+ ret = call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!ret)
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+ return ret;
+}
+
+bool
+llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
+ uint32 *argv)
+{
+ WASMModuleInstance *module_inst;
+ WASMModule *module;
+ uint32 *func_type_indexes;
+ uint32 func_type_idx;
+ WASMType *func_type;
+ void *func_ptr;
+ WASMFunctionImport *import_func;
+ CApiFuncImport *c_api_func_import = NULL;
+ const char *signature;
+ void *attachment;
+ char buf[96];
+ bool ret = false;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
+ return aot_invoke_native(exec_env, func_idx, argc, argv);
+ }
+#endif
+
+ module_inst = (WASMModuleInstance *)wasm_runtime_get_module_inst(exec_env);
+ module = module_inst->module;
+ func_type_indexes = module_inst->func_type_indexes;
+ func_type_idx = func_type_indexes[func_idx];
+ func_type = module->types[func_type_idx];
+ func_ptr = module_inst->func_ptrs[func_idx];
+
+ bh_assert(func_idx < module->import_function_count);
+
+ import_func = &module->import_functions[func_idx].u.function;
+ if (import_func->call_conv_wasm_c_api) {
+ if (module_inst->e->c_api_func_imports) {
+ c_api_func_import = module_inst->e->c_api_func_imports + func_idx;
+ func_ptr = c_api_func_import->func_ptr_linked;
+ }
+ else {
+ c_api_func_import = NULL;
+ func_ptr = NULL;
+ }
+ }
+
+ if (!func_ptr) {
+ snprintf(buf, sizeof(buf),
+ "failed to call unlinked import function (%s, %s)",
+ import_func->module_name, import_func->field_name);
+ wasm_set_exception(module_inst, buf);
+ goto fail;
+ }
+
+ attachment = import_func->attachment;
+ if (import_func->call_conv_wasm_c_api) {
+ ret = wasm_runtime_invoke_c_api_native(
+ (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc,
+ argv, c_api_func_import->with_env_arg, c_api_func_import->env_arg);
+ }
+ else if (!import_func->call_conv_raw) {
+ signature = import_func->signature;
+ ret =
+ wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature,
+ attachment, argv, argc, argv);
+ }
+ else {
+ signature = import_func->signature;
+ ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type,
+ signature, attachment, argv, argc,
+ argv);
+ }
+
+fail:
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (!ret)
+ wasm_runtime_access_exce_check_guard_page();
+#endif
+ return ret;
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index,
+ uint32 offset, uint32 len, uint32 dst)
+{
+ WASMMemoryInstance *memory_inst;
+ WASMModule *module;
+ uint8 *data = NULL;
+ uint8 *maddr;
+ uint64 seg_len = 0;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ return aot_memory_init(module_inst, seg_index, offset, len, dst);
+ }
+#endif
+
+ memory_inst = wasm_get_default_memory(module_inst);
+ module = module_inst->module;
+ seg_len = module->data_segments[seg_index]->data_length;
+ data = module->data_segments[seg_index]->data;
+
+ if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
+ dst, len))
+ return false;
+
+ if ((uint64)offset + (uint64)len > seg_len) {
+ wasm_set_exception(module_inst, "out of bounds memory access");
+ return false;
+ }
+
+ maddr = wasm_runtime_addr_app_to_native(
+ (WASMModuleInstanceCommon *)module_inst, dst);
+
+ bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len);
+ return true;
+}
+
+bool
+llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index)
+{
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ return aot_data_drop(module_inst, seg_index);
+ }
+#endif
+
+ module_inst->module->data_segments[seg_index]->data_length = 0;
+ /* Currently we can't free the dropped data segment
+ as they are stored in wasm bytecode */
+ return true;
+}
+#endif /* end of WASM_ENABLE_BULK_MEMORY != 0 */
+
+#if WASM_ENABLE_REF_TYPES != 0
+void
+llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx)
+{
+ WASMTableSeg *tbl_segs;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ return aot_drop_table_seg(module_inst, tbl_seg_idx);
+ }
+#endif
+
+ tbl_segs = module_inst->module->table_segments;
+ tbl_segs[tbl_seg_idx].is_dropped = true;
+}
+
+void
+llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 tbl_seg_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset)
+{
+ WASMTableInstance *tbl_inst;
+ WASMTableSeg *tbl_seg;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ return aot_table_init(module_inst, tbl_idx, tbl_seg_idx, length,
+ src_offset, dst_offset);
+ }
+#endif
+
+ tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
+ tbl_seg = module_inst->module->table_segments + tbl_seg_idx;
+
+ bh_assert(tbl_inst);
+ bh_assert(tbl_seg);
+
+ if (!length) {
+ return;
+ }
+
+ if (length + src_offset > tbl_seg->function_count
+ || dst_offset + length > tbl_inst->cur_size) {
+ jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ if (tbl_seg->is_dropped) {
+ jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ if (!wasm_elem_is_passive(tbl_seg->mode)) {
+ jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ bh_memcpy_s((uint8 *)tbl_inst + offsetof(WASMTableInstance, elems)
+ + dst_offset * sizeof(uint32),
+ (uint32)sizeof(uint32) * (tbl_inst->cur_size - dst_offset),
+ tbl_seg->func_indexes + src_offset,
+ (uint32)(length * sizeof(uint32)));
+}
+
+void
+llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset)
+{
+ WASMTableInstance *src_tbl_inst;
+ WASMTableInstance *dst_tbl_inst;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ aot_table_copy(module_inst, src_tbl_idx, dst_tbl_idx, length,
+ src_offset, dst_offset);
+ return;
+ }
+#endif
+
+ src_tbl_inst = wasm_get_table_inst(module_inst, src_tbl_idx);
+ dst_tbl_inst = wasm_get_table_inst(module_inst, dst_tbl_idx);
+ bh_assert(src_tbl_inst);
+ bh_assert(dst_tbl_inst);
+
+ if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
+ || (uint64)src_offset + length > src_tbl_inst->cur_size) {
+ jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ /* if src_offset >= dst_offset, copy from front to back */
+ /* if src_offset < dst_offset, copy from back to front */
+ /* merge all together */
+ bh_memmove_s((uint8 *)dst_tbl_inst + offsetof(WASMTableInstance, elems)
+ + sizeof(uint32) * dst_offset,
+ (uint32)sizeof(uint32) * (dst_tbl_inst->cur_size - dst_offset),
+ (uint8 *)src_tbl_inst + offsetof(WASMTableInstance, elems)
+ + sizeof(uint32) * src_offset,
+ (uint32)sizeof(uint32) * length);
+}
+
+void
+llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 length, uint32 val, uint32 data_offset)
+{
+ WASMTableInstance *tbl_inst;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ aot_table_fill(module_inst, tbl_idx, length, val, data_offset);
+ return;
+ }
+#endif
+
+ tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
+ bh_assert(tbl_inst);
+
+ if (data_offset + length > tbl_inst->cur_size) {
+ jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+ return;
+ }
+
+ for (; length != 0; data_offset++, length--) {
+ tbl_inst->elems[data_offset] = val;
+ }
+}
+
+uint32
+llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 inc_size, uint32 init_val)
+{
+ WASMTableInstance *tbl_inst;
+ uint32 i, orig_size, total_size;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == module_inst->module_type) {
+ return aot_table_grow(module_inst, tbl_idx, inc_size, init_val);
+ }
+#endif
+
+ tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
+ if (!tbl_inst) {
+ return (uint32)-1;
+ }
+
+ orig_size = tbl_inst->cur_size;
+
+ if (!inc_size) {
+ return orig_size;
+ }
+
+ if (tbl_inst->cur_size > UINT32_MAX - inc_size) { /* integer overflow */
+ return (uint32)-1;
+ }
+
+ total_size = tbl_inst->cur_size + inc_size;
+ if (total_size > tbl_inst->max_size) {
+ return (uint32)-1;
+ }
+
+ /* fill in */
+ for (i = 0; i < inc_size; ++i) {
+ tbl_inst->elems[tbl_inst->cur_size + i] = init_val;
+ }
+
+ tbl_inst->cur_size = total_size;
+ return orig_size;
+}
+#endif /* end of WASM_ENABLE_REF_TYPES != 0 */
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
+bool
+llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index)
+{
+ WASMModuleInstance *module_inst;
+ WASMInterpFrame *frame;
+ uint32 size;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
+ return aot_alloc_frame(exec_env, func_index);
+ }
+#endif
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ size = wasm_interp_interp_frame_size(0);
+
+ frame = wasm_exec_env_alloc_wasm_frame(exec_env, size);
+ if (!frame) {
+ wasm_set_exception(module_inst, "wasm operand stack overflow");
+ return false;
+ }
+
+ frame->function = module_inst->e->functions + func_index;
+ frame->ip = NULL;
+ frame->sp = frame->lp;
+#if WASM_ENABLE_PERF_PROFILING != 0
+ frame->time_started = os_time_get_boot_microsecond();
+#endif
+ frame->prev_frame = wasm_exec_env_get_cur_frame(exec_env);
+ wasm_exec_env_set_cur_frame(exec_env, frame);
+
+ return true;
+}
+
+void
+llvm_jit_free_frame(WASMExecEnv *exec_env)
+{
+ WASMInterpFrame *frame;
+ WASMInterpFrame *prev_frame;
+
+#if WASM_ENABLE_JIT != 0
+ if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
+ aot_free_frame(exec_env);
+ return;
+ }
+#endif
+
+ frame = wasm_exec_env_get_cur_frame(exec_env);
+ prev_frame = frame->prev_frame;
+
+#if WASM_ENABLE_PERF_PROFILING != 0
+ if (frame->function) {
+ frame->function->total_exec_time +=
+ os_time_get_boot_microsecond() - frame->time_started;
+ frame->function->total_exec_cnt++;
+ }
+#endif
+ wasm_exec_env_free_wasm_frame(exec_env, frame);
+ wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+}
+#endif /* end of WASM_ENABLE_DUMP_CALL_STACK != 0 \
+ || WASM_ENABLE_PERF_PROFILING != 0 */
+
+#endif /* end of WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 */
+
+#if WASM_ENABLE_LIBC_WASI != 0 && WASM_ENABLE_MULTI_MODULE != 0
+void
+wasm_propagate_wasi_args(WASMModule *module)
+{
+ if (!module->import_count)
+ return;
+
+ bh_assert(&module->import_module_list_head);
+
+ WASMRegisteredModule *node =
+ bh_list_first_elem(&module->import_module_list_head);
+ while (node) {
+ WASIArguments *wasi_args_impt_mod =
+ &((WASMModule *)(node->module))->wasi_args;
+ bh_assert(wasi_args_impt_mod);
+
+ bh_memcpy_s(wasi_args_impt_mod, sizeof(WASIArguments),
+ &module->wasi_args, sizeof(WASIArguments));
+ node = bh_list_elem_next(node);
+ }
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.h
new file mode 100644
index 000000000..15169433e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/interpreter/wasm_runtime.h
@@ -0,0 +1,668 @@
+/*
+ * 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"
+
+#if WASM_ENABLE_WASI_NN != 0
+#include "../libraries/wasi-nn/src/wasi_nn_private.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EXCEPTION_BUF_LEN 128
+
+typedef struct WASMModuleInstance WASMModuleInstance;
+typedef struct WASMFunctionInstance WASMFunctionInstance;
+typedef struct WASMMemoryInstance WASMMemoryInstance;
+typedef struct WASMTableInstance WASMTableInstance;
+typedef struct WASMGlobalInstance WASMGlobalInstance;
+
+/**
+ * When LLVM JIT, WAMR compiler or AOT is enabled, we should ensure that
+ * some offsets of the same field in the interpreter module instance and
+ * aot module instance are the same, so that the LLVM JITed/AOTed code
+ * can smoothly access the interpreter module instance.
+ * Same for the memory instance and table instance.
+ * We use the macro DefPointer to define some related pointer fields.
+ */
+#if (WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 \
+ || WASM_ENABLE_AOT != 0) \
+ && UINTPTR_MAX == UINT32_MAX
+/* Add u32 padding if LLVM JIT, WAMR compiler or AOT is enabled on
+ 32-bit platform */
+#define DefPointer(type, field) \
+ type field; \
+ uint32 field##_padding
+#else
+#define DefPointer(type, field) type field
+#endif
+
+typedef enum WASMExceptionID {
+ 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_NATIVE_STACK_OVERFLOW,
+ EXCE_UNALIGNED_ATOMIC,
+ EXCE_AUX_STACK_OVERFLOW,
+ EXCE_AUX_STACK_UNDERFLOW,
+ EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
+ EXCE_OPERAND_STACK_OVERFLOW,
+ EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
+ EXCE_ALREADY_THROWN,
+ EXCE_NUM,
+} WASMExceptionID;
+
+typedef union {
+ uint64 u64;
+ uint32 u32[2];
+} MemBound;
+
+struct WASMMemoryInstance {
+ /* Module type */
+ uint32 module_type;
+ /* Shared memory flag */
+ bool is_shared;
+
+ /* Number bytes per page */
+ uint32 num_bytes_per_page;
+ /* Current page count */
+ uint32 cur_page_count;
+ /* Maximum page count */
+ uint32 max_page_count;
+ /* Memory data size */
+ uint32 memory_data_size;
+ /**
+ * Memory data begin address, Note:
+ * the app-heap might be inserted in to the linear memory,
+ * when memory is re-allocated, the heap data and memory data
+ * must be copied to new memory also
+ */
+ DefPointer(uint8 *, memory_data);
+ /* Memory data end address */
+ DefPointer(uint8 *, memory_data_end);
+
+ /* Heap data base address */
+ DefPointer(uint8 *, heap_data);
+ /* Heap data end address */
+ DefPointer(uint8 *, heap_data_end);
+ /* The heap created */
+ DefPointer(void *, heap_handle);
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_AOT != 0
+ MemBound mem_bound_check_1byte;
+ MemBound mem_bound_check_2bytes;
+ MemBound mem_bound_check_4bytes;
+ MemBound mem_bound_check_8bytes;
+ MemBound mem_bound_check_16bytes;
+#endif
+};
+
+struct WASMTableInstance {
+ /* Current size */
+ uint32 cur_size;
+ /* Maximum size */
+ uint32 max_size;
+ /* Table elements */
+ uint32 elems[1];
+};
+
+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;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ /* just for import, keep the reference here */
+ WASMModuleInstance *import_module_inst;
+ WASMGlobalInstance *import_global_inst;
+#endif
+};
+
+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;
+#if WASM_ENABLE_FAST_INTERP != 0
+ /* cell num of consts */
+ uint16 const_cell_num;
+#endif
+ uint16 *local_offsets;
+ /* parameter types */
+ uint8 *param_types;
+ /* local types, NULL for import function */
+ uint8 *local_types;
+ union {
+ WASMFunctionImport *func_import;
+ WASMFunction *func;
+ } u;
+#if WASM_ENABLE_MULTI_MODULE != 0
+ WASMModuleInstance *import_module_inst;
+ WASMFunctionInstance *import_func_inst;
+#endif
+#if WASM_ENABLE_PERF_PROFILING != 0
+ /* total execution time */
+ uint64 total_exec_time;
+ /* total execution count */
+ uint32 total_exec_cnt;
+#endif
+};
+
+typedef struct WASMExportFuncInstance {
+ char *name;
+ WASMFunctionInstance *function;
+} WASMExportFuncInstance;
+
+typedef struct WASMExportGlobInstance {
+ char *name;
+ WASMGlobalInstance *global;
+} WASMExportGlobInstance;
+
+typedef struct WASMExportTabInstance {
+ char *name;
+ WASMTableInstance *table;
+} WASMExportTabInstance;
+
+typedef struct WASMExportMemInstance {
+ char *name;
+ WASMMemoryInstance *memory;
+} WASMExportMemInstance;
+
+/* wasm-c-api import function info */
+typedef struct CApiFuncImport {
+ /* host func pointer after linked */
+ void *func_ptr_linked;
+ /* whether the host func has env argument */
+ bool with_env_arg;
+ /* the env argument of the host func */
+ void *env_arg;
+} CApiFuncImport;
+
+/* Extra info of WASM module instance for interpreter/jit mode */
+typedef struct WASMModuleInstanceExtra {
+ WASMGlobalInstance *globals;
+ WASMFunctionInstance *functions;
+
+ uint32 global_count;
+ uint32 function_count;
+
+ WASMFunctionInstance *start_function;
+ WASMFunctionInstance *malloc_function;
+ WASMFunctionInstance *free_function;
+ WASMFunctionInstance *retain_function;
+
+ CApiFuncImport *c_api_func_imports;
+ RunningMode running_mode;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+ bh_list sub_module_inst_list_head;
+ bh_list *sub_module_inst_list;
+ /* linked table instances of import table instances */
+ WASMTableInstance **table_insts_linked;
+#endif
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ uint32 max_aux_stack_used;
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0 \
+ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+ && WASM_ENABLE_LAZY_JIT != 0)
+ WASMModuleInstance *next;
+#endif
+
+#if WASM_ENABLE_WASI_NN != 0
+ WASINNContext *wasi_nn_ctx;
+#endif
+} WASMModuleInstanceExtra;
+
+struct AOTFuncPerfProfInfo;
+
+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;
+ DefPointer(WASMMemoryInstance **, memories);
+
+ /* global and table info */
+ uint32 global_data_size;
+ uint32 table_count;
+ DefPointer(uint8 *, global_data);
+ /* For AOTModuleInstance, it denotes `AOTTableInstance *` */
+ DefPointer(WASMTableInstance **, tables);
+
+ /* import func ptrs + llvm jit func ptrs */
+ DefPointer(void **, func_ptrs);
+
+ /* function type indexes */
+ DefPointer(uint32 *, func_type_indexes);
+
+ uint32 export_func_count;
+ uint32 export_global_count;
+ uint32 export_memory_count;
+ uint32 export_table_count;
+ /* For AOTModuleInstance, it denotes `AOTFunctionInstance *` */
+ DefPointer(WASMExportFuncInstance *, export_functions);
+ DefPointer(WASMExportGlobInstance *, export_globals);
+ DefPointer(WASMExportMemInstance *, export_memories);
+ DefPointer(WASMExportTabInstance *, export_tables);
+
+ /* The exception buffer of wasm interpreter for current thread. */
+ char cur_exception[EXCEPTION_BUF_LEN];
+
+ /* The WASM module or AOT module, for AOTModuleInstance,
+ it denotes `AOTModule *` */
+ DefPointer(WASMModule *, module);
+
+#if WASM_ENABLE_LIBC_WASI
+ /* WASI context */
+ DefPointer(WASIContext *, wasi_ctx);
+#else
+ DefPointer(void *, wasi_ctx);
+#endif
+ DefPointer(WASMExecEnv *, exec_env_singleton);
+ /* Array of function pointers to import functions,
+ not available in AOTModuleInstance */
+ DefPointer(void **, import_func_ptrs);
+ /* Array of function pointers to fast jit functions,
+ not available in AOTModuleInstance:
+ Only when the multi-tier JIT macros are all enabled and the running
+ mode of current module instance is set to Mode_Fast_JIT, runtime
+ will allocate new memory for it, otherwise it always points to the
+ module->fast_jit_func_ptrs */
+ DefPointer(void **, fast_jit_func_ptrs);
+ /* The custom data that can be set/get by wasm_{get|set}_custom_data */
+ DefPointer(void *, custom_data);
+ /* Stack frames, used in call stack dump and perf profiling */
+ DefPointer(Vector *, frames);
+ /* Function performance profiling info list, only available
+ in AOTModuleInstance */
+ DefPointer(struct AOTFuncPerfProfInfo *, func_perf_profilings);
+ /* WASM/AOT module extra info, for AOTModuleInstance,
+ it denotes `AOTModuleInstanceExtra *` */
+ DefPointer(WASMModuleInstanceExtra *, e);
+
+ /* Default WASM operand stack size */
+ uint32 default_wasm_stack_size;
+ uint32 reserved[3];
+
+ /*
+ * +------------------------------+ <-- memories
+ * | WASMMemoryInstance[mem_count], mem_count is always 1 for LLVM JIT/AOT
+ * +------------------------------+ <-- global_data
+ * | global data
+ * +------------------------------+ <-- tables
+ * | WASMTableInstance[table_count]
+ * +------------------------------+ <-- e
+ * | WASMModuleInstanceExtra
+ * +------------------------------+
+ */
+ union {
+ uint64 _make_it_8_byte_aligned_;
+ WASMMemoryInstance memory_instances[1];
+ uint8 bytes[1];
+ } global_table_data;
+};
+
+struct WASMInterpFrame;
+typedef struct WASMInterpFrame WASMRuntimeFrame;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+typedef struct WASMSubModInstNode {
+ bh_list_link l;
+ /* point to a string pool */
+ const char *module_name;
+ WASMModuleInstance *module_inst;
+} WASMSubModInstNode;
+#endif
+
+/**
+ * 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)
+{
+#if WASM_ENABLE_FAST_INTERP == 0
+ return func->is_import_func ? NULL : func->u.func->code;
+#else
+ return func->is_import_func ? NULL : func->u.func->code_compiled;
+#endif
+}
+
+/**
+ * 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)
+{
+#if WASM_ENABLE_FAST_INTERP == 0
+ return func->is_import_func ? NULL
+ : func->u.func->code + func->u.func->code_size;
+#else
+ return func->is_import_func
+ ? NULL
+ : func->u.func->code_compiled + func->u.func->code_compiled_size;
+#endif
+}
+
+WASMModule *
+wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size);
+
+WASMModule *
+wasm_load_from_sections(WASMSection *section_list, char *error_buf,
+ uint32 error_buf_size);
+
+void
+wasm_unload(WASMModule *module);
+
+WASMModuleInstance *
+wasm_instantiate(WASMModule *module, bool is_sub_inst,
+ WASMExecEnv *exec_env_main, uint32 stack_size,
+ uint32 heap_size, char *error_buf, uint32 error_buf_size);
+
+void
+wasm_dump_perf_profiling(const WASMModuleInstance *module_inst);
+
+void
+wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
+
+bool
+wasm_set_running_mode(WASMModuleInstance *module_inst,
+ RunningMode running_mode);
+
+WASMFunctionInstance *
+wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
+ const char *signature);
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+WASMGlobalInstance *
+wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name);
+
+WASMMemoryInstance *
+wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name);
+
+WASMTableInstance *
+wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name);
+#endif
+
+bool
+wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
+ unsigned argc, uint32 argv[]);
+
+void
+wasm_set_exception(WASMModuleInstance *module, const char *exception);
+
+void
+wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id);
+
+const char *
+wasm_get_exception(WASMModuleInstance *module);
+
+/**
+ * @brief Copy exception in buffer passed as parameter. Thread-safe version of
+ * `wasm_get_exception()`
+ * @note Buffer size must be no smaller than EXCEPTION_BUF_LEN
+ * @return true if exception found
+ */
+bool
+wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf);
+
+uint32
+wasm_module_malloc_internal(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 size,
+ void **p_native_addr);
+
+uint32
+wasm_module_realloc_internal(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr, uint32 size,
+ void **p_native_addr);
+
+void
+wasm_module_free_internal(WASMModuleInstance *module_inst,
+ WASMExecEnv *exec_env, uint32 ptr);
+
+uint32
+wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
+ void **p_native_addr);
+
+uint32
+wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size,
+ void **p_native_addr);
+
+void
+wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr);
+
+uint32
+wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src,
+ uint32 size);
+
+/**
+ * Check whether the app address and the buf is inside the linear memory,
+ * and convert the app address into native address
+ */
+bool
+wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
+ uint32 app_buf_addr, uint32 app_buf_size,
+ void **p_native_addr);
+
+WASMMemoryInstance *
+wasm_get_default_memory(WASMModuleInstance *module_inst);
+
+bool
+wasm_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count);
+
+bool
+wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 argc, uint32 argv[]);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size);
+
+bool
+wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size);
+#endif
+
+void
+wasm_get_module_mem_consumption(const WASMModule *module,
+ WASMModuleMemConsumption *mem_conspn);
+
+void
+wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module,
+ WASMModuleInstMemConsumption *mem_conspn);
+
+#if WASM_ENABLE_REF_TYPES != 0
+static inline bool
+wasm_elem_is_active(uint32 mode)
+{
+ return (mode & 0x1) == 0x0;
+}
+
+static inline bool
+wasm_elem_is_passive(uint32 mode)
+{
+ return (mode & 0x1) == 0x1;
+}
+
+static inline bool
+wasm_elem_is_declarative(uint32 mode)
+{
+ return (mode & 0x3) == 0x3;
+}
+
+bool
+wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx,
+ uint32 inc_entries, uint32 init_val);
+#endif /* WASM_ENABLE_REF_TYPES != 0 */
+
+static inline WASMTableInstance *
+wasm_get_table_inst(const WASMModuleInstance *module_inst, uint32 tbl_idx)
+{
+ /* careful, it might be a table in another module */
+ WASMTableInstance *tbl_inst = module_inst->tables[tbl_idx];
+#if WASM_ENABLE_MULTI_MODULE != 0
+ if (tbl_idx < module_inst->module->import_table_count
+ && module_inst->e->table_insts_linked[tbl_idx]) {
+ tbl_inst = module_inst->e->table_insts_linked[tbl_idx];
+ }
+#endif
+ bh_assert(tbl_inst);
+ return tbl_inst;
+}
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
+bool
+wasm_interp_create_call_stack(struct WASMExecEnv *exec_env);
+
+/**
+ * @brief Dump wasm call stack or get the size
+ *
+ * @param exec_env the execution environment
+ * @param print whether to print to stdout or not
+ * @param buf buffer to store the dumped content
+ * @param len length of the buffer
+ *
+ * @return when print is true, return the bytes printed out to stdout; when
+ * print is false and buf is NULL, return the size required to store the
+ * callstack content; when print is false and buf is not NULL, return the size
+ * dumped to the buffer, 0 means error and data in buf may be invalid
+ */
+uint32
+wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
+ uint32 len);
+#endif
+
+const uint8 *
+wasm_loader_get_custom_section(WASMModule *module, const char *name,
+ uint32 *len);
+
+#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0
+void
+jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id);
+
+/**
+ * Check whether the app address and the buf is inside the linear memory,
+ * and convert the app address into native address
+ */
+bool
+jit_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
+ uint32 app_buf_addr, uint32 app_buf_size,
+ void **p_native_addr);
+#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
+ || WASM_ENABLE_WAMR_COMPILER != 0 */
+
+#if WASM_ENABLE_FAST_JIT != 0
+bool
+fast_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 type_idx, uint32 argc, uint32 *argv);
+
+bool
+fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
+ struct WASMInterpFrame *prev_frame);
+#endif
+
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+bool
+llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
+ uint32 argc, uint32 *argv);
+
+bool
+llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
+ uint32 *argv);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index,
+ uint32 offset, uint32 len, uint32 dst);
+
+bool
+llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index);
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+void
+llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx);
+
+void
+llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 tbl_seg_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset);
+
+void
+llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx,
+ uint32 dst_tbl_idx, uint32 length, uint32 src_offset,
+ uint32 dst_offset);
+
+void
+llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 length, uint32 val, uint32 data_offset);
+
+uint32
+llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
+ uint32 inc_entries, uint32 init_val);
+#endif
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
+bool
+llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
+
+void
+llvm_jit_free_frame(WASMExecEnv *exec_env);
+#endif
+#endif /* end of WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 */
+
+#if WASM_ENABLE_LIBC_WASI != 0 && WASM_ENABLE_MULTI_MODULE != 0
+void
+wasm_propagate_wasi_args(WASMModule *module);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_RUNTIME_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c
new file mode 100644
index 000000000..1b3db1d49
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "debug_engine.h"
+#include "gdbserver.h"
+#include "handler.h"
+#include "bh_platform.h"
+#include "wasm_interp.h"
+#include "wasm_opcode.h"
+#include "wasm_runtime.h"
+
+static const uint8 break_instr[] = { DEBUG_OP_BREAK };
+
+typedef struct WASMDebugEngine {
+ struct WASMDebugEngine *next;
+ WASMDebugControlThread *control_thread;
+ char ip_addr[128];
+ int32 process_base_port;
+ bh_list debug_instance_list;
+ korp_mutex instance_list_lock;
+} WASMDebugEngine;
+
+void
+on_thread_stop_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&debug_inst->wait_lock);
+ debug_inst->stopped_thread = exec_env;
+
+ if (debug_inst->current_state == DBG_LAUNCHING) {
+ /* In launching phase, send a signal so that handle_threadstop_request
+ * can be woken up */
+ os_cond_signal(&debug_inst->wait_cond);
+ }
+ os_mutex_unlock(&debug_inst->wait_lock);
+}
+
+void
+on_thread_exit_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&debug_inst->wait_lock);
+
+ /* DBG_LAUNCHING: exit when debugger detached,
+ * DBG_ERROR: exit when debugger error */
+ if (debug_inst->current_state != DBG_LAUNCHING
+ && debug_inst->current_state != DBG_ERROR) {
+ /* only when exit normally the debugger thread will participate in
+ * teardown phase */
+ debug_inst->stopped_thread = exec_env;
+ }
+
+ os_mutex_unlock(&debug_inst->wait_lock);
+}
+
+static WASMDebugEngine *g_debug_engine;
+
+static uint32 current_instance_id = 1;
+
+static uint32
+allocate_instance_id()
+{
+ uint32 id;
+
+ bh_assert(g_debug_engine);
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ id = current_instance_id++;
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+
+ return id;
+}
+
+static bool
+is_thread_running(WASMDebugControlThread *control_thread)
+{
+ return control_thread->status == RUNNING;
+}
+
+static bool
+is_thread_stopped(WASMDebugControlThread *control_thread)
+{
+ return control_thread->status == STOPPED;
+}
+
+static bool
+is_thread_detached(WASMDebugControlThread *control_thread)
+{
+ return control_thread->status == DETACHED;
+}
+
+static void *
+control_thread_routine(void *arg)
+{
+ WASMDebugInstance *debug_inst = (WASMDebugInstance *)arg;
+ WASMDebugControlThread *control_thread = NULL;
+
+ control_thread = debug_inst->control_thread;
+ bh_assert(control_thread);
+
+ os_mutex_lock(&debug_inst->wait_lock);
+
+ control_thread->status = RUNNING;
+
+ debug_inst->id = allocate_instance_id();
+
+ control_thread->debug_engine = g_debug_engine;
+ control_thread->debug_instance = debug_inst;
+ bh_strcpy_s(control_thread->ip_addr, sizeof(control_thread->ip_addr),
+ g_debug_engine->ip_addr);
+ if (control_thread->port == -1) {
+ control_thread->port =
+ (g_debug_engine->process_base_port == 0)
+ ? 0
+ : g_debug_engine->process_base_port + debug_inst->id - 1;
+ }
+
+ LOG_WARNING("control thread of debug object %p start\n", debug_inst);
+
+ control_thread->server =
+ wasm_create_gdbserver(control_thread->ip_addr, &control_thread->port);
+
+ if (!control_thread->server) {
+ LOG_ERROR("Failed to create debug server\n");
+ control_thread->port = 0;
+ os_cond_signal(&debug_inst->wait_cond);
+ os_mutex_unlock(&debug_inst->wait_lock);
+ return NULL;
+ }
+
+ control_thread->server->thread = control_thread;
+
+ /*
+ * wasm gdbserver created, the execution thread
+ * doesn't need to wait for the debugger connection,
+ * so we wake up the execution thread before listen
+ */
+ os_cond_signal(&debug_inst->wait_cond);
+ os_mutex_unlock(&debug_inst->wait_lock);
+
+ if (!wasm_gdbserver_listen(control_thread->server)) {
+ LOG_ERROR("Failed while listening for debugger\n");
+ goto fail;
+ }
+
+ /* outer infinite loop: try to connect with the debugger */
+ while (true) {
+ /* wait lldb client to connect */
+ if (!wasm_gdbserver_accept(control_thread->server)) {
+ LOG_ERROR("Failed while accepting debugger connection\n");
+ goto fail;
+ }
+
+ control_thread->status = RUNNING;
+ /* when reattached, send signal */
+ wasm_cluster_send_signal_all(debug_inst->cluster, WAMR_SIG_SINGSTEP);
+
+ /* inner infinite loop: keep serving until detach */
+ while (true) {
+ os_mutex_lock(&control_thread->wait_lock);
+ if (is_thread_running(control_thread)) {
+ /* send thread stop reply */
+ if (debug_inst->stopped_thread
+ && debug_inst->current_state == APP_RUNNING) {
+ uint32 status;
+ korp_tid tid;
+
+ status = (uint32)debug_inst->stopped_thread->current_status
+ ->signal_flag;
+ tid = debug_inst->stopped_thread->handle;
+
+ if (debug_inst->stopped_thread->current_status
+ ->running_status
+ == STATUS_EXIT) {
+ /* If the thread exits, report "W00" if it's the last
+ * thread in the cluster, otherwise ignore this event */
+ status = 0;
+
+ /* By design, all the other threads should have been
+ * stopped at this moment, so it is safe to access the
+ * exec_env_list.len without lock */
+ if (debug_inst->cluster->exec_env_list.len != 1) {
+ debug_inst->stopped_thread = NULL;
+ /* The exiting thread may wait for the signal */
+ os_cond_signal(&debug_inst->wait_cond);
+ os_mutex_unlock(&control_thread->wait_lock);
+ continue;
+ }
+ }
+
+ wasm_debug_instance_set_cur_thread(
+ debug_inst, debug_inst->stopped_thread->handle);
+
+ send_thread_stop_status(control_thread->server, status,
+ tid);
+
+ debug_inst->current_state = APP_STOPPED;
+ debug_inst->stopped_thread = NULL;
+
+ if (status == 0) {
+ /* The exiting thread may wait for the signal */
+ os_cond_signal(&debug_inst->wait_cond);
+ }
+ }
+
+ /* Processing incoming requests */
+ if (!wasm_gdbserver_handle_packet(control_thread->server)) {
+ control_thread->status = STOPPED;
+ LOG_ERROR("An error occurs when handling a packet\n");
+ os_mutex_unlock(&control_thread->wait_lock);
+ goto fail;
+ }
+ }
+ else if (is_thread_detached(control_thread)) {
+ os_mutex_unlock(&control_thread->wait_lock);
+ break;
+ }
+ else if (is_thread_stopped(control_thread)) {
+ os_mutex_unlock(&control_thread->wait_lock);
+ return NULL;
+ }
+ os_mutex_unlock(&control_thread->wait_lock);
+ }
+ }
+fail:
+ wasm_debug_instance_on_failure(debug_inst);
+ LOG_VERBOSE("control thread of debug object [%p] stopped with failure\n",
+ debug_inst);
+ return NULL;
+}
+
+static WASMDebugControlThread *
+wasm_debug_control_thread_create(WASMDebugInstance *debug_instance, int32 port)
+{
+ WASMDebugControlThread *control_thread;
+
+ if (!(control_thread =
+ wasm_runtime_malloc(sizeof(WASMDebugControlThread)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(control_thread, 0, sizeof(WASMDebugControlThread));
+ control_thread->port = port;
+
+ if (os_mutex_init(&control_thread->wait_lock) != 0)
+ goto fail;
+
+ debug_instance->control_thread = control_thread;
+
+ os_mutex_lock(&debug_instance->wait_lock);
+
+ if (0
+ != os_thread_create(&control_thread->tid, control_thread_routine,
+ debug_instance, APP_THREAD_STACK_SIZE_DEFAULT)) {
+ os_mutex_unlock(&debug_instance->wait_lock);
+ goto fail1;
+ }
+
+ /* wait until the debug control thread ready */
+ os_cond_wait(&debug_instance->wait_cond, &debug_instance->wait_lock);
+ os_mutex_unlock(&debug_instance->wait_lock);
+ if (!control_thread->server) {
+ os_thread_join(control_thread->tid, NULL);
+ goto fail1;
+ }
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ /* create control thread success, append debug instance to debug engine */
+ bh_list_insert(&g_debug_engine->debug_instance_list, debug_instance);
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+
+ /* If we set WAMR_SIG_STOP here, the VSCode debugger adaptor will raise an
+ * exception in the UI. We use WAMR_SIG_SINGSTEP to avoid this exception for
+ * better user experience */
+ wasm_cluster_send_signal_all(debug_instance->cluster, WAMR_SIG_SINGSTEP);
+
+ return control_thread;
+
+fail1:
+ os_mutex_destroy(&control_thread->wait_lock);
+fail:
+ wasm_runtime_free(control_thread);
+ return NULL;
+}
+
+static void
+wasm_debug_control_thread_destroy(WASMDebugInstance *debug_instance)
+{
+ WASMDebugControlThread *control_thread = debug_instance->control_thread;
+
+ LOG_VERBOSE("stopping control thread of debug object [%p]\n",
+ debug_instance);
+ control_thread->status = STOPPED;
+ os_mutex_lock(&control_thread->wait_lock);
+ wasm_close_gdbserver(control_thread->server);
+ os_mutex_unlock(&control_thread->wait_lock);
+ os_thread_join(control_thread->tid, NULL);
+ wasm_runtime_free(control_thread->server);
+
+ os_mutex_destroy(&control_thread->wait_lock);
+ wasm_runtime_free(control_thread);
+}
+
+static WASMDebugEngine *
+wasm_debug_engine_create()
+{
+ WASMDebugEngine *engine;
+
+ if (!(engine = wasm_runtime_malloc(sizeof(WASMDebugEngine)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(engine, 0, sizeof(WASMDebugEngine));
+
+ if (os_mutex_init(&engine->instance_list_lock) != 0) {
+ wasm_runtime_free(engine);
+ LOG_ERROR("WASM Debug Engine error: failed to init mutex");
+ return NULL;
+ }
+
+ /* reset current instance id */
+ current_instance_id = 1;
+
+ bh_list_init(&engine->debug_instance_list);
+ return engine;
+}
+
+void
+wasm_debug_engine_destroy()
+{
+ if (g_debug_engine) {
+ wasm_debug_handler_deinit();
+ os_mutex_destroy(&g_debug_engine->instance_list_lock);
+ wasm_runtime_free(g_debug_engine);
+ g_debug_engine = NULL;
+ }
+}
+
+bool
+wasm_debug_engine_init(char *ip_addr, int32 process_port)
+{
+ if (wasm_debug_handler_init() != 0) {
+ return false;
+ }
+
+ if (g_debug_engine == NULL) {
+ g_debug_engine = wasm_debug_engine_create();
+ }
+
+ if (g_debug_engine) {
+ g_debug_engine->process_base_port =
+ (process_port > 0) ? process_port : 0;
+ if (ip_addr)
+ snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
+ "%s", ip_addr);
+ else
+ snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
+ "%s", "127.0.0.1");
+ }
+ else {
+ wasm_debug_handler_deinit();
+ }
+
+ return g_debug_engine != NULL ? true : false;
+}
+
+/* A debug Instance is a debug "process" in gdb remote protocol
+ and bound to a runtime cluster */
+WASMDebugInstance *
+wasm_debug_instance_create(WASMCluster *cluster, int32 port)
+{
+ WASMDebugInstance *instance;
+ WASMExecEnv *exec_env = NULL;
+ wasm_module_inst_t module_inst = NULL;
+
+ if (!g_debug_engine) {
+ return NULL;
+ }
+
+ if (!(instance = wasm_runtime_malloc(sizeof(WASMDebugInstance)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(instance, 0, sizeof(WASMDebugInstance));
+
+ if (os_mutex_init(&instance->wait_lock) != 0) {
+ goto fail1;
+ }
+
+ if (os_cond_init(&instance->wait_cond) != 0) {
+ goto fail2;
+ }
+
+ bh_list_init(&instance->break_point_list);
+ bh_list_init(&instance->watch_point_list_read);
+ bh_list_init(&instance->watch_point_list_write);
+
+ instance->cluster = cluster;
+ exec_env = bh_list_first_elem(&cluster->exec_env_list);
+ bh_assert(exec_env);
+
+ instance->current_tid = exec_env->handle;
+
+ module_inst = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(module_inst);
+
+ /* Allocate linear memory for evaluating expressions during debugging. If
+ * the allocation failed, the debugger will not be able to evaluate
+ * expressions */
+ instance->exec_mem_info.size = DEBUG_EXECUTION_MEMORY_SIZE;
+ instance->exec_mem_info.start_offset = wasm_runtime_module_malloc(
+ module_inst, instance->exec_mem_info.size, NULL);
+ if (instance->exec_mem_info.start_offset == 0) {
+ LOG_WARNING(
+ "WASM Debug Engine warning: failed to allocate linear memory for "
+ "execution. \n"
+ "Will not be able to evaluate expressions during "
+ "debugging");
+ }
+ instance->exec_mem_info.current_pos = instance->exec_mem_info.start_offset;
+
+ if (!wasm_debug_control_thread_create(instance, port)) {
+ LOG_ERROR("WASM Debug Engine error: failed to create control thread");
+ goto fail3;
+ }
+
+ wasm_cluster_set_debug_inst(cluster, instance);
+
+ return instance;
+
+fail3:
+ os_cond_destroy(&instance->wait_cond);
+fail2:
+ os_mutex_destroy(&instance->wait_lock);
+fail1:
+ wasm_runtime_free(instance);
+
+ return NULL;
+}
+
+static void
+wasm_debug_instance_destroy_breakpoints(WASMDebugInstance *instance)
+{
+ WASMDebugBreakPoint *breakpoint, *next_bp;
+
+ breakpoint = bh_list_first_elem(&instance->break_point_list);
+ while (breakpoint) {
+ next_bp = bh_list_elem_next(breakpoint);
+
+ bh_list_remove(&instance->break_point_list, breakpoint);
+ wasm_runtime_free(breakpoint);
+
+ breakpoint = next_bp;
+ }
+}
+
+static void
+wasm_debug_instance_destroy_watchpoints(WASMDebugInstance *instance,
+ bh_list *watchpoints)
+{
+ WASMDebugWatchPoint *watchpoint, *next;
+
+ watchpoint = bh_list_first_elem(watchpoints);
+ while (watchpoint) {
+ next = bh_list_elem_next(watchpoint);
+
+ bh_list_remove(watchpoints, watchpoint);
+ wasm_runtime_free(watchpoint);
+
+ watchpoint = next;
+ }
+}
+
+void
+wasm_debug_instance_destroy(WASMCluster *cluster)
+{
+ WASMDebugInstance *instance = NULL;
+
+ if (!g_debug_engine) {
+ return;
+ }
+
+ instance = cluster->debug_inst;
+ if (instance) {
+ /* destroy control thread */
+ wasm_debug_control_thread_destroy(instance);
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ bh_list_remove(&g_debug_engine->debug_instance_list, instance);
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+
+ /* destroy all breakpoints */
+ wasm_debug_instance_destroy_breakpoints(instance);
+ wasm_debug_instance_destroy_watchpoints(
+ instance, &instance->watch_point_list_read);
+ wasm_debug_instance_destroy_watchpoints(
+ instance, &instance->watch_point_list_write);
+
+ os_mutex_destroy(&instance->wait_lock);
+ os_cond_destroy(&instance->wait_cond);
+
+ wasm_runtime_free(instance);
+ cluster->debug_inst = NULL;
+ }
+}
+
+WASMExecEnv *
+wasm_debug_instance_get_current_env(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env = NULL;
+
+ if (instance) {
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env) {
+ if (exec_env->handle == instance->current_tid)
+ break;
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ }
+ return exec_env;
+}
+
+#if WASM_ENABLE_LIBC_WASI != 0
+bool
+wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
+ char name_buffer[], uint32 len)
+{
+ WASMExecEnv *exec_env;
+ WASIArguments *wasi_args;
+ WASMModuleInstance *module_inst;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ wasi_args = &module_inst->module->wasi_args;
+ if (wasi_args && wasi_args->argc > 0) {
+ char *argv_name = wasi_args->argv[0];
+ uint32 name_len = (uint32)strlen(argv_name);
+
+ printf("the module name is %s\n", argv_name);
+ if (len - 1 >= name_len)
+ bh_strcpy_s(name_buffer, len, argv_name);
+ else
+ bh_strcpy_s(name_buffer, len, argv_name + (name_len + 1 - len));
+ return true;
+ }
+ return false;
+}
+#endif
+
+uint64
+wasm_debug_instance_get_pid(WASMDebugInstance *instance)
+{
+ if (instance != NULL) {
+ return (uint64)instance->id;
+ }
+ return (uint64)0;
+}
+
+korp_tid
+wasm_debug_instance_get_tid(WASMDebugInstance *instance)
+{
+ if (instance != NULL) {
+ return instance->current_tid;
+ }
+ return (korp_tid)(uintptr_t)0;
+}
+
+uint32
+wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
+ uint32 len)
+{
+ WASMExecEnv *exec_env;
+ uint32 i = 0, threads_num = 0;
+
+ if (!instance)
+ return 0;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env && i < len) {
+ /* Some threads may not be ready */
+ if (exec_env->handle != 0) {
+ tids[i++] = exec_env->handle;
+ threads_num++;
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ LOG_VERBOSE("find %d tids\n", threads_num);
+ return threads_num;
+}
+
+uint32
+wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, korp_tid tid)
+{
+ WASMExecEnv *exec_env = NULL;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env) {
+ if (exec_env->handle == tid) {
+ return (uint32)exec_env->current_status->signal_flag;
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ return 0;
+}
+
+void
+wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid)
+{
+ instance->current_tid = tid;
+}
+
+uint64
+wasm_debug_instance_get_pc(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return 0;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if ((exec_env != NULL) && (exec_env->cur_frame != NULL)
+ && (exec_env->cur_frame->ip != NULL)) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ return WASM_ADDR(
+ WasmObj, instance->id,
+ (exec_env->cur_frame->ip - module_inst->module->load_addr));
+ }
+ return 0;
+}
+
+uint64
+wasm_debug_instance_get_load_addr(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return WASM_ADDR(WasmInvalid, 0, 0);
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (exec_env) {
+ return WASM_ADDR(WasmObj, instance->id, 0);
+ }
+
+ return WASM_ADDR(WasmInvalid, 0, 0);
+}
+
+WASMDebugMemoryInfo *
+wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr)
+{
+ WASMDebugMemoryInfo *mem_info;
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory;
+ uint32 num_bytes_per_page;
+ uint32 linear_mem_size = 0;
+
+ if (!instance)
+ return NULL;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return NULL;
+
+ if (!(mem_info = wasm_runtime_malloc(sizeof(WASMDebugMemoryInfo)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(mem_info, 0, sizeof(WASMDebugMemoryInfo));
+ mem_info->start = WASM_ADDR(WasmInvalid, 0, 0);
+ mem_info->size = 0;
+ mem_info->name[0] = '\0';
+ mem_info->permisson[0] = '\0';
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+
+ switch (WASM_ADDR_TYPE(addr)) {
+ case WasmObj:
+ if (WASM_ADDR_OFFSET(addr) < module_inst->module->load_size) {
+ mem_info->start = WASM_ADDR(WasmObj, instance->id, 0);
+ mem_info->size = module_inst->module->load_size;
+ snprintf(mem_info->name, sizeof(mem_info->name), "%s",
+ "module");
+ snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
+ "rx");
+ }
+ break;
+ case WasmMemory:
+ {
+ memory = wasm_get_default_memory(module_inst);
+
+ if (memory) {
+ num_bytes_per_page = memory->num_bytes_per_page;
+ linear_mem_size = num_bytes_per_page * memory->cur_page_count;
+ }
+ if (WASM_ADDR_OFFSET(addr) < linear_mem_size) {
+ mem_info->start = WASM_ADDR(WasmMemory, instance->id, 0);
+ mem_info->size = linear_mem_size;
+ snprintf(mem_info->name, sizeof(mem_info->name), "%s",
+ "memory");
+ snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
+ "rw");
+ }
+ break;
+ }
+ default:
+ mem_info->start = WASM_ADDR(WasmInvalid, 0, 0);
+ mem_info->size = 0;
+ }
+ return mem_info;
+}
+
+void
+wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance,
+ WASMDebugMemoryInfo *mem_info)
+{
+ wasm_runtime_free(mem_info);
+}
+
+bool
+wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
+ char *buf, uint64 *size)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMDebugBreakPoint *breakpoint;
+ WASMFastOPCodeNode *fast_opcode;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+
+ if (offset + *size > module_inst->module->load_size) {
+ LOG_VERBOSE("wasm_debug_instance_get_data_mem size over flow!\n");
+ *size = module_inst->module->load_size >= offset
+ ? module_inst->module->load_size - offset
+ : 0;
+ }
+
+ bh_memcpy_s(buf, (uint32)*size, module_inst->module->load_addr + offset,
+ (uint32)*size);
+
+ breakpoint = bh_list_first_elem(&instance->break_point_list);
+ while (breakpoint) {
+ if (offset <= breakpoint->addr && breakpoint->addr < offset + *size) {
+ bh_memcpy_s(buf + (breakpoint->addr - offset), sizeof(break_instr),
+ &breakpoint->orignal_data, sizeof(break_instr));
+ }
+ breakpoint = bh_list_elem_next(breakpoint);
+ }
+
+ fast_opcode = bh_list_first_elem(&module_inst->module->fast_opcode_list);
+ while (fast_opcode) {
+ if (offset <= fast_opcode->offset
+ && fast_opcode->offset < offset + *size) {
+ *(uint8 *)(buf + (fast_opcode->offset - offset)) =
+ fast_opcode->orig_op;
+ }
+ fast_opcode = bh_list_elem_next(fast_opcode);
+ }
+
+ return true;
+}
+
+bool
+wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset,
+ char *buf, uint64 *size)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory;
+ uint32 num_bytes_per_page;
+ uint32 linear_mem_size;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ memory = wasm_get_default_memory(module_inst);
+ if (memory) {
+ num_bytes_per_page = memory->num_bytes_per_page;
+ linear_mem_size = num_bytes_per_page * memory->cur_page_count;
+ if (offset + *size > linear_mem_size) {
+ LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
+ *size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
+ }
+ bh_memcpy_s(buf, (uint32)*size, memory->memory_data + offset,
+ (uint32)*size);
+ return true;
+ }
+ return false;
+}
+
+bool
+wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset,
+ char *buf, uint64 *size)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory;
+ uint32 num_bytes_per_page;
+ uint32 linear_mem_size;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ memory = wasm_get_default_memory(module_inst);
+ if (memory) {
+ num_bytes_per_page = memory->num_bytes_per_page;
+ linear_mem_size = num_bytes_per_page * memory->cur_page_count;
+ if (offset + *size > linear_mem_size) {
+ LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
+ *size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
+ }
+ bh_memcpy_s(memory->memory_data + offset, (uint32)*size, buf,
+ (uint32)*size);
+ return true;
+ }
+ return false;
+}
+
+bool
+wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size)
+{
+ switch (WASM_ADDR_TYPE(addr)) {
+ case WasmMemory:
+ return wasm_debug_instance_get_linear_mem(
+ instance, WASM_ADDR_OFFSET(addr), buf, size);
+ break;
+ case WasmObj:
+ return wasm_debug_instance_get_obj_mem(
+ instance, WASM_ADDR_OFFSET(addr), buf, size);
+ break;
+ default:
+ return false;
+ }
+}
+
+bool
+wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size)
+{
+ switch (WASM_ADDR_TYPE(addr)) {
+ case WasmMemory:
+ return wasm_debug_instance_set_linear_mem(
+ instance, WASM_ADDR_OFFSET(addr), buf, size);
+ break;
+ case WasmObj:
+ default:
+ return false;
+ }
+}
+
+WASMDebugInstance *
+wasm_exec_env_get_instance(WASMExecEnv *exec_env)
+{
+ WASMDebugInstance *instance = NULL;
+
+ if (!g_debug_engine) {
+ return NULL;
+ }
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ instance = bh_list_first_elem(&g_debug_engine->debug_instance_list);
+ while (instance) {
+ if (instance->cluster == exec_env->cluster)
+ break;
+ instance = bh_list_elem_next(instance);
+ }
+
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+ return instance;
+}
+
+uint32
+wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
+ korp_tid tid, uint64 buf[], uint64 size)
+{
+ WASMExecEnv *exec_env;
+ struct WASMInterpFrame *frame;
+ uint32 i = 0;
+
+ if (!instance)
+ return 0;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env) {
+ if (exec_env->handle == tid) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ frame = exec_env->cur_frame;
+ while (frame && i < size) {
+ if (frame->ip != NULL) {
+ buf[i++] =
+ WASM_ADDR(WasmObj, instance->id,
+ (frame->ip - module_inst->module->load_addr));
+ }
+ frame = frame->prev_frame;
+ }
+ return i;
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ return 0;
+}
+
+bool
+wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ uint64 offset;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ if (WASM_ADDR_TYPE(addr) != WasmObj)
+ return false;
+
+ offset = WASM_ADDR_OFFSET(addr);
+
+ if (length >= sizeof(break_instr)) {
+ if (offset + sizeof(break_instr) <= module_inst->module->load_size) {
+ WASMDebugBreakPoint *breakpoint;
+ if (!(breakpoint =
+ wasm_runtime_malloc(sizeof(WASMDebugBreakPoint)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return false;
+ }
+ memset(breakpoint, 0, sizeof(WASMDebugBreakPoint));
+ breakpoint->addr = offset;
+ /* TODO: how to if more than one breakpoints are set
+ at the same addr? */
+ bh_memcpy_s(&breakpoint->orignal_data, (uint32)sizeof(break_instr),
+ module_inst->module->load_addr + offset,
+ (uint32)sizeof(break_instr));
+
+ bh_memcpy_s(module_inst->module->load_addr + offset,
+ (uint32)sizeof(break_instr), break_instr,
+ (uint32)sizeof(break_instr));
+
+ bh_list_insert(&instance->break_point_list, breakpoint);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ uint64 offset;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+
+ if (WASM_ADDR_TYPE(addr) != WasmObj)
+ return false;
+ offset = WASM_ADDR_OFFSET(addr);
+
+ if (length >= sizeof(break_instr)) {
+ if (offset + sizeof(break_instr) <= module_inst->module->load_size) {
+ WASMDebugBreakPoint *breakpoint =
+ bh_list_first_elem(&instance->break_point_list);
+ while (breakpoint) {
+ WASMDebugBreakPoint *next_break = bh_list_elem_next(breakpoint);
+ if (breakpoint->addr == offset) {
+ /* TODO: how to if more than one breakpoints are set
+ at the same addr? */
+ bh_memcpy_s(module_inst->module->load_addr + offset,
+ (uint32)sizeof(break_instr),
+ &breakpoint->orignal_data,
+ (uint32)sizeof(break_instr));
+ bh_list_remove(&instance->break_point_list, breakpoint);
+ wasm_runtime_free(breakpoint);
+ }
+ breakpoint = next_break;
+ }
+ }
+ }
+ return true;
+}
+
+static bool
+add_watchpoint(bh_list *list, uint64 addr, uint64 length)
+{
+ WASMDebugWatchPoint *watchpoint;
+ if (!(watchpoint = wasm_runtime_malloc(sizeof(WASMDebugWatchPoint)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory for "
+ "watchpoint");
+ return false;
+ }
+ memset(watchpoint, 0, sizeof(WASMDebugWatchPoint));
+ watchpoint->addr = addr;
+ watchpoint->length = length;
+ bh_list_insert(list, watchpoint);
+ return true;
+}
+
+static bool
+remove_watchpoint(bh_list *list, uint64 addr, uint64 length)
+{
+ WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list);
+ while (watchpoint) {
+ WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint);
+ if (watchpoint->addr == addr && watchpoint->length == length) {
+ bh_list_remove(list, watchpoint);
+ wasm_runtime_free(watchpoint);
+ }
+ watchpoint = next;
+ }
+ return true;
+}
+
+bool
+wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return add_watchpoint(&instance->watch_point_list_write, addr, length);
+}
+
+bool
+wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return remove_watchpoint(&instance->watch_point_list_write, addr, length);
+}
+
+bool
+wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return add_watchpoint(&instance->watch_point_list_read, addr, length);
+}
+
+bool
+wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return remove_watchpoint(&instance->watch_point_list_read, addr, length);
+}
+
+bool
+wasm_debug_instance_on_failure(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ os_mutex_lock(&instance->wait_lock);
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env) {
+ os_mutex_unlock(&instance->wait_lock);
+ return false;
+ }
+
+ if (instance->stopped_thread == NULL
+ && instance->current_state == DBG_LAUNCHING) {
+ /* if fail in start stage: may need wait for main thread to notify it */
+ os_cond_wait(&instance->wait_cond, &instance->wait_lock);
+ }
+ instance->current_state = DBG_ERROR;
+ instance->stopped_thread = NULL;
+
+ /* terminate the wasm execution thread */
+ while (exec_env) {
+ /* Resume all threads so they can receive the TERM signal */
+ os_mutex_lock(&exec_env->wait_lock);
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
+ exec_env->current_status->running_status = STATUS_RUNNING;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ os_mutex_unlock(&instance->wait_lock);
+
+ return true;
+}
+
+bool
+wasm_debug_instance_continue(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ if (instance->current_state == APP_RUNNING) {
+ LOG_VERBOSE("Already in running state, ignore continue request");
+ return false;
+ }
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ wasm_cluster_thread_continue(exec_env);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ instance->current_state = APP_RUNNING;
+
+ return true;
+}
+
+bool
+wasm_debug_instance_interrupt_all_threads(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ return true;
+}
+
+bool
+wasm_debug_instance_detach(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ wasm_gdbserver_detach(instance->control_thread->server);
+
+ while (exec_env) {
+ if (instance->current_state == APP_STOPPED) {
+ /* Resume all threads since remote debugger detached*/
+ wasm_cluster_thread_continue(exec_env);
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ /* relaunch, accept new debug connection */
+ instance->current_state = DBG_LAUNCHING;
+ instance->control_thread->status = DETACHED;
+ instance->stopped_thread = NULL;
+
+ return true;
+}
+
+bool
+wasm_debug_instance_kill(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
+ if (instance->current_state == APP_STOPPED) {
+ /* Resume all threads so they can receive the TERM signal */
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->current_status->running_status = STATUS_RUNNING;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ instance->current_state = APP_RUNNING;
+ return true;
+}
+
+bool
+wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ if (instance->current_state == APP_RUNNING) {
+ LOG_VERBOSE("Already in running state, ignore step request");
+ return false;
+ }
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ if (exec_env->handle == tid || tid == (korp_tid)(uintptr_t)~0LL) {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_SINGSTEP);
+ wasm_cluster_thread_step(exec_env);
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ instance->current_state = APP_RUNNING;
+
+ return true;
+}
+
+bool
+wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
+ int32 local_index, char buf[], int32 *size)
+{
+ WASMExecEnv *exec_env;
+ struct WASMInterpFrame *frame;
+ WASMFunctionInstance *cur_func;
+ uint8 local_type = 0xFF;
+ uint32 local_offset;
+ int32 param_count;
+ int32 fi = 0;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ frame = exec_env->cur_frame;
+ while (frame && fi++ != frame_index) {
+ frame = frame->prev_frame;
+ }
+
+ if (!frame)
+ return false;
+ cur_func = frame->function;
+ if (!cur_func)
+ return false;
+
+ param_count = cur_func->param_count;
+
+ if (local_index >= param_count + cur_func->local_count)
+ return false;
+
+ local_offset = cur_func->local_offsets[local_index];
+ if (local_index < param_count)
+ local_type = cur_func->param_types[local_index];
+ else if (local_index < cur_func->local_count + param_count)
+ local_type = cur_func->local_types[local_index - param_count];
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+ *size = 4;
+ bh_memcpy_s(buf, 4, (char *)(frame->lp + local_offset), 4);
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ *size = 8;
+ bh_memcpy_s(buf, 8, (char *)(frame->lp + local_offset), 8);
+ break;
+ default:
+ *size = 0;
+ break;
+ }
+ return true;
+}
+
+bool
+wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
+ int32 global_index, char buf[], int32 *size)
+{
+ WASMExecEnv *exec_env;
+ struct WASMInterpFrame *frame;
+ WASMModuleInstance *module_inst;
+ WASMGlobalInstance *globals, *global;
+ uint8 *global_addr;
+ uint8 global_type = 0xFF;
+ uint8 *global_data;
+ int32 fi = 0;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ frame = exec_env->cur_frame;
+ while (frame && fi++ != frame_index) {
+ frame = frame->prev_frame;
+ }
+
+ if (!frame)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ global_data = module_inst->global_data;
+ globals = module_inst->e->globals;
+
+ if ((global_index < 0)
+ || ((uint32)global_index >= module_inst->e->global_count)) {
+ return false;
+ }
+ global = globals + global_index;
+
+#if WASM_ENABLE_MULTI_MODULE == 0
+ global_addr = global_data + global->data_offset;
+#else
+ global_addr = global->import_global_inst
+ ? global->import_module_inst->global_data
+ + global->import_global_inst->data_offset
+ : global_data + global->data_offset;
+#endif
+ global_type = global->type;
+
+ switch (global_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+ *size = 4;
+ bh_memcpy_s(buf, 4, (char *)(global_addr), 4);
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ *size = 8;
+ bh_memcpy_s(buf, 8, (char *)(global_addr), 8);
+ break;
+ default:
+ *size = 0;
+ break;
+ }
+ return true;
+}
+
+uint64
+wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
+ int32 map_prot)
+{
+ WASMExecEnv *exec_env;
+ uint32 offset = 0;
+ (void)map_prot;
+
+ if (!instance)
+ return 0;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return 0;
+
+ if (instance->exec_mem_info.start_offset == 0) {
+ return 0;
+ }
+
+ if ((uint64)instance->exec_mem_info.current_pos
+ - instance->exec_mem_info.start_offset + size
+ <= (uint64)instance->exec_mem_info.size) {
+ offset = instance->exec_mem_info.current_pos;
+ instance->exec_mem_info.current_pos += size;
+ }
+
+ if (offset == 0) {
+ LOG_WARNING("the memory may be not enough for debug, try use larger "
+ "--heap-size");
+ return 0;
+ }
+
+ return WASM_ADDR(WasmMemory, 0, offset);
+}
+
+bool
+wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ if (instance->exec_mem_info.start_offset == 0) {
+ return false;
+ }
+
+ (void)addr;
+
+ /* Currently we don't support to free the execution memory, simply return
+ * true here */
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake
new file mode 100644
index 000000000..914ddd639
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2021 Ant Group. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (DEBUG_ENGINE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_DEBUG_INTERP=1)
+
+include_directories(${DEBUG_ENGINE_DIR})
+
+file (GLOB source_all ${DEBUG_ENGINE_DIR}/*.c)
+
+set (DEBUG_ENGINE_SOURCE ${source_all})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h
new file mode 100644
index 000000000..e12f827bd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _DEBUG_ENGINE_H
+#define _DEBUG_ENGINE_H
+
+#include "bh_list.h"
+#include "gdbserver.h"
+#include "thread_manager.h"
+
+typedef enum WASMDebugControlThreadStatus {
+ RUNNING,
+ DETACHED,
+ STOPPED,
+} WASMDebugControlThreadStatus;
+
+struct WASMDebugEngine;
+struct WASMDebugInstance;
+
+typedef struct WASMDebugControlThread {
+ WASMGDBServer *server;
+ korp_tid tid;
+ korp_mutex wait_lock;
+ char ip_addr[128];
+ int port;
+ WASMDebugControlThreadStatus status;
+ struct WASMDebugEngine *debug_engine;
+ struct WASMDebugInstance *debug_instance;
+} WASMDebugControlThread;
+
+typedef struct WASMDebugBreakPoint {
+ struct WASMDebugBreakPoint *next;
+ uint64 addr;
+ uint64 orignal_data;
+} WASMDebugBreakPoint;
+
+typedef struct WASMDebugWatchPoint {
+ bh_list_link next;
+ uint64 addr;
+ uint64 length;
+} WASMDebugWatchPoint;
+
+typedef enum debug_state_t {
+ /* Debugger state conversion sequence:
+ * DBG_LAUNCHING ---> APP_STOPPED <---> APP_RUNNING
+ */
+ DBG_LAUNCHING,
+ APP_RUNNING,
+ APP_STOPPED,
+ DBG_ERROR
+} debug_state_t;
+
+typedef struct WASMDebugExecutionMemory {
+ uint32 start_offset;
+ uint32 size;
+ uint32 current_pos;
+} WASMDebugExecutionMemory;
+
+struct WASMDebugInstance {
+ struct WASMDebugInstance *next;
+ WASMDebugControlThread *control_thread;
+ bh_list break_point_list;
+ bh_list watch_point_list_read;
+ bh_list watch_point_list_write;
+ WASMCluster *cluster;
+ uint32 id;
+ korp_tid current_tid;
+ korp_mutex wait_lock;
+ korp_cond wait_cond;
+ /* Last stopped thread, it should be set to NULL when sending
+ * out the thread stop reply */
+ WASMExecEnv *volatile stopped_thread;
+ /* Currently status of the debug instance, it will be set to
+ * RUNNING when receiving STEP/CONTINUE commands, and set to
+ * STOPPED when any thread stopped */
+ volatile debug_state_t current_state;
+ /* Execution memory info. During debugging, the debug client may request to
+ * malloc a memory space to evaluate user expressions. We preserve a buffer
+ * during creating debug instance, and use a simple bump pointer allocator
+ * to serve lldb's memory request */
+ WASMDebugExecutionMemory exec_mem_info;
+};
+
+typedef enum WASMDebugEventKind {
+ BREAK_POINT_ADD,
+ BREAK_POINT_REMOVE
+} WASMDebugEventKind;
+
+typedef struct WASMDebugEvent {
+ WASMDebugEventKind kind;
+ unsigned char metadata[0];
+} WASMDebugEvent;
+
+typedef struct WASMDebugMemoryInfo {
+ uint64 start;
+ uint64 size;
+ char name[128];
+ char permisson[4];
+} WASMDebugMemoryInfo;
+
+typedef enum WasmAddressType {
+ WasmMemory = 0x00,
+ WasmObj = 0x01,
+ WasmInvalid = 0x03
+} WasmAddressType;
+
+#define WASM_ADDR(type, id, offset) \
+ (((uint64)type << 62) | ((uint64)0 << 32) | ((uint64)offset << 0))
+
+#define WASM_ADDR_TYPE(addr) (((addr)&0xC000000000000000) >> 62)
+#define WASM_ADDR_OFFSET(addr) (((addr)&0x00000000FFFFFFFF))
+
+#define INVALIED_ADDR (0xFFFFFFFFFFFFFFFF)
+
+void
+on_thread_stop_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env);
+
+void
+on_thread_exit_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env);
+
+WASMDebugInstance *
+wasm_debug_instance_create(WASMCluster *cluster, int32 port);
+
+void
+wasm_debug_instance_destroy(WASMCluster *cluster);
+
+WASMDebugInstance *
+wasm_exec_env_get_instance(WASMExecEnv *exec_env);
+
+bool
+wasm_debug_engine_init(char *ip_addr, int32 process_port);
+
+void
+wasm_debug_engine_destroy();
+
+WASMExecEnv *
+wasm_debug_instance_get_current_env(WASMDebugInstance *instance);
+
+uint64
+wasm_debug_instance_get_pid(WASMDebugInstance *instance);
+
+korp_tid
+wasm_debug_instance_get_tid(WASMDebugInstance *instance);
+
+uint32
+wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
+ uint32 len);
+
+void
+wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid);
+
+uint64
+wasm_debug_instance_get_pc(WASMDebugInstance *instance);
+
+uint64
+wasm_debug_instance_get_load_addr(WASMDebugInstance *instance);
+
+WASMDebugMemoryInfo *
+wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr);
+
+void
+wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance,
+ WASMDebugMemoryInfo *mem_info);
+
+bool
+wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 addr,
+ char *buf, uint64 *size);
+
+bool
+wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 addr,
+ char *buf, uint64 *size);
+
+bool
+wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size);
+
+bool
+wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size);
+
+uint32
+wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
+ korp_tid tid, uint64 buf[], uint64 size);
+
+bool
+wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length);
+
+bool
+wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_on_failure(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_interrupt_all_threads(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_continue(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_detach(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_kill(WASMDebugInstance *instance);
+
+uint32
+wasm_debug_instance_get_thread_status(WASMDebugInstance *instance,
+ korp_tid tid);
+
+bool
+wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid);
+
+bool
+wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
+ int32 local_index, char buf[], int32 *size);
+
+bool
+wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
+ int32 global_index, char buf[], int32 *size);
+
+#if WASM_ENABLE_LIBC_WASI != 0
+bool
+wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
+ char name_buffer[], uint32 len);
+#endif
+
+uint64
+wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
+ int32 map_prot);
+
+bool
+wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr);
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c
new file mode 100644
index 000000000..fbd876ac3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "gdbserver.h"
+#include "handler.h"
+#include "packets.h"
+#include "utils.h"
+
+typedef void (*PacketHandler)(WASMGDBServer *server, char *payload);
+
+struct packet_handler_elem {
+ char request;
+ PacketHandler handler;
+};
+
+#define DEL_HANDLER(r, h) [r] = { .request = r, .handler = h }
+
+static const struct packet_handler_elem packet_handler_table[255] = {
+ DEL_HANDLER('Q', handle_general_set),
+ DEL_HANDLER('q', handle_general_query),
+ DEL_HANDLER('v', handle_v_packet),
+ DEL_HANDLER('?', handle_threadstop_request),
+ DEL_HANDLER('H', handle_set_current_thread),
+ DEL_HANDLER('p', handle_get_register),
+ DEL_HANDLER('j', handle_get_json_request),
+ DEL_HANDLER('m', handle_get_read_memory),
+ DEL_HANDLER('M', handle_get_write_memory),
+ DEL_HANDLER('x', handle_get_read_binary_memory),
+ DEL_HANDLER('Z', handle_add_break),
+ DEL_HANDLER('z', handle_remove_break),
+ DEL_HANDLER('c', handle_continue_request),
+ DEL_HANDLER('k', handle_kill_request),
+ DEL_HANDLER('_', handle____request),
+ DEL_HANDLER('D', handle_detach_request),
+};
+
+WASMGDBServer *
+wasm_create_gdbserver(const char *host, int32 *port)
+{
+ bh_socket_t listen_fd = (bh_socket_t)-1;
+ WASMGDBServer *server;
+
+ bh_assert(port);
+
+ if (!(server = wasm_runtime_malloc(sizeof(WASMGDBServer)))) {
+ LOG_ERROR("wasm gdb server error: failed to allocate memory");
+ return NULL;
+ }
+
+ memset(server, 0, sizeof(WASMGDBServer));
+
+ if (!(server->receive_ctx =
+ wasm_runtime_malloc(sizeof(rsp_recv_context_t)))) {
+ LOG_ERROR("wasm gdb server error: failed to allocate memory");
+ goto fail;
+ }
+
+ memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
+
+ if (0 != os_socket_create(&listen_fd, true, true)) {
+ LOG_ERROR("wasm gdb server error: create socket failed");
+ goto fail;
+ }
+
+ if (0 != os_socket_bind(listen_fd, host, port)) {
+ LOG_ERROR("wasm gdb server error: socket bind failed");
+ goto fail;
+ }
+
+ LOG_WARNING("Debug server listening on %s:%" PRIu32 "\n", host, *port);
+ server->listen_fd = listen_fd;
+
+ return server;
+
+fail:
+ if (listen_fd >= 0) {
+ os_socket_shutdown(listen_fd);
+ os_socket_close(listen_fd);
+ }
+ if (server->receive_ctx)
+ wasm_runtime_free(server->receive_ctx);
+ if (server)
+ wasm_runtime_free(server);
+ return NULL;
+}
+
+bool
+wasm_gdbserver_listen(WASMGDBServer *server)
+{
+ int32 ret;
+
+ ret = os_socket_listen(server->listen_fd, 1);
+ if (ret != 0) {
+ LOG_ERROR("wasm gdb server error: socket listen failed");
+ goto fail;
+ }
+
+ LOG_VERBOSE("listen for gdb client");
+ return true;
+
+fail:
+ os_socket_shutdown(server->listen_fd);
+ os_socket_close(server->listen_fd);
+ return false;
+}
+
+bool
+wasm_gdbserver_accept(WASMGDBServer *server)
+{
+
+ bh_socket_t sockt_fd = (bh_socket_t)-1;
+
+ LOG_VERBOSE("waiting for gdb client to connect...");
+
+ os_socket_accept(server->listen_fd, &sockt_fd, NULL, NULL);
+ if (sockt_fd < 0) {
+ LOG_ERROR("wasm gdb server error: socket accept failed");
+ goto fail;
+ }
+
+ LOG_VERBOSE("accept gdb client");
+ server->socket_fd = sockt_fd;
+ server->noack = false;
+ return true;
+
+fail:
+ os_socket_shutdown(server->listen_fd);
+ os_socket_close(server->listen_fd);
+ return false;
+}
+
+void
+wasm_gdbserver_detach(WASMGDBServer *server)
+{
+ if (server->socket_fd > 0) {
+ os_socket_shutdown(server->socket_fd);
+ os_socket_close(server->socket_fd);
+ }
+}
+
+void
+wasm_close_gdbserver(WASMGDBServer *server)
+{
+ if (server->receive_ctx) {
+ wasm_runtime_free(server->receive_ctx);
+ }
+ if (server->socket_fd > 0) {
+ os_socket_shutdown(server->socket_fd);
+ os_socket_close(server->socket_fd);
+ }
+ if (server->listen_fd > 0) {
+ os_socket_shutdown(server->listen_fd);
+ os_socket_close(server->listen_fd);
+ }
+}
+
+static inline void
+handle_packet(WASMGDBServer *server, char request, char *payload)
+{
+ if (packet_handler_table[(int)request].handler != NULL)
+ packet_handler_table[(int)request].handler(server, payload);
+}
+
+static void
+process_packet(WASMGDBServer *server)
+{
+ uint8 *inbuf = (uint8 *)server->receive_ctx->receive_buffer;
+ char request;
+ char *payload = NULL;
+
+ request = inbuf[0];
+
+ if (request == '\0') {
+ LOG_VERBOSE("ignore empty request");
+ return;
+ }
+
+ payload = (char *)&inbuf[1];
+
+ LOG_VERBOSE("receive request:%c %s\n", request, payload);
+ handle_packet(server, request, payload);
+}
+
+static inline void
+push_byte(rsp_recv_context_t *ctx, unsigned char ch, bool checksum)
+{
+ if (ctx->receive_index >= sizeof(ctx->receive_buffer)) {
+ LOG_ERROR("RSP message buffer overflow");
+ bh_assert(false);
+ return;
+ }
+
+ ctx->receive_buffer[ctx->receive_index++] = ch;
+
+ if (checksum) {
+ ctx->check_sum += ch;
+ }
+}
+
+/**
+ * The packet layout is:
+ * 1. Normal packet:
+ * '$' + payload + '#' + checksum(2bytes)
+ * ^
+ * packetend
+ * 2. Interrupt:
+ * 0x03
+ */
+
+/* return:
+ * 0: incomplete message received
+ * 1: complete message received
+ * 2: interrupt message received
+ */
+static int
+on_rsp_byte_arrive(unsigned char ch, rsp_recv_context_t *ctx)
+{
+ if (ctx->phase == Phase_Idle) {
+ ctx->receive_index = 0;
+ ctx->check_sum = 0;
+
+ if (ch == 0x03) {
+ LOG_VERBOSE("Receive interrupt package");
+ return 2;
+ }
+ else if (ch == '$') {
+ ctx->phase = Phase_Payload;
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Payload) {
+ if (ch == '#') {
+ ctx->phase = Phase_Checksum;
+ push_byte(ctx, ch, false);
+ }
+ else {
+ push_byte(ctx, ch, true);
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Checksum) {
+ ctx->size_in_phase++;
+ push_byte(ctx, ch, false);
+
+ if (ctx->size_in_phase == 2) {
+ ctx->size_in_phase = 0;
+
+ bh_assert(ctx->receive_index >= 3);
+
+ if ((hex(ctx->receive_buffer[ctx->receive_index - 2]) << 4
+ | hex(ctx->receive_buffer[ctx->receive_index - 1]))
+ != ctx->check_sum) {
+ LOG_WARNING("RSP package checksum error, ignore it");
+ ctx->phase = Phase_Idle;
+ return 0;
+ }
+ else {
+ /* Change # to \0 */
+ ctx->receive_buffer[ctx->receive_index - 3] = '\0';
+ ctx->phase = Phase_Idle;
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /* Should never reach here */
+ bh_assert(false);
+ return 0;
+}
+
+bool
+wasm_gdbserver_handle_packet(WASMGDBServer *server)
+{
+ int32 n;
+ char buf[1024];
+
+ if (os_socket_settimeout(server->socket_fd, 1000) != 0) {
+ LOG_ERROR("Set socket recv timeout failed");
+ return false;
+ }
+
+ n = os_socket_recv(server->socket_fd, buf, sizeof(buf));
+
+ if (n == 0) {
+ handle_detach_request(server, NULL);
+ LOG_VERBOSE("Debugger disconnected, waiting for debugger reconnection");
+ return true;
+ }
+ else if (n < 0) {
+#if defined(BH_PLATFORM_WINDOWS)
+ if (WSAGetLastError() == WSAETIMEDOUT)
+#else
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+#endif
+ {
+ /* No bytes arrived */
+ return true;
+ }
+ else {
+ LOG_ERROR("Socket receive error");
+ return false;
+ }
+ }
+ else {
+ int32 i, ret;
+
+ for (i = 0; i < n; i++) {
+ ret = on_rsp_byte_arrive(buf[i], server->receive_ctx);
+
+ if (ret == 1) {
+ if (!server->noack)
+ write_data_raw(server, (uint8 *)"+", 1);
+
+ process_packet(server);
+ }
+ else if (ret == 2) {
+ handle_interrupt(server);
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h
new file mode 100644
index 000000000..9e279a2e6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _GDB_SERVER_H
+#define _GDB_SERVER_H
+
+#include "bh_platform.h"
+
+#define PACKET_BUF_SIZE 0x8000
+
+enum GDBStoppointType {
+ eStoppointInvalid = -1,
+ eBreakpointSoftware = 0,
+ eBreakpointHardware,
+ eWatchpointWrite,
+ eWatchpointRead,
+ eWatchpointReadWrite
+};
+
+typedef enum rsp_recv_phase_t {
+ Phase_Idle,
+ Phase_Payload,
+ Phase_Checksum
+} rsp_recv_phase_t;
+
+/* Remote Serial Protocol Receive Context */
+typedef struct rsp_recv_context_t {
+ rsp_recv_phase_t phase;
+ uint16 receive_index;
+ uint16 size_in_phase;
+ uint8 check_sum;
+ /* RSP packet should not be too long */
+ char receive_buffer[1024];
+} rsp_recv_context_t;
+
+typedef struct WasmDebugPacket {
+ unsigned char buf[PACKET_BUF_SIZE];
+ uint32 size;
+} WasmDebugPacket;
+
+struct WASMDebugControlThread;
+typedef struct WASMGDBServer {
+ bh_socket_t listen_fd;
+ bh_socket_t socket_fd;
+ WasmDebugPacket pkt;
+ bool noack;
+ struct WASMDebugControlThread *thread;
+ rsp_recv_context_t *receive_ctx;
+} WASMGDBServer;
+
+WASMGDBServer *
+wasm_create_gdbserver(const char *host, int32 *port);
+
+bool
+wasm_gdbserver_listen(WASMGDBServer *server);
+
+bool
+wasm_gdbserver_accept(WASMGDBServer *server);
+
+void
+wasm_gdbserver_detach(WASMGDBServer *server);
+
+void
+wasm_close_gdbserver(WASMGDBServer *server);
+
+bool
+wasm_gdbserver_handle_packet(WASMGDBServer *server);
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c
new file mode 100644
index 000000000..8d451b1a3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "handler.h"
+#include "debug_engine.h"
+#include "packets.h"
+#include "utils.h"
+#include "wasm_runtime.h"
+
+/*
+ * Note: A moderate MAX_PACKET_SIZE is ok because
+ * LLDB queries our buffer size (via qSupported PacketSize)
+ * and limits packet sizes accordingly.
+ */
+
+#if defined(DEBUG_MAX_PACKET_SIZE)
+#define MAX_PACKET_SIZE DEBUG_MAX_PACKET_SIZE
+#else
+#define MAX_PACKET_SIZE (4096)
+#endif
+
+/*
+ * Note: It's assumed that MAX_PACKET_SIZE is reasonably large.
+ * See GetWorkingDir, WasmCallStack, etc.
+ */
+#if MAX_PACKET_SIZE < PATH_MAX || MAX_PACKET_SIZE < (2048 + 1)
+#error MAX_PACKET_SIZE is too small
+#endif
+
+static char *tmpbuf;
+static korp_mutex tmpbuf_lock;
+
+int
+wasm_debug_handler_init()
+{
+ int ret;
+ tmpbuf = wasm_runtime_malloc(MAX_PACKET_SIZE);
+ if (tmpbuf == NULL) {
+ LOG_ERROR("debug-engine: Packet buffer allocation failure");
+ return BHT_ERROR;
+ }
+ ret = os_mutex_init(&tmpbuf_lock);
+ if (ret != BHT_OK) {
+ wasm_runtime_free(tmpbuf);
+ tmpbuf = NULL;
+ }
+ return ret;
+}
+
+void
+wasm_debug_handler_deinit()
+{
+ wasm_runtime_free(tmpbuf);
+ tmpbuf = NULL;
+ os_mutex_destroy(&tmpbuf_lock);
+}
+
+void
+handle_interrupt(WASMGDBServer *server)
+{
+ wasm_debug_instance_interrupt_all_threads(server->thread->debug_instance);
+}
+
+void
+handle_general_set(WASMGDBServer *server, char *payload)
+{
+ const char *name;
+ char *args;
+
+ args = strchr(payload, ':');
+ if (args)
+ *args++ = '\0';
+
+ name = payload;
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+
+ if (!strcmp(name, "StartNoAckMode")) {
+ server->noack = true;
+ write_packet(server, "OK");
+ }
+ if (!strcmp(name, "ThreadSuffixSupported")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "ListThreadsInStopReply")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "EnableErrorStrings")) {
+ write_packet(server, "OK");
+ }
+}
+
+static void
+process_xfer(WASMGDBServer *server, const char *name, char *args)
+{
+ const char *mode = args;
+
+ args = strchr(args, ':');
+ if (args)
+ *args++ = '\0';
+
+ if (!strcmp(name, "libraries") && !strcmp(mode, "read")) {
+ // TODO: how to get current wasm file name?
+ uint64 addr = wasm_debug_instance_get_load_addr(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ os_mutex_lock(&tmpbuf_lock);
+#if WASM_ENABLE_LIBC_WASI != 0
+ char objname[128];
+ if (!wasm_debug_instance_get_current_object_name(
+ (WASMDebugInstance *)server->thread->debug_instance, objname,
+ 128)) {
+ objname[0] = 0; /* use an empty string */
+ }
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "l<library-list><library name=\"%s\"><section "
+ "address=\"0x%" PRIx64 "\"/></library></library-list>",
+ objname, addr);
+#else
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "l<library-list><library name=\"%s\"><section "
+ "address=\"0x%" PRIx64 "\"/></library></library-list>",
+ "nobody.wasm", addr);
+#endif
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+}
+
+void
+process_wasm_local(WASMGDBServer *server, char *args)
+{
+ int32 frame_index;
+ int32 local_index;
+ char buf[16];
+ int32 size = 16;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "E01");
+ if (sscanf(args, "%" PRId32 ";%" PRId32, &frame_index, &local_index) == 2) {
+ ret = wasm_debug_instance_get_local(
+ (WASMDebugInstance *)server->thread->debug_instance, frame_index,
+ local_index, buf, &size);
+ if (ret && size > 0) {
+ mem2hex(buf, tmpbuf, size);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+process_wasm_global(WASMGDBServer *server, char *args)
+{
+ int32 frame_index;
+ int32 global_index;
+ char buf[16];
+ int32 size = 16;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "E01");
+ if (sscanf(args, "%" PRId32 ";%" PRId32, &frame_index, &global_index)
+ == 2) {
+ ret = wasm_debug_instance_get_global(
+ (WASMDebugInstance *)server->thread->debug_instance, frame_index,
+ global_index, buf, &size);
+ if (ret && size > 0) {
+ mem2hex(buf, tmpbuf, size);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_general_query(WASMGDBServer *server, char *payload)
+{
+ const char *name;
+ char *args;
+ char triple[256];
+
+ args = strchr(payload, ':');
+ if (args)
+ *args++ = '\0';
+ name = payload;
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+
+ if (!strcmp(name, "C")) {
+ uint64 pid, tid;
+ pid = wasm_debug_instance_get_pid(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ tid = (uint64)(uintptr_t)wasm_debug_instance_get_tid(
+ (WASMDebugInstance *)server->thread->debug_instance);
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "QCp%" PRIx64 ".%" PRIx64 "", pid,
+ tid);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "Supported")) {
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "qXfer:libraries:read+;PacketSize=%" PRIx32 ";",
+ MAX_PACKET_SIZE);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+
+ if (!strcmp(name, "Xfer")) {
+ name = args;
+
+ if (!args) {
+ LOG_ERROR("payload parse error during handle_general_query");
+ return;
+ }
+
+ args = strchr(args, ':');
+
+ if (args) {
+ *args++ = '\0';
+ process_xfer(server, name, args);
+ }
+ }
+
+ if (!strcmp(name, "HostInfo")) {
+ mem2hex("wasm32-wamr-wasi-wasm", triple,
+ strlen("wasm32-wamr-wasi-wasm"));
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "vendor:wamr;ostype:wasi;arch:wasm32;"
+ "triple:%s;endian:little;ptrsize:4;",
+ triple);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "ModuleInfo")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "GetWorkingDir")) {
+ os_mutex_lock(&tmpbuf_lock);
+ if (getcwd(tmpbuf, PATH_MAX))
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "QueryGDBServer")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "VAttachOrWaitSupported")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "ProcessInfo")) {
+ // Todo: process id parent-pid
+ uint64 pid;
+ pid = wasm_debug_instance_get_pid(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ mem2hex("wasm32-wamr-wasi-wasm", triple,
+ strlen("wasm32-wamr-wasi-wasm"));
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "pid:%" PRIx64 ";parent-pid:%" PRIx64
+ ";vendor:wamr;ostype:wasi;arch:wasm32;"
+ "triple:%s;endian:little;ptrsize:4;",
+ pid, pid, triple);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "RegisterInfo0")) {
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(
+ tmpbuf, MAX_PACKET_SIZE,
+ "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
+ "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
+ write_packet(server, "E45");
+ }
+ if (!strcmp(name, "StructuredDataPlugins")) {
+ write_packet(server, "");
+ }
+
+ if (args && (!strcmp(name, "MemoryRegionInfo"))) {
+ uint64 addr = strtoll(args, NULL, 16);
+ WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
+ (WASMDebugInstance *)server->thread->debug_instance, addr);
+ if (mem_info) {
+ char name_buf[256];
+ mem2hex(mem_info->name, name_buf, strlen(mem_info->name));
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "start:%" PRIx64 ";size:%" PRIx64
+ ";permissions:%s;name:%s;",
+ (uint64)mem_info->start, mem_info->size,
+ mem_info->permisson, name_buf);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+
+ wasm_debug_instance_destroy_memregion(
+ (WASMDebugInstance *)server->thread->debug_instance, mem_info);
+ }
+ }
+
+ if (!strcmp(name, "WasmData")) {
+ }
+
+ if (!strcmp(name, "WasmMem")) {
+ }
+
+ if (!strcmp(name, "Symbol")) {
+ write_packet(server, "");
+ }
+
+ if (args && (!strcmp(name, "WasmCallStack"))) {
+ uint64 tid = strtoll(args, NULL, 16);
+ uint64 buf[1024 / sizeof(uint64)];
+ uint32 count = wasm_debug_instance_get_call_stack_pcs(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ (korp_tid)(uintptr_t)tid, buf, 1024 / sizeof(uint64));
+
+ if (count > 0) {
+ os_mutex_lock(&tmpbuf_lock);
+ mem2hex((char *)buf, tmpbuf, count * sizeof(uint64));
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ else
+ write_packet(server, "");
+ }
+
+ if (args && (!strcmp(name, "WasmLocal"))) {
+ process_wasm_local(server, args);
+ }
+
+ if (args && (!strcmp(name, "WasmGlobal"))) {
+ process_wasm_global(server, args);
+ }
+
+ if (!strcmp(name, "Offsets")) {
+ write_packet(server, "");
+ }
+
+ if (!strncmp(name, "ThreadStopInfo", strlen("ThreadStopInfo"))) {
+ int32 prefix_len = strlen("ThreadStopInfo");
+ uint64 tid_number = strtoll(name + prefix_len, NULL, 16);
+ korp_tid tid = (korp_tid)(uintptr_t)tid_number;
+ uint32 status;
+
+ status = wasm_debug_instance_get_thread_status(
+ server->thread->debug_instance, tid);
+
+ send_thread_stop_status(server, status, tid);
+ }
+
+ if (!strcmp(name, "WatchpointSupportInfo")) {
+ os_mutex_lock(&tmpbuf_lock);
+ // Any uint32 is OK for the watchpoint support
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "num:32;");
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+}
+
+void
+send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
+{
+ int32 len = 0;
+ uint64 pc;
+ korp_tid tids[20];
+ char pc_string[17];
+ uint32 tids_count, i = 0;
+ uint32 gdb_status = status;
+ WASMExecEnv *exec_env;
+ const char *exception;
+
+ if (status == 0) {
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "W%02x", status);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ return;
+ }
+ tids_count = wasm_debug_instance_get_tids(
+ (WASMDebugInstance *)server->thread->debug_instance, tids, 20);
+ pc = wasm_debug_instance_get_pc(
+ (WASMDebugInstance *)server->thread->debug_instance);
+
+ if (status == WAMR_SIG_SINGSTEP) {
+ gdb_status = WAMR_SIG_TRAP;
+ }
+
+ os_mutex_lock(&tmpbuf_lock);
+ // TODO: how name a wasm thread?
+ len += snprintf(tmpbuf, MAX_PACKET_SIZE, "T%02xthread:%" PRIx64 ";name:%s;",
+ gdb_status, (uint64)(uintptr_t)tid, "nobody");
+ if (tids_count > 0) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "threads:");
+ while (i < tids_count) {
+ if (i == tids_count - 1)
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "%" PRIx64 ";", (uint64)(uintptr_t)tids[i]);
+ else
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "%" PRIx64 ",", (uint64)(uintptr_t)tids[i]);
+ i++;
+ }
+ }
+ mem2hex((void *)&pc, pc_string, 8);
+ pc_string[8 * 2] = '\0';
+
+ exec_env = wasm_debug_instance_get_current_env(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ bh_assert(exec_env);
+
+ exception =
+ wasm_runtime_get_exception(wasm_runtime_get_module_inst(exec_env));
+ if (exception) {
+ /* When exception occurs, use reason:exception so the description can be
+ * correctly processed by LLDB */
+ uint32 exception_len = strlen(exception);
+ len +=
+ snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;description:", pc,
+ pc_string, "exception");
+ /* The description should be encoded as HEX */
+ for (i = 0; i < exception_len; i++) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "%02x",
+ exception[i]);
+ }
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, ";");
+ }
+ else {
+ if (status == WAMR_SIG_TRAP) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
+ pc_string, "breakpoint");
+ }
+ else if (status == WAMR_SIG_SINGSTEP) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
+ pc_string, "trace");
+ }
+ else if (status > 0) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
+ pc_string, "signal");
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_v_packet(WASMGDBServer *server, char *payload)
+{
+ const char *name;
+ char *args;
+
+ args = strchr(payload, ';');
+ if (args)
+ *args++ = '\0';
+ name = payload;
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+
+ if (!strcmp("Cont?", name))
+ write_packet(server, "vCont;c;C;s;S;");
+
+ if (!strcmp("Cont", name)) {
+ if (args) {
+ if (args[0] == 's' || args[0] == 'c') {
+ char *numstring = strchr(args, ':');
+ if (numstring) {
+ uint64 tid_number;
+ korp_tid tid;
+
+ *numstring++ = '\0';
+ tid_number = strtoll(numstring, NULL, 16);
+ tid = (korp_tid)(uintptr_t)tid_number;
+ wasm_debug_instance_set_cur_thread(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ tid);
+
+ if (args[0] == 's') {
+ wasm_debug_instance_singlestep(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ tid);
+ }
+ else {
+ wasm_debug_instance_continue(
+ (WASMDebugInstance *)
+ server->thread->debug_instance);
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+handle_threadstop_request(WASMGDBServer *server, char *payload)
+{
+ korp_tid tid;
+ uint32 status;
+ WASMDebugInstance *debug_inst =
+ (WASMDebugInstance *)server->thread->debug_instance;
+ bh_assert(debug_inst);
+
+ /* According to
+ https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#Packets, the "?"
+ package should be sent when connection is first established to query the
+ reason the target halted */
+ bh_assert(debug_inst->current_state == DBG_LAUNCHING);
+
+ /* Waiting for the stop event */
+ os_mutex_lock(&debug_inst->wait_lock);
+ while (!debug_inst->stopped_thread) {
+ os_cond_wait(&debug_inst->wait_cond, &debug_inst->wait_lock);
+ }
+ os_mutex_unlock(&debug_inst->wait_lock);
+
+ tid = debug_inst->stopped_thread->handle;
+ status = (uint32)debug_inst->stopped_thread->current_status->signal_flag;
+
+ wasm_debug_instance_set_cur_thread(debug_inst, tid);
+
+ send_thread_stop_status(server, status, tid);
+
+ debug_inst->current_state = APP_STOPPED;
+ debug_inst->stopped_thread = NULL;
+}
+
+void
+handle_set_current_thread(WASMGDBServer *server, char *payload)
+{
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+ if ('g' == *payload++) {
+ uint64 tid = strtoll(payload, NULL, 16);
+ if (tid > 0)
+ wasm_debug_instance_set_cur_thread(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ (korp_tid)(uintptr_t)tid);
+ }
+ write_packet(server, "OK");
+}
+
+void
+handle_get_register(WASMGDBServer *server, char *payload)
+{
+ uint64 regdata;
+ int32 i = strtol(payload, NULL, 16);
+
+ if (i != 0) {
+ write_packet(server, "E01");
+ return;
+ }
+ regdata = wasm_debug_instance_get_pc(
+ (WASMDebugInstance *)server->thread->debug_instance);
+
+ os_mutex_lock(&tmpbuf_lock);
+ mem2hex((void *)&regdata, tmpbuf, 8);
+ tmpbuf[8 * 2] = '\0';
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_get_json_request(WASMGDBServer *server, char *payload)
+{
+ char *args;
+
+ args = strchr(payload, ':');
+ if (args)
+ *args++ = '\0';
+ write_packet(server, "");
+}
+
+void
+handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
+{
+ write_packet(server, "");
+}
+
+void
+handle_get_read_memory(WASMGDBServer *server, char *payload)
+{
+ uint64 maddr, mlen;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "");
+ if (sscanf(payload, "%" SCNx64 ",%" SCNx64, &maddr, &mlen) == 2) {
+ char *buff;
+
+ if (mlen * 2 > MAX_PACKET_SIZE) {
+ LOG_ERROR("Buffer overflow!");
+ mlen = MAX_PACKET_SIZE / 2;
+ }
+
+ buff = wasm_runtime_malloc(mlen);
+ if (buff) {
+ ret = wasm_debug_instance_get_mem(
+ (WASMDebugInstance *)server->thread->debug_instance, maddr,
+ buff, &mlen);
+ if (ret) {
+ mem2hex(buff, tmpbuf, mlen);
+ }
+ wasm_runtime_free(buff);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_get_write_memory(WASMGDBServer *server, char *payload)
+{
+ size_t hex_len;
+ int32 offset, act_len;
+ uint64 maddr, mlen;
+ char *buff;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "");
+ if (sscanf(payload, "%" SCNx64 ",%" SCNx64 ":%n", &maddr, &mlen, &offset)
+ == 2) {
+ payload += offset;
+ hex_len = strlen(payload);
+ act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
+
+ buff = wasm_runtime_malloc(act_len);
+ if (buff) {
+ hex2mem(payload, buff, act_len);
+ ret = wasm_debug_instance_set_mem(
+ (WASMDebugInstance *)server->thread->debug_instance, maddr,
+ buff, &mlen);
+ if (ret) {
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "OK");
+ }
+ wasm_runtime_free(buff);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_breakpoint_software_add(WASMGDBServer *server, uint64 addr,
+ size_t length)
+{
+ bool ret = wasm_debug_instance_add_breakpoint(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_breakpoint_software_remove(WASMGDBServer *server, uint64 addr,
+ size_t length)
+{
+ bool ret = wasm_debug_instance_remove_breakpoint(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_write_add(WASMGDBServer *server, uint64 addr, size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_write_add(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_write_remove(WASMGDBServer *server, uint64 addr,
+ size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_write_remove(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_read_add(WASMGDBServer *server, uint64 addr, size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_read_add(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_read_remove(WASMGDBServer *server, uint64 addr, size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_read_remove(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_add_break(WASMGDBServer *server, char *payload)
+{
+ int arg_c;
+ size_t type, length;
+ uint64 addr;
+
+ if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length))
+ != 3) {
+ LOG_ERROR("Unsupported number of add break arguments %d", arg_c);
+ write_packet(server, "");
+ return;
+ }
+
+ switch (type) {
+ case eBreakpointSoftware:
+ handle_breakpoint_software_add(server, addr, length);
+ break;
+ case eWatchpointWrite:
+ handle_watchpoint_write_add(server, addr, length);
+ break;
+ case eWatchpointRead:
+ handle_watchpoint_read_add(server, addr, length);
+ break;
+ case eWatchpointReadWrite:
+ handle_watchpoint_write_add(server, addr, length);
+ handle_watchpoint_read_add(server, addr, length);
+ break;
+ default:
+ LOG_ERROR("Unsupported breakpoint type %zu", type);
+ write_packet(server, "");
+ break;
+ }
+}
+
+void
+handle_remove_break(WASMGDBServer *server, char *payload)
+{
+ int arg_c;
+ size_t type, length;
+ uint64 addr;
+
+ if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length))
+ != 3) {
+ LOG_ERROR("Unsupported number of remove break arguments %d", arg_c);
+ write_packet(server, "");
+ return;
+ }
+
+ switch (type) {
+ case eBreakpointSoftware:
+ handle_breakpoint_software_remove(server, addr, length);
+ break;
+ case eWatchpointWrite:
+ handle_watchpoint_write_remove(server, addr, length);
+ break;
+ case eWatchpointRead:
+ handle_watchpoint_read_remove(server, addr, length);
+ break;
+ case eWatchpointReadWrite:
+ handle_watchpoint_write_remove(server, addr, length);
+ handle_watchpoint_read_remove(server, addr, length);
+ break;
+ default:
+ LOG_ERROR("Unsupported breakpoint type %zu", type);
+ write_packet(server, "");
+ break;
+ }
+}
+
+void
+handle_continue_request(WASMGDBServer *server, char *payload)
+{
+ wasm_debug_instance_continue(
+ (WASMDebugInstance *)server->thread->debug_instance);
+}
+
+void
+handle_kill_request(WASMGDBServer *server, char *payload)
+{
+ wasm_debug_instance_kill(
+ (WASMDebugInstance *)server->thread->debug_instance);
+}
+
+static void
+handle_malloc(WASMGDBServer *server, char *payload)
+{
+ char *args;
+ uint64 addr, size;
+ int32 map_prot = MMAP_PROT_NONE;
+
+ args = strstr(payload, ",");
+ if (args) {
+ *args++ = '\0';
+ }
+ else {
+ LOG_ERROR("Payload parse error during handle malloc");
+ return;
+ }
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "E03");
+
+ size = strtoll(payload, NULL, 16);
+ if (size > 0) {
+ while (*args) {
+ if (*args == 'r') {
+ map_prot |= MMAP_PROT_READ;
+ }
+ if (*args == 'w') {
+ map_prot |= MMAP_PROT_WRITE;
+ }
+ if (*args == 'x') {
+ map_prot |= MMAP_PROT_EXEC;
+ }
+ args++;
+ }
+ addr = wasm_debug_instance_mmap(
+ (WASMDebugInstance *)server->thread->debug_instance, size,
+ map_prot);
+ if (addr) {
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%" PRIx64, addr);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+static void
+handle_free(WASMGDBServer *server, char *payload)
+{
+ uint64 addr;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "E03");
+ addr = strtoll(payload, NULL, 16);
+
+ ret = wasm_debug_instance_ummap(
+ (WASMDebugInstance *)server->thread->debug_instance, addr);
+ if (ret) {
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "OK");
+ }
+
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle____request(WASMGDBServer *server, char *payload)
+{
+ char *args;
+
+ if (payload[0] == 'M') {
+ args = payload + 1;
+ handle_malloc(server, args);
+ }
+ if (payload[0] == 'm') {
+ args = payload + 1;
+ handle_free(server, args);
+ }
+}
+
+void
+handle_detach_request(WASMGDBServer *server, char *payload)
+{
+ if (payload != NULL) {
+ write_packet(server, "OK");
+ }
+ wasm_debug_instance_detach(
+ (WASMDebugInstance *)server->thread->debug_instance);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h
new file mode 100644
index 000000000..af2566da5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef HANDLER_H
+#define HANDLER_H
+
+#include "gdbserver.h"
+
+int
+wasm_debug_handler_init();
+
+void
+wasm_debug_handler_deinit();
+
+void
+handle_interrupt(WASMGDBServer *server);
+
+void
+handle_general_set(WASMGDBServer *server, char *payload);
+
+void
+handle_general_query(WASMGDBServer *server, char *payload);
+
+void
+handle_v_packet(WASMGDBServer *server, char *payload);
+
+void
+handle_threadstop_request(WASMGDBServer *server, char *payload);
+
+void
+handle_set_current_thread(WASMGDBServer *server, char *payload);
+
+void
+handle_get_register(WASMGDBServer *server, char *payload);
+
+void
+handle_get_json_request(WASMGDBServer *server, char *payload);
+
+void
+handle_get_read_binary_memory(WASMGDBServer *server, char *payload);
+
+void
+handle_get_read_memory(WASMGDBServer *server, char *payload);
+
+void
+handle_get_write_memory(WASMGDBServer *server, char *payload);
+
+void
+handle_add_break(WASMGDBServer *server, char *payload);
+
+void
+handle_remove_break(WASMGDBServer *server, char *payload);
+
+void
+handle_continue_request(WASMGDBServer *server, char *payload);
+
+void
+handle_kill_request(WASMGDBServer *server, char *payload);
+
+void
+handle____request(WASMGDBServer *server, char *payload);
+
+void
+handle_detach_request(WASMGDBServer *server, char *payload);
+
+void
+send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid);
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c
new file mode 100644
index 000000000..1bdb3d2ce
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "packets.h"
+#include "gdbserver.h"
+
+void
+write_data_raw(WASMGDBServer *gdbserver, const uint8 *data, ssize_t len)
+{
+ ssize_t nwritten;
+
+ nwritten = os_socket_send(gdbserver->socket_fd, data, len);
+ if (nwritten < 0) {
+ LOG_ERROR("Write error\n");
+ exit(-2);
+ }
+}
+
+void
+write_hex(WASMGDBServer *gdbserver, unsigned long hex)
+{
+ char buf[32];
+ size_t len;
+
+ len = snprintf(buf, sizeof(buf) - 1, "%02lx", hex);
+ write_data_raw(gdbserver, (uint8 *)buf, len);
+}
+
+void
+write_packet_bytes(WASMGDBServer *gdbserver, const uint8 *data,
+ size_t num_bytes)
+{
+ uint8 checksum;
+ size_t i;
+
+ write_data_raw(gdbserver, (uint8 *)"$", 1);
+ for (i = 0, checksum = 0; i < num_bytes; ++i)
+ checksum += data[i];
+ write_data_raw(gdbserver, (uint8 *)data, num_bytes);
+ write_data_raw(gdbserver, (uint8 *)"#", 1);
+ write_hex(gdbserver, checksum);
+}
+
+void
+write_packet(WASMGDBServer *gdbserver, const char *data)
+{
+ LOG_VERBOSE("send replay:%s", data);
+ write_packet_bytes(gdbserver, (const uint8 *)data, strlen(data));
+}
+
+void
+write_binary_packet(WASMGDBServer *gdbserver, const char *pfx,
+ const uint8 *data, ssize_t num_bytes)
+{
+ uint8 *buf;
+ ssize_t pfx_num_chars = strlen(pfx);
+ ssize_t buf_num_bytes = 0, total_size;
+ int32 i;
+
+ total_size = 2 * num_bytes + pfx_num_chars;
+ buf = wasm_runtime_malloc(total_size);
+ if (!buf) {
+ LOG_ERROR("Failed to allocate memory for binary packet");
+ return;
+ }
+
+ memset(buf, 0, total_size);
+ memcpy(buf, pfx, pfx_num_chars);
+ buf_num_bytes += pfx_num_chars;
+
+ for (i = 0; i < num_bytes; ++i) {
+ uint8 b = data[i];
+ switch (b) {
+ case '#':
+ case '$':
+ case '}':
+ case '*':
+ buf[buf_num_bytes++] = '}';
+ buf[buf_num_bytes++] = b ^ 0x20;
+ break;
+ default:
+ buf[buf_num_bytes++] = b;
+ break;
+ }
+ }
+ write_packet_bytes(gdbserver, buf, buf_num_bytes);
+ wasm_runtime_free(buf);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h
new file mode 100644
index 000000000..b35889394
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef PACKETS_H
+#define PACKETS_H
+
+#include "gdbserver.h"
+
+void
+write_data_raw(WASMGDBServer *gdbserver, const uint8 *data, ssize_t len);
+
+void
+write_packet(WASMGDBServer *gdbserver, const char *data);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c
new file mode 100644
index 000000000..4d9299c1b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "utils.h"
+
+static const char hexchars[] = "0123456789abcdef";
+
+int32
+hex(char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+char *
+mem2hex(char *mem, char *buf, int32 count)
+{
+ uint8 ch;
+
+ for (int i = 0; i < count; i++) {
+ ch = *(mem++);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ return (buf);
+}
+
+char *
+hex2mem(char *buf, char *mem, int32 count)
+{
+ uint8 ch;
+
+ for (int i = 0; i < count; i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ *(mem++) = ch;
+ }
+ return (mem);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h
new file mode 100644
index 000000000..1c7580859
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "bh_platform.h"
+
+int32
+hex(char ch);
+
+char *
+mem2hex(char *mem, char *buf, int32 count);
+
+char *
+hex2mem(char *buf, char *mem, int32 count);
+
+int32
+unescape(char *msg, int32 len);
+
+#endif /* UTILS_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript
new file mode 100644
index 000000000..d03936c2f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+libc_pthread_wrapper.c
+''')
+
+CPPPATH = [cwd]
+
+
+group = DefineGroup('iwasm_libc_pthread', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake
new file mode 100644
index 000000000..134edf0e8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_PTHREAD_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIB_PTHREAD=1)
+
+if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
+add_definitions (-DWASM_ENABLE_LIB_PTHREAD_SEMAPHORE=1)
+endif()
+
+include_directories(${LIB_PTHREAD_DIR})
+
+file (GLOB source_all ${LIB_PTHREAD_DIR}/*.c)
+
+set (LIB_PTHREAD_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
new file mode 100644
index 000000000..206479c2a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
@@ -0,0 +1,1331 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+#include "../common/wasm_runtime_common.h"
+#include "thread_manager.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#define WAMR_PTHREAD_KEYS_MAX 32
+
+/* clang-format off */
+#define get_module(exec_env) \
+ wasm_exec_env_get_module(exec_env)
+
+#define get_module_inst(exec_env) \
+ wasm_runtime_get_module_inst(exec_env)
+
+#define get_thread_arg(exec_env) \
+ wasm_exec_env_get_thread_arg(exec_env)
+
+#define get_wasi_ctx(module_inst) \
+ wasm_runtime_get_wasi_ctx(module_inst)
+
+#define validate_app_addr(offset, size) \
+ wasm_runtime_validate_app_addr(module_inst, offset, size)
+
+#define validate_native_addr(addr, size) \
+ wasm_runtime_validate_native_addr(module_inst, addr, size)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+/* clang-format on */
+
+enum {
+ T_THREAD,
+ T_MUTEX,
+ T_COND,
+ T_SEM,
+};
+
+enum thread_status_t {
+ THREAD_INIT,
+ THREAD_RUNNING,
+ THREAD_CANCELLED,
+ THREAD_EXIT,
+};
+
+enum mutex_status_t {
+ MUTEX_CREATED,
+ MUTEX_DESTROYED,
+};
+
+enum cond_status_t {
+ COND_CREATED,
+ COND_DESTROYED,
+};
+
+enum sem_status_t {
+ SEM_CREATED,
+ SEM_CLOSED,
+ SEM_DESTROYED,
+};
+
+typedef struct ThreadKeyValueNode {
+ bh_list_link l;
+ wasm_exec_env_t exec_env;
+ int32 thread_key_values[WAMR_PTHREAD_KEYS_MAX];
+} ThreadKeyValueNode;
+
+typedef struct KeyData {
+ int32 destructor_func;
+ bool is_created;
+} KeyData;
+
+typedef struct ClusterInfoNode {
+ bh_list_link l;
+ WASMCluster *cluster;
+ HashMap *thread_info_map;
+ /* Key data list */
+ KeyData key_data_list[WAMR_PTHREAD_KEYS_MAX];
+ korp_mutex key_data_list_lock;
+ /* Every node contains the key value list for a thread */
+ bh_list thread_list_head;
+ bh_list *thread_list;
+} ClusterInfoNode;
+
+typedef struct ThreadInfoNode {
+ wasm_exec_env_t parent_exec_env;
+ wasm_exec_env_t exec_env;
+ /* the id returned to app */
+ uint32 handle;
+ /* type can be [THREAD | MUTEX | CONDITION] */
+ uint32 type;
+ /* Thread status, this variable should be volatile
+ as its value may be changed in different threads */
+ volatile uint32 status;
+ bool joinable;
+ union {
+ korp_tid thread;
+ korp_mutex *mutex;
+ korp_cond *cond;
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ korp_sem *sem;
+#endif
+ /* A copy of the thread return value */
+ void *ret;
+ } u;
+} ThreadInfoNode;
+
+typedef struct {
+ ThreadInfoNode *info_node;
+ /* table elem index of the app's entry function */
+ uint32 elem_index;
+ /* arg of the app's entry function */
+ uint32 arg;
+ wasm_module_inst_t module_inst;
+} ThreadRoutineArgs;
+
+typedef struct {
+ uint32 handle;
+ ThreadInfoNode *node;
+} SemCallbackArgs;
+
+static bh_list cluster_info_list;
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+static HashMap *sem_info_map;
+#endif
+static korp_mutex thread_global_lock;
+static uint32 handle_id = 1;
+
+static void
+lib_pthread_destroy_callback(WASMCluster *cluster);
+
+static uint32
+thread_handle_hash(void *handle)
+{
+ return (uint32)(uintptr_t)handle;
+}
+
+static bool
+thread_handle_equal(void *h1, void *h2)
+{
+ return (uint32)(uintptr_t)h1 == (uint32)(uintptr_t)h2 ? true : false;
+}
+
+static void
+thread_info_destroy(void *node)
+{
+ ThreadInfoNode *info_node = (ThreadInfoNode *)node;
+
+ os_mutex_lock(&thread_global_lock);
+ if (info_node->type == T_MUTEX) {
+ if (info_node->status != MUTEX_DESTROYED)
+ os_mutex_destroy(info_node->u.mutex);
+ wasm_runtime_free(info_node->u.mutex);
+ }
+ else if (info_node->type == T_COND) {
+ if (info_node->status != COND_DESTROYED)
+ os_cond_destroy(info_node->u.cond);
+ wasm_runtime_free(info_node->u.cond);
+ }
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ else if (info_node->type == T_SEM) {
+ if (info_node->status != SEM_DESTROYED)
+ os_sem_close(info_node->u.sem);
+ }
+#endif
+ wasm_runtime_free(info_node);
+ os_mutex_unlock(&thread_global_lock);
+}
+
+bool
+lib_pthread_init()
+{
+ if (0 != os_mutex_init(&thread_global_lock))
+ return false;
+ bh_list_init(&cluster_info_list);
+ if (!wasm_cluster_register_destroy_callback(lib_pthread_destroy_callback)) {
+ os_mutex_destroy(&thread_global_lock);
+ return false;
+ }
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ if (!(sem_info_map = bh_hash_map_create(
+ 32, true, (HashFunc)wasm_string_hash,
+ (KeyEqualFunc)wasm_string_equal, NULL, thread_info_destroy))) {
+ os_mutex_destroy(&thread_global_lock);
+ return false;
+ }
+#endif
+ return true;
+}
+
+void
+lib_pthread_destroy()
+{
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ bh_hash_map_destroy(sem_info_map);
+#endif
+ os_mutex_destroy(&thread_global_lock);
+}
+
+static ClusterInfoNode *
+get_cluster_info(WASMCluster *cluster)
+{
+ ClusterInfoNode *node;
+
+ os_mutex_lock(&thread_global_lock);
+ node = bh_list_first_elem(&cluster_info_list);
+
+ while (node) {
+ if (cluster == node->cluster) {
+ os_mutex_unlock(&thread_global_lock);
+ return node;
+ }
+ node = bh_list_elem_next(node);
+ }
+ os_mutex_unlock(&thread_global_lock);
+
+ return NULL;
+}
+
+static KeyData *
+key_data_list_lookup(wasm_exec_env_t exec_env, int32 key)
+{
+ ClusterInfoNode *node;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+
+ if ((node = get_cluster_info(cluster))) {
+ return (key >= 0 && key < WAMR_PTHREAD_KEYS_MAX
+ && node->key_data_list[key].is_created)
+ ? &(node->key_data_list[key])
+ : NULL;
+ }
+
+ return NULL;
+}
+
+/**
+ * Lookup the thread key value node for a thread, create a new one if failed
+ * This design will reduce the memory usage. If the thread doesn't use the
+ * local storage, it will not occupy memory space.
+ */
+static int32 *
+key_value_list_lookup_or_create(wasm_exec_env_t exec_env, ClusterInfoNode *info,
+ int32 key)
+{
+ KeyData *key_node;
+ ThreadKeyValueNode *data;
+
+ /* Check if the key is valid */
+ key_node = key_data_list_lookup(exec_env, key);
+ if (!key_node) {
+ return NULL;
+ }
+
+ /* Find key values node */
+ data = bh_list_first_elem(info->thread_list);
+ while (data) {
+ if (data->exec_env == exec_env)
+ return data->thread_key_values;
+ data = bh_list_elem_next(data);
+ }
+
+ /* If not found, create a new node for this thread */
+ if (!(data = wasm_runtime_malloc(sizeof(ThreadKeyValueNode))))
+ return NULL;
+ memset(data, 0, sizeof(ThreadKeyValueNode));
+ data->exec_env = exec_env;
+
+ if (bh_list_insert(info->thread_list, data) != 0) {
+ wasm_runtime_free(data);
+ return NULL;
+ }
+
+ return data->thread_key_values;
+}
+
+static void
+call_key_destructor(wasm_exec_env_t exec_env)
+{
+ int32 i;
+ uint32 destructor_index;
+ KeyData *key_node;
+ ThreadKeyValueNode *value_node;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info) {
+ return;
+ }
+
+ value_node = bh_list_first_elem(info->thread_list);
+ while (value_node) {
+ if (value_node->exec_env == exec_env)
+ break;
+ value_node = bh_list_elem_next(value_node);
+ }
+
+ /* This thread hasn't created key value node */
+ if (!value_node)
+ return;
+
+ /* Destroy key values */
+ for (i = 0; i < WAMR_PTHREAD_KEYS_MAX; i++) {
+ if (value_node->thread_key_values[i] != 0) {
+ int32 value = value_node->thread_key_values[i];
+ os_mutex_lock(&info->key_data_list_lock);
+
+ if ((key_node = key_data_list_lookup(exec_env, i)))
+ destructor_index = key_node->destructor_func;
+ else
+ destructor_index = 0;
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ /* reset key value */
+ value_node->thread_key_values[i] = 0;
+
+ /* Call the destructor func provided by app */
+ if (destructor_index) {
+ uint32 argv[1];
+
+ argv[0] = value;
+ wasm_runtime_call_indirect(exec_env, destructor_index, 1, argv);
+ }
+ }
+ }
+
+ bh_list_remove(info->thread_list, value_node);
+ wasm_runtime_free(value_node);
+}
+
+static void
+destroy_thread_key_value_list(bh_list *list)
+{
+ ThreadKeyValueNode *node, *next;
+
+ /* There should be only one node for main thread */
+ bh_assert(list->len <= 1);
+
+ if (list->len) {
+ node = bh_list_first_elem(list);
+ while (node) {
+ next = bh_list_elem_next(node);
+ call_key_destructor(node->exec_env);
+ node = next;
+ }
+ }
+}
+
+static ClusterInfoNode *
+create_cluster_info(WASMCluster *cluster)
+{
+ ClusterInfoNode *node;
+ bh_list_status ret;
+
+ if (!(node = wasm_runtime_malloc(sizeof(ClusterInfoNode)))) {
+ return NULL;
+ }
+ memset(node, 0, sizeof(ClusterInfoNode));
+
+ node->thread_list = &node->thread_list_head;
+ ret = bh_list_init(node->thread_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+
+ if (os_mutex_init(&node->key_data_list_lock) != 0) {
+ wasm_runtime_free(node);
+ return NULL;
+ }
+
+ node->cluster = cluster;
+ if (!(node->thread_info_map = bh_hash_map_create(
+ 32, true, (HashFunc)thread_handle_hash,
+ (KeyEqualFunc)thread_handle_equal, NULL, thread_info_destroy))) {
+ os_mutex_destroy(&node->key_data_list_lock);
+ wasm_runtime_free(node);
+ return NULL;
+ }
+ os_mutex_lock(&thread_global_lock);
+ ret = bh_list_insert(&cluster_info_list, node);
+ bh_assert(ret == BH_LIST_SUCCESS);
+ os_mutex_unlock(&thread_global_lock);
+
+ (void)ret;
+ return node;
+}
+
+static bool
+destroy_cluster_info(WASMCluster *cluster)
+{
+ ClusterInfoNode *node = get_cluster_info(cluster);
+ if (node) {
+ bh_hash_map_destroy(node->thread_info_map);
+ destroy_thread_key_value_list(node->thread_list);
+ os_mutex_destroy(&node->key_data_list_lock);
+
+ /* Remove from the cluster info list */
+ os_mutex_lock(&thread_global_lock);
+ bh_list_remove(&cluster_info_list, node);
+ wasm_runtime_free(node);
+ os_mutex_unlock(&thread_global_lock);
+ return true;
+ }
+ return false;
+}
+
+static void
+lib_pthread_destroy_callback(WASMCluster *cluster)
+{
+ destroy_cluster_info(cluster);
+}
+
+static void
+delete_thread_info_node(ThreadInfoNode *thread_info)
+{
+ ClusterInfoNode *node;
+ bool ret;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(thread_info->exec_env);
+
+ if ((node = get_cluster_info(cluster))) {
+ ret = bh_hash_map_remove(node->thread_info_map,
+ (void *)(uintptr_t)thread_info->handle, NULL,
+ NULL);
+ (void)ret;
+ }
+
+ thread_info_destroy(thread_info);
+}
+
+static bool
+append_thread_info_node(ThreadInfoNode *thread_info)
+{
+ ClusterInfoNode *node;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(thread_info->exec_env);
+
+ if (!(node = get_cluster_info(cluster))) {
+ if (!(node = create_cluster_info(cluster))) {
+ return false;
+ }
+ }
+
+ if (!bh_hash_map_insert(node->thread_info_map,
+ (void *)(uintptr_t)thread_info->handle,
+ thread_info)) {
+ return false;
+ }
+
+ return true;
+}
+
+static ThreadInfoNode *
+get_thread_info(wasm_exec_env_t exec_env, uint32 handle)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info) {
+ return NULL;
+ }
+
+ return bh_hash_map_find(info->thread_info_map, (void *)(uintptr_t)handle);
+}
+
+static uint32
+allocate_handle()
+{
+ uint32 id;
+ os_mutex_lock(&thread_global_lock);
+ id = handle_id++;
+ os_mutex_unlock(&thread_global_lock);
+ return id;
+}
+
+static void *
+pthread_start_routine(void *arg)
+{
+ wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
+ wasm_exec_env_t parent_exec_env;
+ ThreadRoutineArgs *routine_args = exec_env->thread_arg;
+ ThreadInfoNode *info_node = routine_args->info_node;
+ uint32 argv[1];
+
+ parent_exec_env = info_node->parent_exec_env;
+ os_mutex_lock(&parent_exec_env->wait_lock);
+ info_node->exec_env = exec_env;
+ info_node->u.thread = exec_env->handle;
+ if (!append_thread_info_node(info_node)) {
+ delete_thread_info_node(info_node);
+ os_cond_signal(&parent_exec_env->wait_cond);
+ os_mutex_unlock(&parent_exec_env->wait_lock);
+ return NULL;
+ }
+
+ info_node->status = THREAD_RUNNING;
+ os_cond_signal(&parent_exec_env->wait_cond);
+ os_mutex_unlock(&parent_exec_env->wait_lock);
+
+ wasm_exec_env_set_thread_info(exec_env);
+ argv[0] = routine_args->arg;
+
+ if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1,
+ argv)) {
+ /* Exception has already been spread during throwing */
+ }
+
+ /* destroy pthread key values */
+ call_key_destructor(exec_env);
+
+ wasm_runtime_free(routine_args);
+
+ /* if the thread is joinable, store the result in its info node,
+ if the other threads join this thread after exited, then we
+ can return the stored result */
+ if (!info_node->joinable) {
+ delete_thread_info_node(info_node);
+ }
+ else {
+ info_node->u.ret = (void *)(uintptr_t)argv[0];
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env->suspend_flags.flags & 0x08)
+ /* argv[0] isn't set after longjmp(1) to
+ invoke_native_with_hw_bound_check */
+ info_node->u.ret = exec_env->thread_ret_value;
+#endif
+ /* Update node status after ret value was set */
+ info_node->status = THREAD_EXIT;
+ }
+
+ return (void *)(uintptr_t)argv[0];
+}
+
+static int
+pthread_create_wrapper(wasm_exec_env_t exec_env,
+ uint32 *thread, /* thread_handle */
+ const void *attr, /* not supported */
+ uint32 elem_index, /* entry function */
+ uint32 arg) /* arguments buffer */
+{
+ wasm_module_t module = get_module(exec_env);
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_inst_t new_module_inst = NULL;
+ ThreadInfoNode *info_node = NULL;
+ ThreadRoutineArgs *routine_args = NULL;
+ uint32 thread_handle;
+ uint32 stack_size = 8192;
+ int32 ret = -1;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIContext *wasi_ctx;
+#endif
+
+ bh_assert(module);
+ bh_assert(module_inst);
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ stack_size =
+ ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ stack_size =
+ ((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+ if (!(new_module_inst = wasm_runtime_instantiate_internal(
+ module, true, exec_env, stack_size, 0, NULL, 0)))
+ return -1;
+
+ /* Set custom_data to new module instance */
+ wasm_runtime_set_custom_data_internal(
+ new_module_inst, wasm_runtime_get_custom_data(module_inst));
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_ctx = get_wasi_ctx(module_inst);
+ if (wasi_ctx)
+ wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
+#endif
+
+ if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
+ goto fail;
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ thread_handle = allocate_handle();
+ info_node->parent_exec_env = exec_env;
+ info_node->handle = thread_handle;
+ info_node->type = T_THREAD;
+ info_node->status = THREAD_INIT;
+ info_node->joinable = true;
+
+ if (!(routine_args = wasm_runtime_malloc(sizeof(ThreadRoutineArgs))))
+ goto fail;
+
+ routine_args->arg = arg;
+ routine_args->elem_index = elem_index;
+ routine_args->info_node = info_node;
+ routine_args->module_inst = new_module_inst;
+
+ os_mutex_lock(&exec_env->wait_lock);
+ ret =
+ wasm_cluster_create_thread(exec_env, new_module_inst, true,
+ pthread_start_routine, (void *)routine_args);
+ if (ret != 0) {
+ os_mutex_unlock(&exec_env->wait_lock);
+ goto fail;
+ }
+
+ /* Wait for the thread routine to assign the exec_env to
+ thread_info_node, otherwise the exec_env in the thread
+ info node may be NULL in the next pthread API call */
+ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock);
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ if (thread)
+ *thread = thread_handle;
+
+ return 0;
+
+fail:
+ if (new_module_inst)
+ wasm_runtime_deinstantiate_internal(new_module_inst, true);
+ if (info_node)
+ wasm_runtime_free(info_node);
+ if (routine_args)
+ wasm_runtime_free(routine_args);
+ return ret;
+}
+
+static int32
+pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread,
+ int32 retval_offset) /* void **retval */
+{
+ uint32 *ret;
+ int32 join_ret;
+ void **retval;
+ ThreadInfoNode *node;
+ wasm_module_inst_t module_inst;
+ wasm_exec_env_t target_exec_env;
+
+ module_inst = get_module_inst(exec_env);
+
+ /* validate addr, we can use current thread's
+ module instance here as the memory is shared */
+ if (!validate_app_addr(retval_offset, sizeof(int32))) {
+ /* Join failed, but we don't want to terminate all threads,
+ do not spread exception here */
+ wasm_runtime_set_exception(module_inst, NULL);
+ return -1;
+ }
+
+ retval = (void **)addr_app_to_native(retval_offset);
+
+ node = get_thread_info(exec_env, thread);
+ if (!node) {
+ /* The thread has exited and not joinable, return 0 to app */
+ return 0;
+ }
+
+ target_exec_env = node->exec_env;
+ bh_assert(target_exec_env);
+
+ if (node->status != THREAD_EXIT) {
+ /* if the thread is still running, call the platforms join API */
+ join_ret = wasm_cluster_join_thread(target_exec_env, (void **)&ret);
+ }
+ else {
+ /* if the thread has exited, return stored results */
+
+ /* this thread must be joinable, otherwise the
+ info_node should be destroyed once exit */
+ bh_assert(node->joinable);
+ join_ret = 0;
+ ret = node->u.ret;
+ }
+
+ if (retval_offset != 0)
+ *(uint32 *)retval = (uint32)(uintptr_t)ret;
+
+ return join_ret;
+}
+
+static int32
+pthread_detach_wrapper(wasm_exec_env_t exec_env, uint32 thread)
+{
+ ThreadInfoNode *node;
+ wasm_exec_env_t target_exec_env;
+
+ node = get_thread_info(exec_env, thread);
+ if (!node)
+ return 0;
+
+ node->joinable = false;
+
+ target_exec_env = node->exec_env;
+ bh_assert(target_exec_env != NULL);
+
+ return wasm_cluster_detach_thread(target_exec_env);
+}
+
+static int32
+pthread_cancel_wrapper(wasm_exec_env_t exec_env, uint32 thread)
+{
+ ThreadInfoNode *node;
+ wasm_exec_env_t target_exec_env;
+
+ node = get_thread_info(exec_env, thread);
+ if (!node)
+ return 0;
+
+ node->status = THREAD_CANCELLED;
+ node->joinable = false;
+
+ target_exec_env = node->exec_env;
+ bh_assert(target_exec_env != NULL);
+
+ return wasm_cluster_cancel_thread(target_exec_env);
+}
+
+static int32
+pthread_self_wrapper(wasm_exec_env_t exec_env)
+{
+ ThreadRoutineArgs *args = get_thread_arg(exec_env);
+ /* If thread_arg is NULL, it's the exec_env of the main thread,
+ return id 0 to app */
+ if (!args)
+ return 0;
+
+ return args->info_node->handle;
+}
+
+/* emcc use __pthread_self rather than pthread_self */
+static int32
+__pthread_self_wrapper(wasm_exec_env_t exec_env)
+{
+ return pthread_self_wrapper(exec_env);
+}
+
+static void
+pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ ThreadRoutineArgs *args = get_thread_arg(exec_env);
+ /* Currently exit main thread is not allowed */
+ if (!args)
+ return;
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && !defined(BH_PLATFORM_WINDOWS)
+ /* If hardware bound check enabled, don't deinstantiate module inst
+ and thread info node here for AoT module, as they will be freed
+ in pthread_start_routine */
+ if (exec_env->jmpbuf_stack_top) {
+ wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset);
+ }
+#endif
+
+ /* destroy pthread key values */
+ call_key_destructor(exec_env);
+
+ /* routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ if (!args->info_node->joinable) {
+ delete_thread_info_node(args->info_node);
+ }
+ else {
+ args->info_node->u.ret = (void *)(uintptr_t)retval_offset;
+ /* Update node status after ret value was set */
+ args->info_node->status = THREAD_EXIT;
+ }
+
+ wasm_runtime_free(args);
+
+ wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset);
+}
+
+static int32
+pthread_mutex_init_wrapper(wasm_exec_env_t exec_env, uint32 *mutex, void *attr)
+{
+ korp_mutex *pmutex;
+ ThreadInfoNode *info_node;
+
+ if (!(pmutex = wasm_runtime_malloc(sizeof(korp_mutex)))) {
+ return -1;
+ }
+
+ if (os_mutex_init(pmutex) != 0) {
+ goto fail1;
+ }
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail2;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ info_node->exec_env = exec_env;
+ info_node->handle = allocate_handle();
+ info_node->type = T_MUTEX;
+ info_node->u.mutex = pmutex;
+ info_node->status = MUTEX_CREATED;
+
+ if (!append_thread_info_node(info_node))
+ goto fail3;
+
+ /* Return the mutex handle to app */
+ if (mutex)
+ *(uint32 *)mutex = info_node->handle;
+
+ return 0;
+
+fail3:
+ delete_thread_info_node(info_node);
+fail2:
+ os_mutex_destroy(pmutex);
+fail1:
+ wasm_runtime_free(pmutex);
+
+ return -1;
+}
+
+static int32
+pthread_mutex_lock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex);
+ if (!info_node || info_node->type != T_MUTEX)
+ return -1;
+
+ return os_mutex_lock(info_node->u.mutex);
+}
+
+static int32
+pthread_mutex_unlock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex);
+ if (!info_node || info_node->type != T_MUTEX)
+ return -1;
+
+ return os_mutex_unlock(info_node->u.mutex);
+}
+
+static int32
+pthread_mutex_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *mutex)
+{
+ int32 ret_val;
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex);
+ if (!info_node || info_node->type != T_MUTEX)
+ return -1;
+
+ ret_val = os_mutex_destroy(info_node->u.mutex);
+
+ info_node->status = MUTEX_DESTROYED;
+ delete_thread_info_node(info_node);
+
+ return ret_val;
+}
+
+static int32
+pthread_cond_init_wrapper(wasm_exec_env_t exec_env, uint32 *cond, void *attr)
+{
+ korp_cond *pcond;
+ ThreadInfoNode *info_node;
+
+ if (!(pcond = wasm_runtime_malloc(sizeof(korp_cond)))) {
+ return -1;
+ }
+
+ if (os_cond_init(pcond) != 0) {
+ goto fail1;
+ }
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail2;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ info_node->exec_env = exec_env;
+ info_node->handle = allocate_handle();
+ info_node->type = T_COND;
+ info_node->u.cond = pcond;
+ info_node->status = COND_CREATED;
+
+ if (!append_thread_info_node(info_node))
+ goto fail3;
+
+ /* Return the cond handle to app */
+ if (cond)
+ *(uint32 *)cond = info_node->handle;
+
+ return 0;
+
+fail3:
+ delete_thread_info_node(info_node);
+fail2:
+ os_cond_destroy(pcond);
+fail1:
+ wasm_runtime_free(pcond);
+
+ return -1;
+}
+
+static int32
+pthread_cond_wait_wrapper(wasm_exec_env_t exec_env, uint32 *cond, uint32 *mutex)
+{
+ ThreadInfoNode *cond_info_node, *mutex_info_node;
+
+ cond_info_node = get_thread_info(exec_env, *cond);
+ if (!cond_info_node || cond_info_node->type != T_COND)
+ return -1;
+
+ mutex_info_node = get_thread_info(exec_env, *mutex);
+ if (!mutex_info_node || mutex_info_node->type != T_MUTEX)
+ return -1;
+
+ return os_cond_wait(cond_info_node->u.cond, mutex_info_node->u.mutex);
+}
+
+/**
+ * Currently we don't support struct timespec in built-in libc,
+ * so the pthread_cond_timedwait use useconds instead
+ */
+static int32
+pthread_cond_timedwait_wrapper(wasm_exec_env_t exec_env, uint32 *cond,
+ uint32 *mutex, uint64 useconds)
+{
+ ThreadInfoNode *cond_info_node, *mutex_info_node;
+
+ cond_info_node = get_thread_info(exec_env, *cond);
+ if (!cond_info_node || cond_info_node->type != T_COND)
+ return -1;
+
+ mutex_info_node = get_thread_info(exec_env, *mutex);
+ if (!mutex_info_node || mutex_info_node->type != T_MUTEX)
+ return -1;
+
+ return os_cond_reltimedwait(cond_info_node->u.cond,
+ mutex_info_node->u.mutex, useconds);
+}
+
+static int32
+pthread_cond_signal_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
+ if (!info_node || info_node->type != T_COND)
+ return -1;
+
+ return os_cond_signal(info_node->u.cond);
+}
+
+static int32
+pthread_cond_broadcast_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
+ if (!info_node || info_node->type != T_COND)
+ return -1;
+
+ return os_cond_broadcast(info_node->u.cond);
+}
+
+static int32
+pthread_cond_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
+{
+ int32 ret_val;
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
+ if (!info_node || info_node->type != T_COND)
+ return -1;
+
+ ret_val = os_cond_destroy(info_node->u.cond);
+
+ info_node->status = COND_DESTROYED;
+ delete_thread_info_node(info_node);
+
+ return ret_val;
+}
+
+static int32
+pthread_key_create_wrapper(wasm_exec_env_t exec_env, int32 *key,
+ int32 destructor_elem_index)
+{
+ uint32 i;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info) {
+ /* The user may call pthread_key_create in main thread,
+ in this case the cluster info hasn't been created */
+ if (!(info = create_cluster_info(cluster))) {
+ return -1;
+ }
+ }
+
+ os_mutex_lock(&info->key_data_list_lock);
+ for (i = 0; i < WAMR_PTHREAD_KEYS_MAX; i++) {
+ if (!info->key_data_list[i].is_created) {
+ break;
+ }
+ }
+
+ if (i == WAMR_PTHREAD_KEYS_MAX) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return -1;
+ }
+
+ info->key_data_list[i].destructor_func = destructor_elem_index;
+ info->key_data_list[i].is_created = true;
+ *key = i;
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return 0;
+}
+
+static int32
+pthread_setspecific_wrapper(wasm_exec_env_t exec_env, int32 key,
+ int32 value_offset)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+ int32 *key_values;
+
+ if (!info)
+ return -1;
+
+ os_mutex_lock(&info->key_data_list_lock);
+
+ key_values = key_value_list_lookup_or_create(exec_env, info, key);
+ if (!key_values) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return -1;
+ }
+
+ key_values[key] = value_offset;
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return 0;
+}
+
+static int32
+pthread_getspecific_wrapper(wasm_exec_env_t exec_env, int32 key)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+ int32 ret, *key_values;
+
+ if (!info)
+ return 0;
+
+ os_mutex_lock(&info->key_data_list_lock);
+
+ key_values = key_value_list_lookup_or_create(exec_env, info, key);
+ if (!key_values) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return 0;
+ }
+
+ ret = key_values[key];
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return ret;
+}
+
+static int32
+pthread_key_delete_wrapper(wasm_exec_env_t exec_env, int32 key)
+{
+ KeyData *data;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info)
+ return -1;
+
+ os_mutex_lock(&info->key_data_list_lock);
+ data = key_data_list_lookup(exec_env, key);
+ if (!data) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return -1;
+ }
+
+ memset(data, 0, sizeof(KeyData));
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return 0;
+}
+
+/**
+ * Currently the memory allocator doesn't support alloc specific aligned
+ * space, we wrap posix_memalign to simply malloc memory
+ */
+static int32
+posix_memalign_wrapper(wasm_exec_env_t exec_env, void **memptr, int32 align,
+ int32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ void *p = NULL;
+
+ *((int32 *)memptr) = module_malloc(size, (void **)&p);
+ if (!p)
+ return -1;
+
+ return 0;
+}
+
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+
+static int32
+sem_open_wrapper(wasm_exec_env_t exec_env, const char *name, int32 oflags,
+ int32 mode, int32 val)
+{
+ korp_sem *psem = NULL;
+ ThreadInfoNode *info_node = NULL;
+
+ /**
+ * For RTOS, global semaphore map is safe for share the same semaphore
+ * between task/pthread.
+ * For Unix like system, it's dedicated for multiple processes.
+ */
+
+ if ((info_node = bh_hash_map_find(sem_info_map, (void *)name))) {
+ return info_node->handle;
+ }
+
+ if (!(psem = os_sem_open(name, oflags, mode, val))) {
+ goto fail1;
+ }
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail2;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ info_node->exec_env = exec_env;
+ info_node->handle = allocate_handle();
+ info_node->type = T_SEM;
+ info_node->u.sem = psem;
+ info_node->status = SEM_CREATED;
+
+ if (!bh_hash_map_insert(sem_info_map, (void *)name, info_node))
+ goto fail3;
+
+ return info_node->handle;
+
+fail3:
+ wasm_runtime_free(info_node);
+fail2:
+ os_sem_close(psem);
+fail1:
+ return -1;
+}
+
+void
+sem_fetch_cb(void *key, void *value, void *user_data)
+{
+ (void)key;
+ SemCallbackArgs *args = user_data;
+ ThreadInfoNode *info_node = value;
+ if (args->handle == info_node->handle && info_node->status == SEM_CREATED) {
+ args->node = info_node;
+ }
+}
+
+static int32
+sem_close_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ int ret = -1;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ ret = os_sem_close(args.node->u.sem);
+ if (ret == 0) {
+ args.node->status = SEM_CLOSED;
+ }
+ }
+
+ return ret;
+}
+
+static int32
+sem_wait_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ return os_sem_wait(args.node->u.sem);
+ }
+
+ return -1;
+}
+
+static int32
+sem_trywait_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ return os_sem_trywait(args.node->u.sem);
+ }
+
+ return -1;
+}
+
+static int32
+sem_post_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ return os_sem_post(args.node->u.sem);
+ }
+
+ return -1;
+}
+
+static int32
+sem_getvalue_wrapper(wasm_exec_env_t exec_env, uint32 sem, int32 *sval)
+{
+ int32 ret = -1;
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ if (validate_native_addr(sval, sizeof(int32))) {
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ ret = os_sem_getvalue(args.node->u.sem, sval);
+ }
+ }
+ return ret;
+}
+
+static int32
+sem_unlink_wrapper(wasm_exec_env_t exec_env, const char *name)
+{
+ (void)exec_env;
+ int32 ret_val;
+
+ ThreadInfoNode *info_node = bh_hash_map_find(sem_info_map, (void *)name);
+ if (!info_node || info_node->type != T_SEM)
+ return -1;
+
+ if (info_node->status != SEM_CLOSED) {
+ ret_val = os_sem_close(info_node->u.sem);
+ if (ret_val != 0) {
+ return ret_val;
+ }
+ }
+
+ ret_val = os_sem_unlink(name);
+
+ if (ret_val == 0) {
+ bh_hash_map_remove(sem_info_map, (void *)name, NULL, NULL);
+ info_node->status = SEM_DESTROYED;
+ thread_info_destroy(info_node);
+ }
+ return ret_val;
+}
+
+#endif
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_pthread[] = {
+ REG_NATIVE_FUNC(pthread_create, "(**ii)i"),
+ REG_NATIVE_FUNC(pthread_join, "(ii)i"),
+ REG_NATIVE_FUNC(pthread_detach, "(i)i"),
+ REG_NATIVE_FUNC(pthread_cancel, "(i)i"),
+ REG_NATIVE_FUNC(pthread_self, "()i"),
+ REG_NATIVE_FUNC(__pthread_self, "()i"),
+ REG_NATIVE_FUNC(pthread_exit, "(i)"),
+ REG_NATIVE_FUNC(pthread_mutex_init, "(**)i"),
+ REG_NATIVE_FUNC(pthread_mutex_lock, "(*)i"),
+ REG_NATIVE_FUNC(pthread_mutex_unlock, "(*)i"),
+ REG_NATIVE_FUNC(pthread_mutex_destroy, "(*)i"),
+ REG_NATIVE_FUNC(pthread_cond_init, "(**)i"),
+ REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"),
+ REG_NATIVE_FUNC(pthread_cond_timedwait, "(**I)i"),
+ REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"),
+ REG_NATIVE_FUNC(pthread_cond_broadcast, "(*)i"),
+ REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"),
+ REG_NATIVE_FUNC(pthread_key_create, "(*i)i"),
+ REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"),
+ REG_NATIVE_FUNC(pthread_getspecific, "(i)i"),
+ REG_NATIVE_FUNC(pthread_key_delete, "(i)i"),
+ REG_NATIVE_FUNC(posix_memalign, "(*ii)i"),
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ REG_NATIVE_FUNC(sem_open, "($iii)i"),
+ REG_NATIVE_FUNC(sem_close, "(i)i"),
+ REG_NATIVE_FUNC(sem_wait, "(i)i"),
+ REG_NATIVE_FUNC(sem_trywait, "(i)i"),
+ REG_NATIVE_FUNC(sem_post, "(i)i"),
+ REG_NATIVE_FUNC(sem_getvalue, "(i*)i"),
+ REG_NATIVE_FUNC(sem_unlink, "($)i"),
+#endif
+};
+
+uint32
+get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis)
+{
+ *p_lib_pthread_apis = native_symbols_lib_pthread;
+ return sizeof(native_symbols_lib_pthread) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake
new file mode 100644
index 000000000..b773c837e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake
@@ -0,0 +1,43 @@
+# Copyright (c) 2022 Intel Corporation
+# Copyright (c) 2020-2021 Alibaba Cloud
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_RATS_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+if ("$ENV{SGX_SSL_DIR}" STREQUAL "")
+ set (SGX_SSL_DIR "/opt/intel/sgxssl")
+else()
+ set (SGX_SSL_DIR $ENV{SGX_SSL_DIR})
+endif()
+
+if (NOT EXISTS ${SGX_SSL_DIR})
+ message(FATAL_ERROR "Can not find SGX_SSL, please install it first")
+endif()
+
+add_definitions (-DWASM_ENABLE_LIB_RATS=1)
+
+include_directories(${LIB_RATS_DIR} ${SGX_SSL_DIR}/include)
+
+include(FetchContent)
+
+set(RATS_BUILD_MODE "sgx"
+ CACHE INTERNAL "Select build mode for librats(host|occlum|sgx|wasm)")
+set(RATS_INSTALL_PATH "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "")
+
+FetchContent_Declare(
+ librats
+ GIT_REPOSITORY https://github.com/inclavare-containers/librats
+ GIT_TAG master
+)
+FetchContent_GetProperties(librats)
+if (NOT librats_POPULATED)
+ message("-- Fetching librats ..")
+ FetchContent_Populate(librats)
+ include_directories("${librats_SOURCE_DIR}/include")
+ add_subdirectory(${librats_SOURCE_DIR} ${librats_BINARY_DIR} EXCLUDE_FROM_ALL)
+
+endif()
+
+file (GLOB source_all ${LIB_RATS_DIR}/*.c)
+
+set (LIB_RATS_SOURCE ${source_all}) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h
new file mode 100644
index 000000000..929e105f0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 Intel Corporation
+ * Copyright (c) 2020-2021 Alibaba Cloud
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _RATS_WAMR_COMMON_H
+#define _RATS_WAMR_COMMON_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SGX_QUOTE_MAX_SIZE 8192
+#define SGX_USER_DATA_SIZE 64
+#define SGX_MEASUREMENT_SIZE 32
+
+/* clang-format off */
+typedef struct rats_sgx_evidence {
+ uint8_t quote[SGX_QUOTE_MAX_SIZE]; /* The quote of the Enclave */
+ uint32_t quote_size; /* The size of the quote */
+ uint8_t user_data[SGX_USER_DATA_SIZE]; /* The custom data in the quote */
+ uint32_t product_id; /* Product ID of the Enclave */
+ uint8_t mr_enclave[SGX_MEASUREMENT_SIZE]; /* The MRENCLAVE of the Enclave */
+ uint32_t security_version; /* Security Version of the Enclave */
+ uint8_t mr_signer[SGX_MEASUREMENT_SIZE]; /* The MRSIGNER of the Enclave */
+ uint64_t att_flags; /* Flags of the Enclave in attributes */
+ uint64_t att_xfrm; /* XSAVE Feature Request Mask */
+} rats_sgx_evidence_t;
+/* clang-format on */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c
new file mode 100644
index 000000000..59d61f4c8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2022 Intel Corporation
+ * Copyright (c) 2020-2021 Alibaba Cloud
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <librats/api.h>
+#include <string.h>
+#include <openssl/sha.h>
+
+#include "sgx_quote_3.h"
+#include "wasm_export.h"
+#include "bh_common.h"
+#include "lib_rats_common.h"
+
+static int
+librats_collect_wrapper(wasm_exec_env_t exec_env, char **evidence_json,
+ const char *buffer, uint32_t buffer_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_t module = wasm_runtime_get_module(module_inst);
+ char *wasm_module_hash = wasm_runtime_get_module_hash(module);
+
+ char *json, *str_ret;
+ uint32_t str_ret_offset;
+ uint8_t final_hash[SHA256_DIGEST_LENGTH];
+
+ SHA256_CTX sha256;
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256, wasm_module_hash, SHA256_DIGEST_LENGTH);
+ if (buffer != NULL)
+ SHA256_Update(&sha256, buffer, buffer_size);
+ SHA256_Final(final_hash, &sha256);
+
+ int ret_code = librats_collect_evidence_to_json(final_hash, &json);
+ if (ret_code != 0) {
+ return ret_code;
+ }
+
+ uint32_t json_size = strlen(json) + 1;
+ str_ret_offset = module_malloc(json_size, (void **)&str_ret);
+ if (!str_ret_offset) {
+ free(json);
+ return (int)RATS_ATTESTER_ERR_NO_MEM;
+ }
+ bh_memcpy_s(str_ret, json_size, json, json_size);
+ *((int *)evidence_json) = str_ret_offset;
+ free(json);
+
+ return 0;
+}
+
+static int
+librats_verify_wrapper(wasm_exec_env_t exec_env, const char *evidence_json,
+ uint32_t evidence_size, const uint8_t *hash,
+ uint32_t hash_size)
+{
+ return librats_verify_evidence_from_json(evidence_json, hash);
+}
+
+static int
+librats_parse_evidence_wrapper(wasm_exec_env_t exec_env,
+ const char *evidence_json, uint32_t json_size,
+ rats_sgx_evidence_t *evidence,
+ uint32_t evidence_size)
+{
+ attestation_evidence_t att_ev;
+
+ if (get_evidence_from_json(evidence_json, &att_ev) != 0) {
+ return -1;
+ }
+
+ // Only supports parsing sgx evidence currently
+ if (strcmp(att_ev.type, "sgx_ecdsa") != 0) {
+ return -1;
+ }
+
+ sgx_quote3_t *quote_ptr = (sgx_quote3_t *)att_ev.ecdsa.quote;
+ bh_memcpy_s(evidence->quote, att_ev.ecdsa.quote_len, att_ev.ecdsa.quote,
+ att_ev.ecdsa.quote_len);
+ evidence->quote_size = att_ev.ecdsa.quote_len;
+ bh_memcpy_s(evidence->user_data, SGX_REPORT_DATA_SIZE,
+ quote_ptr->report_body.report_data.d, SGX_REPORT_DATA_SIZE);
+ bh_memcpy_s(evidence->mr_enclave, sizeof(sgx_measurement_t),
+ quote_ptr->report_body.mr_enclave.m, sizeof(sgx_measurement_t));
+ bh_memcpy_s(evidence->mr_signer, sizeof(sgx_measurement_t),
+ quote_ptr->report_body.mr_signer.m, sizeof(sgx_measurement_t));
+ evidence->product_id = quote_ptr->report_body.isv_prod_id;
+ evidence->security_version = quote_ptr->report_body.isv_svn;
+ evidence->att_flags = quote_ptr->report_body.attributes.flags;
+ evidence->att_xfrm = quote_ptr->report_body.attributes.flags;
+
+ return 0;
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_rats[] = {
+ REG_NATIVE_FUNC(librats_collect, "(**~)i"),
+ REG_NATIVE_FUNC(librats_verify, "(*~*~)i"),
+ REG_NATIVE_FUNC(librats_parse_evidence, "(*~*~)i")
+};
+
+uint32_t
+get_lib_rats_export_apis(NativeSymbol **p_lib_rats_apis)
+{
+ *p_lib_rats_apis = native_symbols_lib_rats;
+ return sizeof(native_symbols_lib_rats) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h
new file mode 100644
index 000000000..e334983e9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 Intel Corporation
+ * Copyright (c) 2020-2021 Alibaba Cloud
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _RATS_WAMR_API_H
+#define _RATS_WAMR_API_H
+
+#include <stdint.h>
+#include <string.h>
+
+#include "lib_rats_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+librats_collect(char **evidence_json, const char *buffer, uint32_t buffer_size);
+
+int
+librats_verify(const char *evidence_json, uint32_t evidence_size,
+ const uint8_t *hash, uint32_t hash_size);
+
+int
+librats_parse_evidence(const char *evidence_json, uint32_t json_size,
+ rats_sgx_evidence_t *evidence, uint32_t evidence_size);
+
+#define librats_collect(evidence_json, buffer) \
+ librats_collect(evidence_json, buffer, buffer ? strlen(buffer) + 1 : 0)
+
+#define librats_verify(evidence_json, hash) \
+ librats_verify(evidence_json, \
+ evidence_json ? strlen(evidence_json) + 1 : 0, hash, \
+ hash ? strlen((const char *)hash) + 1 : 0)
+
+#define librats_parse_evidence(evidence_json, evidence) \
+ librats_parse_evidence(evidence_json, \
+ evidence_json ? strlen(evidence_json) + 1 : 0, \
+ evidence, sizeof(rats_sgx_evidence_t))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h
new file mode 100644
index 000000000..c9a07eb72
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASI_SOCKET_EXT_H_
+#define _WASI_SOCKET_EXT_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*Be a part of <wasi/api.h>*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SOCKET_DGRAM = 0,
+ SOCKET_STREAM,
+} __wasi_sock_type_t;
+
+typedef uint16_t __wasi_ip_port_t;
+
+typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
+
+/*
+ n0.n1.n2.n3
+ Example:
+ IP Address: 127.0.0.1
+ Structure: {n0: 127, n1: 0, n2: 0, n3: 1}
+*/
+typedef struct __wasi_addr_ip4_t {
+ uint8_t n0;
+ uint8_t n1;
+ uint8_t n2;
+ uint8_t n3;
+} __wasi_addr_ip4_t;
+
+typedef struct __wasi_addr_ip4_port_t {
+ __wasi_addr_ip4_t addr;
+ __wasi_ip_port_t port; /* host byte order */
+} __wasi_addr_ip4_port_t;
+
+/*
+ n0:n1:n2:n3:h0:h1:h2:h3, each 16bit value uses host byte order
+ Example (little-endian system)
+ IP Address fe80::3ba2:893b:4be0:e3dd
+ Structure: {
+ n0: 0xfe80, n1:0x0, n2: 0x0, n3: 0x0,
+ h0: 0x3ba2, h1: 0x893b, h2: 0x4be0, h3: 0xe3dd
+ }
+*/
+typedef struct __wasi_addr_ip6_t {
+ uint16_t n0;
+ uint16_t n1;
+ uint16_t n2;
+ uint16_t n3;
+ uint16_t h0;
+ uint16_t h1;
+ uint16_t h2;
+ uint16_t h3;
+} __wasi_addr_ip6_t;
+
+typedef struct __wasi_addr_ip6_port_t {
+ __wasi_addr_ip6_t addr;
+ __wasi_ip_port_t port; /* host byte order */
+} __wasi_addr_ip6_port_t;
+
+typedef struct __wasi_addr_ip_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_t ip4;
+ __wasi_addr_ip6_t ip6;
+ } addr;
+} __wasi_addr_ip_t;
+
+typedef struct __wasi_addr_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_port_t ip4;
+ __wasi_addr_ip6_port_t ip6;
+ } addr;
+} __wasi_addr_t;
+
+typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
+
+typedef struct __wasi_addr_info_t {
+ __wasi_addr_t addr;
+ __wasi_sock_type_t type;
+} __wasi_addr_info_t;
+
+typedef struct __wasi_addr_info_hints_t {
+ __wasi_sock_type_t type;
+ __wasi_address_family_t family;
+ // this is to workaround lack of optional parameters
+ uint8_t hints_enabled;
+} __wasi_addr_info_hints_t;
+
+#ifdef __wasi__
+/**
+ * Reimplement below POSIX APIs with __wasi_sock_XXX functions.
+ *
+ * Keep sync with
+ * <sys/socket.h>
+ * <sys/types.h>
+ */
+#define SO_REUSEADDR 2
+#define SO_BROADCAST 6
+#define SO_SNDBUF 7
+#define SO_RCVBUF 8
+#define SO_KEEPALIVE 9
+#define SO_LINGER 13
+#define SO_REUSEPORT 15
+#define SO_RCVTIMEO 20
+#define SO_SNDTIMEO 21
+
+#define TCP_NODELAY 1
+#define TCP_KEEPIDLE 4
+#define TCP_KEEPINTVL 5
+#define TCP_QUICKACK 12
+#define TCP_FASTOPEN_CONNECT 30
+
+#define IP_TTL 2
+#define IP_MULTICAST_TTL 33
+#define IP_MULTICAST_LOOP 34
+#define IP_ADD_MEMBERSHIP 35
+#define IP_DROP_MEMBERSHIP 36
+
+#define IPV6_MULTICAST_LOOP 19
+#define IPV6_JOIN_GROUP 20
+#define IPV6_LEAVE_GROUP 21
+#define IPV6_V6ONLY 26
+
+struct addrinfo {
+ int ai_flags; /* Input flags. */
+ int ai_family; /* Protocol family for socket. */
+ int ai_socktype; /* Socket type. */
+ int ai_protocol; /* Protocol for socket. */
+ socklen_t ai_addrlen; /* Length of socket address. */
+ struct sockaddr *ai_addr; /* Socket address for socket. */
+ char *ai_canonname; /* Canonical name for service location. */
+ struct addrinfo *ai_next; /* Pointer to next in list. */
+};
+
+#ifndef __WASI_RIGHTS_SOCK_ACCEPT
+int
+accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+#endif
+
+int
+bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+int
+connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+int
+listen(int sockfd, int backlog);
+
+ssize_t
+recvmsg(int sockfd, struct msghdr *msg, int flags);
+
+ssize_t
+sendmsg(int sockfd, const struct msghdr *msg, int flags);
+
+ssize_t
+sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen);
+
+ssize_t
+recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen);
+
+int
+socket(int domain, int type, int protocol);
+
+int
+getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+int
+getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+int
+getsockopt(int sockfd, int level, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen);
+
+int
+setsockopt(int sockfd, int level, int optname, const void *optval,
+ socklen_t optlen);
+
+int
+getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
+ struct addrinfo **res);
+
+void
+freeaddrinfo(struct addrinfo *res);
+#endif
+
+/**
+ * __wasi_sock_accept was introduced in wasi-sdk v15. To
+ * temporarily maintain backward compatibility with the old
+ * wasi-sdk, we explicitly add that implementation here so it works
+ * with older versions of the SDK.
+ */
+#ifndef __WASI_RIGHTS_SOCK_ACCEPT
+/**
+ * Accept a connection on a socket
+ * Note: This is similar to `accept`
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_accept(int32_t arg0, int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_accept")));
+
+static inline __wasi_errno_t
+__wasi_sock_accept(__wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_accept(
+ (int32_t)fd, (int32_t)flags, (int32_t)fd_new);
+}
+#endif
+
+/**
+ * Returns the local address to which the socket is bound.
+ *
+ * Note: This is similar to `getsockname` in POSIX
+ *
+ * When successful, the contents of the output buffer consist of an IP address,
+ * either IP4 or IP6.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_addr_local")));
+
+static inline __wasi_errno_t
+__wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
+ (int32_t)fd, (int32_t)addr);
+}
+
+/**
+ * Returns the remote address to which the socket is connected to.
+ *
+ * Note: This is similar to `getpeername` in POSIX
+ *
+ * When successful, the contents of the output buffer consist of an IP address,
+ * either IP4 or IP6.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_addr_remote")));
+
+static inline __wasi_errno_t
+__wasi_sock_addr_remote(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
+ (int32_t)fd, (int32_t)addr);
+}
+
+/**
+ * Resolve a hostname and a service to one or more IP addresses. Service is
+ * optional and you can pass empty string in most cases, it is used as a hint
+ * for protocol.
+ *
+ * Note: This is similar to `getaddrinfo` in POSIX
+ *
+ * When successful, the contents of the output buffer consist of a sequence of
+ * IPv4 and/or IPv6 addresses. Each address entry consists of a wasi_addr_t
+ * object.
+ *
+ * This function fills the output buffer as much as possible, truncating the
+ * entries that didn't fit into the buffer. A number of available addresses
+ * will be returned through the last parameter.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_addr_resolve(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_addr_resolve")));
+
+static inline __wasi_errno_t
+__wasi_sock_addr_resolve(const char *host, const char *service,
+ __wasi_addr_info_hints_t *hints,
+ __wasi_addr_info_t *addr_info,
+ __wasi_size_t addr_info_size,
+ __wasi_size_t *max_info_size)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_resolve(
+ (int32_t)host, (int32_t)service, (int32_t)hints, (int32_t)addr_info,
+ (int32_t)addr_info_size, (int32_t)max_info_size);
+}
+
+/**
+ * Bind a socket
+ * Note: This is similar to `bind` in POSIX using PF_INET
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_bind(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_bind")));
+
+static inline __wasi_errno_t
+__wasi_sock_bind(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_bind(
+ (int32_t)fd, (int32_t)addr);
+}
+
+/**
+ * Send data to a specific target
+ * Note: This is similar to `sendto` in POSIX
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_send_to(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_send_to")));
+
+static inline __wasi_errno_t
+__wasi_sock_send_to(__wasi_fd_t fd, const __wasi_ciovec_t *si_data,
+ uint32_t si_data_len, __wasi_siflags_t si_flags,
+ const __wasi_addr_t *dest_addr, uint32_t *so_data_len)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_send_to(
+ (int32_t)fd, (int32_t)si_data, (int32_t)si_data_len, (int32_t)si_flags,
+ (uint32_t)dest_addr, (uint32_t)so_data_len);
+}
+
+/**
+ * Receives data from a socket
+ * Note: This is similar to `recvfrom` in POSIX
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_recv_from(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_recv_from")));
+
+static inline __wasi_errno_t
+__wasi_sock_recv_from(__wasi_fd_t fd, __wasi_ciovec_t *ri_data,
+ uint32_t ri_data_len, __wasi_riflags_t ri_flags,
+ __wasi_addr_t *src_addr, uint32_t *ro_data_len)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_recv_from(
+ (int32_t)fd, (int32_t)ri_data, (int32_t)ri_data_len, (int32_t)ri_flags,
+ (uint32_t)src_addr, (uint32_t)ro_data_len);
+}
+
+/**
+ * Close a socket (this is an alias for `fd_close`)
+ * Note: This is similar to `close` in POSIX.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_close(int32_t arg0)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_close")));
+
+static inline __wasi_errno_t
+__wasi_sock_close(__wasi_fd_t fd)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_close(
+ (int32_t)fd);
+}
+
+/**
+ * Initiate a connection on a socket to the specified address
+ * Note: This is similar to `connect` in POSIX
+ */
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_connect(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_connect")));
+
+static inline __wasi_errno_t
+__wasi_sock_connect(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_connect(
+ (int32_t)fd, (int32_t)addr);
+}
+/**
+ * Retrieve the size of the receive buffer
+ * Note: This is similar to `getsockopt` in POSIX for SO_RCVBUF
+ */
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_recv_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_recv_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_recv_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_recv_buf_size((int32_t)fd,
+ (int32_t)size);
+}
+/**
+ * Retrieve status of address reuse on a socket
+ * Note: This is similar to `getsockopt` in POSIX for SO_REUSEADDR
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_reuse_addr(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_reuse_addr")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_reuse_addr(__wasi_fd_t fd, bool *reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_reuse_addr((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Retrieve status of port reuse on a socket
+ * Note: This is similar to `getsockopt` in POSIX for SO_REUSEPORT
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_reuse_port(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_reuse_port")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_reuse_port(__wasi_fd_t fd, bool *reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_reuse_port((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Retrieve the size of the send buffer
+ * Note: This is similar to `getsockopt` in POSIX for SO_SNDBUF
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_send_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_send_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_send_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_send_buf_size((int32_t)fd,
+ (int32_t)size);
+}
+
+/**
+ * Listen for connections on a socket
+ * Note: This is similar to `listen`
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_listen(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_listen")));
+
+static inline __wasi_errno_t
+__wasi_sock_listen(__wasi_fd_t fd, __wasi_size_t backlog)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_listen(
+ (int32_t)fd, (int32_t)backlog);
+}
+
+/**
+ * Open a socket
+
+ * The first argument to this function is a handle to an
+ * address pool. The address pool determines what actions can
+ * be performed and at which addresses they can be performed to.
+
+ * The address pool cannot be re-assigned. You will need to close
+ * the socket and open a new one to use a different address pool.
+
+ * Note: This is similar to `socket` in POSIX using PF_INET
+ */
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_open(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_open")));
+
+static inline __wasi_errno_t
+__wasi_sock_open(__wasi_fd_t fd, __wasi_address_family_t af,
+ __wasi_sock_type_t socktype, __wasi_fd_t *sockfd)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_open(
+ (int32_t)fd, (int32_t)af, (int32_t)socktype, (int32_t)sockfd);
+}
+
+/**
+ * Set size of receive buffer
+ * Note: This is similar to `setsockopt` in POSIX for SO_RCVBUF
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_recv_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_recv_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_recv_buf_size(__wasi_fd_t fd, __wasi_size_t size)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_recv_buf_size((int32_t)fd,
+ (int32_t)size);
+}
+
+/**
+ * Enable/disable address reuse on a socket
+ * Note: This is similar to `setsockopt` in POSIX for SO_REUSEADDR
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_reuse_addr(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_reuse_addr")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_reuse_addr(__wasi_fd_t fd, bool reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_reuse_addr((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Enable port reuse on a socket
+ * Note: This is similar to `setsockopt` in POSIX for SO_REUSEPORT
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_reuse_port(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_reuse_port")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_reuse_port(__wasi_fd_t fd, bool reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_reuse_port((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Set size of send buffer
+ * Note: This is similar to `setsockopt` in POSIX for SO_SNDBUF
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_send_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_send_buf_size(__wasi_fd_t fd, __wasi_size_t buf_len)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_send_buf_size(
+ (int32_t)fd, (int32_t)buf_len);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_recv_timeout(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_recv_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_recv_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_recv_timeout(
+ (int32_t)fd, (int32_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_recv_timeout(int32_t arg0,
+ int64_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_recv_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_recv_timeout(__wasi_fd_t fd, uint64_t timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_recv_timeout(
+ (int32_t)fd, (int64_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_send_timeout(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_send_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_send_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_send_timeout(
+ (int32_t)fd, (int32_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_send_timeout(int32_t arg0,
+ int64_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_send_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_send_timeout(
+ (int32_t)fd, (int64_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_keep_alive(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_keep_alive")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_keep_alive(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_keep_alive((int32_t)fd,
+ (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_keep_alive(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_keep_alive")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_keep_alive(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_keep_alive((int32_t)fd,
+ (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_linger(int32_t arg0, int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_linger")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_linger(__wasi_fd_t fd, bool is_enabled, int linger_s)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_linger(
+ (int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_linger(int32_t arg0, int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_linger")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_linger(__wasi_fd_t fd, bool *is_enabled, int *linger_s)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_linger(
+ (int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_keep_idle")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_keep_idle(__wasi_fd_t fd, uint32_t time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_keep_idle")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_keep_idle(__wasi_fd_t fd, uint32_t *time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_keep_intvl")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_keep_intvl(__wasi_fd_t fd, uint32_t time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_keep_intvl")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_keep_intvl(__wasi_fd_t fd, uint32_t *time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_fastopen_connect")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_fastopen_connect(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_fastopen_connect")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_fastopen_connect(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_multicast_loop")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(
+ (int32_t)fd, (int32_t)ipv6, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ip_multicast_loop")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(
+ (int32_t)fd, (int32_t)ipv6, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_multicast_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_multicast_ttl(__wasi_fd_t fd, uint8_t option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ip_multicast_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ip_multicast_ttl(__wasi_fd_t fd, uint8_t *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_add_membership(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_add_membership")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_add_membership(__wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_add_membership(
+ (int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_drop_membership")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_drop_membership(__wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(
+ (int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_broadcast(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_broadcast")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_broadcast(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_broadcast(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_broadcast(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_broadcast")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_broadcast(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_broadcast(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_no_delay")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_no_delay(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_no_delay")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_no_delay(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_quick_ack")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_quick_ack(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_quick_ack")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_quick_ack(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_ttl(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_ttl(__wasi_fd_t fd, uint8_t option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ip_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ip_ttl(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ip_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ip_ttl(__wasi_fd_t fd, uint8_t *option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ip_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ipv6_only(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ipv6_only")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ipv6_only(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ipv6_only(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ipv6_only(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ipv6_only")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ipv6_only(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ipv6_only(
+ (int32_t)fd, (int32_t)option);
+}
+/**
+ * TODO: modify recv() and send()
+ * since don't want to re-compile the wasi-libc,
+ * we tend to keep original implentations of recv() and send().
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake
new file mode 100644
index 000000000..209b0c4c9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake
@@ -0,0 +1,9 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.8...3.16)
+
+project(socket_wasi_ext)
+
+add_library(${PROJECT_NAME} STATIC ${CMAKE_CURRENT_LIST_DIR}/src/wasi/wasi_socket_ext.c)
+target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc/)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c
new file mode 100644
index 000000000..defbc6efe
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c
@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <wasi/api.h>
+#include <wasi_socket_ext.h>
+
+#define HANDLE_ERROR(error) \
+ if (error != __WASI_ERRNO_SUCCESS) { \
+ errno = error; \
+ return -1; \
+ }
+
+static void
+ipv4_addr_to_wasi_ip4_addr(uint32_t addr_num, __wasi_addr_ip4_t *out)
+{
+ addr_num = ntohl(addr_num);
+ out->n0 = (addr_num & 0xFF000000) >> 24;
+ out->n1 = (addr_num & 0x00FF0000) >> 16;
+ out->n2 = (addr_num & 0x0000FF00) >> 8;
+ out->n3 = (addr_num & 0x000000FF);
+}
+
+/* addr_num and port are in network order */
+static void
+ipv4_addr_to_wasi_addr(uint32_t addr_num, uint16_t port, __wasi_addr_t *out)
+{
+ out->kind = IPv4;
+ out->addr.ip4.port = ntohs(port);
+ ipv4_addr_to_wasi_ip4_addr(addr_num, &(out->addr.ip4.addr));
+}
+
+static void
+ipv6_addr_to_wasi_ipv6_addr(uint16_t *addr, __wasi_addr_ip6_t *out)
+{
+ out->n0 = ntohs(addr[0]);
+ out->n1 = ntohs(addr[1]);
+ out->n2 = ntohs(addr[2]);
+ out->n3 = ntohs(addr[3]);
+ out->h0 = ntohs(addr[4]);
+ out->h1 = ntohs(addr[5]);
+ out->h2 = ntohs(addr[6]);
+ out->h3 = ntohs(addr[7]);
+}
+
+static void
+ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out)
+{
+ out->kind = IPv6;
+ out->addr.ip6.port = ntohs(port);
+ ipv6_addr_to_wasi_ipv6_addr(addr, &(out->addr.ip6.addr));
+}
+
+static __wasi_errno_t
+sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
+ __wasi_addr_t *wasi_addr)
+{
+ __wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
+ if (AF_INET == sock_addr->sa_family) {
+ assert(sizeof(struct sockaddr_in) <= addrlen);
+
+ ipv4_addr_to_wasi_addr(
+ ((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
+ ((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
+ }
+ else if (AF_INET6 == sock_addr->sa_family) {
+ assert(sizeof(struct sockaddr_in6) <= addrlen);
+ ipv6_addr_to_wasi_addr(
+ (uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_addr,
+ ((struct sockaddr_in6 *)sock_addr)->sin6_port, wasi_addr);
+ }
+ else {
+ ret = __WASI_ERRNO_AFNOSUPPORT;
+ }
+
+ return ret;
+}
+
+static __wasi_errno_t
+wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
+ struct sockaddr *sock_addr, socklen_t *addrlen)
+{
+ switch (wasi_addr->kind) {
+ case IPv4:
+ {
+ struct sockaddr_in sock_addr_in;
+ uint32_t s_addr;
+
+ memset(&sock_addr_in, 0, sizeof(sock_addr_in));
+
+ s_addr = (wasi_addr->addr.ip4.addr.n0 << 24)
+ | (wasi_addr->addr.ip4.addr.n1 << 16)
+ | (wasi_addr->addr.ip4.addr.n2 << 8)
+ | wasi_addr->addr.ip4.addr.n3;
+
+ sock_addr_in.sin_family = AF_INET;
+ sock_addr_in.sin_addr.s_addr = htonl(s_addr);
+ sock_addr_in.sin_port = htons(wasi_addr->addr.ip4.port);
+ memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
+
+ *addrlen = sizeof(sock_addr_in);
+ break;
+ }
+ case IPv6:
+ {
+ struct sockaddr_in6 sock_addr_in6;
+
+ memset(&sock_addr_in6, 0, sizeof(sock_addr_in6));
+
+ uint16_t *addr_buf = (uint16_t *)sock_addr_in6.sin6_addr.s6_addr;
+
+ addr_buf[0] = htons(wasi_addr->addr.ip6.addr.n0);
+ addr_buf[1] = htons(wasi_addr->addr.ip6.addr.n1);
+ addr_buf[2] = htons(wasi_addr->addr.ip6.addr.n2);
+ addr_buf[3] = htons(wasi_addr->addr.ip6.addr.n3);
+ addr_buf[4] = htons(wasi_addr->addr.ip6.addr.h0);
+ addr_buf[5] = htons(wasi_addr->addr.ip6.addr.h1);
+ addr_buf[6] = htons(wasi_addr->addr.ip6.addr.h2);
+ addr_buf[7] = htons(wasi_addr->addr.ip6.addr.h3);
+
+ sock_addr_in6.sin6_family = AF_INET6;
+ sock_addr_in6.sin6_port = htons(wasi_addr->addr.ip6.port);
+ memcpy(sock_addr, &sock_addr_in6, sizeof(sock_addr_in6));
+
+ *addrlen = sizeof(sock_addr_in6);
+ break;
+ }
+ default:
+ return __WASI_ERRNO_AFNOSUPPORT;
+ }
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_fd_t new_sockfd;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = __wasi_sock_accept(sockfd, 0, &new_sockfd);
+ HANDLE_ERROR(error)
+
+ if (getpeername(new_sockfd, addr, addrlen) == -1) {
+ return -1;
+ }
+
+ return new_sockfd;
+}
+
+int
+bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = __wasi_sock_bind(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ if (NULL == addr) {
+ HANDLE_ERROR(__WASI_ERRNO_INVAL)
+ }
+
+ error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = __wasi_sock_connect(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+listen(int sockfd, int backlog)
+{
+ __wasi_errno_t error = __wasi_sock_listen(sockfd, backlog);
+ HANDLE_ERROR(error)
+ return __WASI_ERRNO_SUCCESS;
+}
+
+ssize_t
+recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+ // Prepare input parameters.
+ __wasi_iovec_t *ri_data = NULL;
+ size_t i = 0;
+ size_t ro_datalen = 0;
+ __wasi_roflags_t ro_flags = 0;
+
+ if (NULL == msg) {
+ HANDLE_ERROR(__WASI_ERRNO_INVAL)
+ }
+
+ // Validate flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ // __wasi_ciovec_t -> struct iovec
+ if (!(ri_data = (__wasi_iovec_t *)malloc(sizeof(__wasi_iovec_t)
+ * msg->msg_iovlen))) {
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ ri_data[i].buf = (uint8_t *)msg->msg_iov[i].iov_base;
+ ri_data[i].buf_len = msg->msg_iov[i].iov_len;
+ }
+
+ // Perform system call.
+ __wasi_errno_t error = __wasi_sock_recv(sockfd, ri_data, msg->msg_iovlen, 0,
+ &ro_datalen, &ro_flags);
+ free(ri_data);
+ HANDLE_ERROR(error)
+
+ return ro_datalen;
+}
+
+ssize_t
+sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+ // Prepare input parameters.
+ __wasi_ciovec_t *si_data = NULL;
+ size_t so_datalen = 0;
+ size_t i = 0;
+
+ if (NULL == msg) {
+ HANDLE_ERROR(__WASI_ERRNO_INVAL)
+ }
+
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ // struct iovec -> __wasi_ciovec_t
+ if (!(si_data = (__wasi_ciovec_t *)malloc(sizeof(__wasi_ciovec_t)
+ * msg->msg_iovlen))) {
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ si_data[i].buf = (uint8_t *)msg->msg_iov[i].iov_base;
+ si_data[i].buf_len = msg->msg_iov[i].iov_len;
+ }
+
+ // Perform system call.
+ __wasi_errno_t error =
+ __wasi_sock_send(sockfd, si_data, msg->msg_iovlen, 0, &so_datalen);
+ free(si_data);
+ HANDLE_ERROR(error)
+
+ return so_datalen;
+}
+
+ssize_t
+sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+ // Prepare input parameters.
+ __wasi_ciovec_t iov = { .buf = (uint8_t *)buf, .buf_len = len };
+ uint32_t so_datalen = 0;
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+ size_t si_data_len = 1;
+ __wasi_siflags_t si_flags = 0;
+
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ error = sockaddr_to_wasi_addr(dest_addr, addrlen, &wasi_addr);
+ HANDLE_ERROR(error);
+
+ // Perform system call.
+ error = __wasi_sock_send_to(sockfd, &iov, si_data_len, si_flags, &wasi_addr,
+ &so_datalen);
+ HANDLE_ERROR(error)
+
+ return so_datalen;
+}
+
+ssize_t
+recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ // Prepare input parameters.
+ __wasi_ciovec_t iov = { .buf = (uint8_t *)buf, .buf_len = len };
+ uint32_t so_datalen = 0;
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+ size_t si_data_len = 1;
+ __wasi_siflags_t si_flags = 0;
+
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ if (!src_addr) {
+ return recv(sockfd, buf, len, flags);
+ }
+
+ // Perform system call.
+ error = __wasi_sock_recv_from(sockfd, &iov, si_data_len, si_flags,
+ &wasi_addr, &so_datalen);
+ HANDLE_ERROR(error);
+
+ error = wasi_addr_to_sockaddr(&wasi_addr, src_addr, addrlen);
+ HANDLE_ERROR(error);
+
+ return so_datalen;
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ // the stub of address pool fd
+ __wasi_fd_t poolfd = -1;
+ __wasi_fd_t sockfd;
+ __wasi_errno_t error;
+ __wasi_address_family_t af;
+ __wasi_sock_type_t socktype;
+
+ if (AF_INET == domain) {
+ af = INET4;
+ }
+ else if (AF_INET6 == domain) {
+ af = INET6;
+ }
+ else {
+ return __WASI_ERRNO_NOPROTOOPT;
+ }
+
+ if (SOCK_DGRAM == type) {
+ socktype = SOCKET_DGRAM;
+ }
+ else if (SOCK_STREAM == type) {
+ socktype = SOCKET_STREAM;
+ }
+ else {
+ return __WASI_ERRNO_NOPROTOOPT;
+ }
+
+ error = __wasi_sock_open(poolfd, af, socktype, &sockfd);
+ HANDLE_ERROR(error)
+
+ return sockfd;
+}
+
+int
+getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = __wasi_sock_addr_local(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = __wasi_sock_addr_remote(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+struct aibuf {
+ struct addrinfo ai;
+ union sa {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } sa;
+};
+
+static __wasi_errno_t
+addrinfo_hints_to_wasi_hints(const struct addrinfo *hints,
+ __wasi_addr_info_hints_t *wasi_hints)
+{
+ if (hints) {
+ wasi_hints->hints_enabled = 1;
+
+ switch (hints->ai_family) {
+ case AF_INET:
+ wasi_hints->family = INET4;
+ break;
+ case AF_INET6:
+ wasi_hints->family = INET6;
+ break;
+ default:
+ return __WASI_ERRNO_AFNOSUPPORT;
+ }
+ switch (hints->ai_socktype) {
+ case SOCK_STREAM:
+ wasi_hints->type = SOCKET_STREAM;
+ break;
+ case SOCK_DGRAM:
+ wasi_hints->type = SOCKET_DGRAM;
+ break;
+ default:
+ return __WASI_ERRNO_NOTSUP;
+ }
+
+ if (hints->ai_protocol != 0) {
+ return __WASI_ERRNO_NOTSUP;
+ }
+
+ if (hints->ai_flags != 0) {
+ return __WASI_ERRNO_NOTSUP;
+ }
+ }
+ else {
+ wasi_hints->hints_enabled = 0;
+ }
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+static __wasi_errno_t
+wasi_addr_info_to_addr_info(const __wasi_addr_info_t *addr_info,
+ struct addrinfo *ai)
+{
+ ai->ai_socktype =
+ addr_info->type == SOCKET_DGRAM ? SOCK_DGRAM : SOCK_STREAM;
+ ai->ai_protocol = 0;
+ ai->ai_canonname = NULL;
+
+ if (addr_info->addr.kind == IPv4) {
+ ai->ai_family = AF_INET;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ }
+ else {
+ ai->ai_family = AF_INET6;
+ ai->ai_addrlen = sizeof(struct sockaddr_in6);
+ }
+
+ return wasi_addr_to_sockaddr(&addr_info->addr, ai->ai_addr,
+ &ai->ai_addrlen); // TODO err handling
+}
+
+int
+getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ __wasi_addr_info_hints_t wasi_hints;
+ __wasi_addr_info_t *addr_info = NULL;
+ __wasi_size_t addr_info_size, i;
+ __wasi_size_t max_info_size = 16;
+ __wasi_errno_t error;
+ struct aibuf *aibuf_res;
+
+ error = addrinfo_hints_to_wasi_hints(hints, &wasi_hints);
+ HANDLE_ERROR(error)
+
+ do {
+ if (addr_info)
+ free(addr_info);
+
+ addr_info_size = max_info_size;
+ addr_info = (__wasi_addr_info_t *)malloc(addr_info_size
+ * sizeof(__wasi_addr_info_t));
+
+ if (!addr_info) {
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ error = __wasi_sock_addr_resolve(node, service == NULL ? "" : service,
+ &wasi_hints, addr_info, addr_info_size,
+ &max_info_size);
+ if (error != __WASI_ERRNO_SUCCESS) {
+ free(addr_info);
+ HANDLE_ERROR(error);
+ }
+ } while (max_info_size > addr_info_size);
+
+ if (addr_info_size == 0) {
+ free(addr_info);
+ *res = NULL;
+ return __WASI_ERRNO_SUCCESS;
+ }
+
+ aibuf_res =
+ (struct aibuf *)calloc(1, addr_info_size * sizeof(struct aibuf));
+ if (!aibuf_res) {
+ free(addr_info);
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ *res = &aibuf_res[0].ai;
+
+ if (addr_info_size) {
+ addr_info_size = max_info_size;
+ }
+
+ for (i = 0; i < addr_info_size; i++) {
+ struct addrinfo *ai = &aibuf_res[i].ai;
+ ai->ai_addr = (struct sockaddr *)&aibuf_res[i].sa;
+
+ error = wasi_addr_info_to_addr_info(&addr_info[i], ai);
+ if (error != __WASI_ERRNO_SUCCESS) {
+ free(addr_info);
+ free(aibuf_res);
+ HANDLE_ERROR(error)
+ }
+ ai->ai_next = i == addr_info_size - 1 ? NULL : &aibuf_res[i + 1].ai;
+ }
+
+ free(addr_info);
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+void
+freeaddrinfo(struct addrinfo *res)
+{
+ /* res is a pointer to a first field in the first element
+ * of aibuf array allocated in getaddrinfo, therefore this call
+ * frees the memory of the entire array. */
+ free(res);
+}
+
+static struct timeval
+time_us_to_timeval(uint64_t time_us)
+{
+ struct timeval tv;
+ tv.tv_sec = time_us / 1000000UL;
+ tv.tv_usec = time_us % 1000000UL;
+ return tv;
+}
+
+static uint64_t
+timeval_to_time_us(struct timeval tv)
+{
+ return (tv.tv_sec * 1000000UL) + tv.tv_usec;
+}
+
+static int
+get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+ uint64_t timeout_us;
+ bool is_linger_enabled;
+ int linger_s;
+
+ switch (optname) {
+ case SO_RCVTIMEO:
+ assert(*optlen == sizeof(struct timeval));
+ error = __wasi_sock_get_recv_timeout(sockfd, &timeout_us);
+ HANDLE_ERROR(error);
+ *(struct timeval *)optval = time_us_to_timeval(timeout_us);
+ return error;
+ case SO_SNDTIMEO:
+ assert(*optlen == sizeof(struct timeval));
+ error = __wasi_sock_get_send_timeout(sockfd, &timeout_us);
+ HANDLE_ERROR(error);
+ *(struct timeval *)optval = time_us_to_timeval(timeout_us);
+ return error;
+ case SO_SNDBUF:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_send_buf_size(sockfd, (size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_RCVBUF:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_recv_buf_size(sockfd, (size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_KEEPALIVE:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_keep_alive(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_REUSEADDR:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_reuse_addr(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_REUSEPORT:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_reuse_port(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_LINGER:
+ assert(*optlen == sizeof(struct linger));
+ error =
+ __wasi_sock_get_linger(sockfd, &is_linger_enabled, &linger_s);
+ HANDLE_ERROR(error);
+ ((struct linger *)optval)->l_onoff = (int)is_linger_enabled;
+ ((struct linger *)optval)->l_linger = linger_s;
+ return error;
+ case SO_BROADCAST:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_broadcast(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+get_ipproto_tcp_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+ switch (optname) {
+ case TCP_KEEPIDLE:
+ assert(*optlen == sizeof(uint32_t));
+ error = __wasi_sock_get_tcp_keep_idle(sockfd, (uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_KEEPINTVL:
+ assert(*optlen == sizeof(uint32_t));
+ error = __wasi_sock_get_tcp_keep_intvl(sockfd, (uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_FASTOPEN_CONNECT:
+ assert(*optlen == sizeof(int));
+ error =
+ __wasi_sock_get_tcp_fastopen_connect(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_NODELAY:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_tcp_no_delay(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_QUICKACK:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_tcp_quick_ack(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+get_ipproto_ip_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+
+ switch (optname) {
+ case IP_MULTICAST_LOOP:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ip_multicast_loop(sockfd, false,
+ (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_TTL:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ip_ttl(sockfd, (uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_MULTICAST_TTL:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ip_multicast_ttl(sockfd, (uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+get_ipproto_ipv6_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+
+ switch (optname) {
+ case IPV6_V6ONLY:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ipv6_only(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_MULTICAST_LOOP:
+ assert(*optlen == sizeof(int));
+ error =
+ __wasi_sock_get_ip_multicast_loop(sockfd, true, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+int
+getsockopt(int sockfd, int level, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+
+ switch (level) {
+ case SOL_SOCKET:
+ return get_sol_socket_option(sockfd, optname, optval, optlen);
+ case IPPROTO_TCP:
+ return get_ipproto_tcp_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IP:
+ return get_ipproto_ip_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IPV6:
+ return get_ipproto_ipv6_option(sockfd, optname, optval, optlen);
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+set_sol_socket_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+ uint64_t timeout_us;
+
+ switch (optname) {
+ case SO_RCVTIMEO:
+ {
+ assert(optlen == sizeof(struct timeval));
+ timeout_us = timeval_to_time_us(*(struct timeval *)optval);
+ error = __wasi_sock_set_recv_timeout(sockfd, timeout_us);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_SNDTIMEO:
+ {
+ assert(optlen == sizeof(struct timeval));
+ timeout_us = timeval_to_time_us(*(struct timeval *)optval);
+ error = __wasi_sock_set_send_timeout(sockfd, timeout_us);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_SNDBUF:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_send_buf_size(sockfd, *(size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_RCVBUF:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_recv_buf_size(sockfd, *(size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_KEEPALIVE:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_keep_alive(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_REUSEADDR:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_reuse_addr(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_REUSEPORT:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_reuse_port(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_LINGER:
+ {
+ assert(optlen == sizeof(struct linger));
+ struct linger *linger_opt = ((struct linger *)optval);
+ error = __wasi_sock_set_linger(sockfd, (bool)linger_opt->l_onoff,
+ linger_opt->l_linger);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_BROADCAST:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_broadcast(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ default:
+ {
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+ }
+}
+
+static int
+set_ipproto_tcp_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+
+ switch (optname) {
+ case TCP_NODELAY:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_tcp_no_delay(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_KEEPIDLE:
+ assert(optlen == sizeof(uint32_t));
+ error = __wasi_sock_set_tcp_keep_idle(sockfd, *(uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_KEEPINTVL:
+ assert(optlen == sizeof(uint32_t));
+ error = __wasi_sock_set_tcp_keep_intvl(sockfd, *(uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_FASTOPEN_CONNECT:
+ assert(optlen == sizeof(int));
+ error =
+ __wasi_sock_set_tcp_fastopen_connect(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_QUICKACK:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_tcp_quick_ack(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+set_ipproto_ip_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+ __wasi_addr_ip_t imr_multiaddr;
+ struct ip_mreq *ip_mreq_opt;
+
+ switch (optname) {
+ case IP_MULTICAST_LOOP:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ip_multicast_loop(sockfd, false,
+ *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_ADD_MEMBERSHIP:
+ assert(optlen == sizeof(struct ip_mreq));
+ ip_mreq_opt = (struct ip_mreq *)optval;
+ imr_multiaddr.kind = IPv4;
+ ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
+ &imr_multiaddr.addr.ip4);
+ error = __wasi_sock_set_ip_add_membership(
+ sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_DROP_MEMBERSHIP:
+ assert(optlen == sizeof(struct ip_mreq));
+ ip_mreq_opt = (struct ip_mreq *)optval;
+ imr_multiaddr.kind = IPv4;
+ ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
+ &imr_multiaddr.addr.ip4);
+ error = __wasi_sock_set_ip_drop_membership(
+ sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_TTL:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ip_ttl(sockfd, *(uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_MULTICAST_TTL:
+ assert(optlen == sizeof(int));
+ error =
+ __wasi_sock_set_ip_multicast_ttl(sockfd, *(uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+set_ipproto_ipv6_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+ struct ipv6_mreq *ipv6_mreq_opt;
+ __wasi_addr_ip_t imr_multiaddr;
+
+ switch (optname) {
+ case IPV6_V6ONLY:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ipv6_only(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_MULTICAST_LOOP:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ip_multicast_loop(sockfd, true,
+ *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_JOIN_GROUP:
+ assert(optlen == sizeof(struct ipv6_mreq));
+ ipv6_mreq_opt = (struct ipv6_mreq *)optval;
+ imr_multiaddr.kind = IPv6;
+ ipv6_addr_to_wasi_ipv6_addr(
+ (uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
+ &imr_multiaddr.addr.ip6);
+ error = __wasi_sock_set_ip_add_membership(
+ sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_LEAVE_GROUP:
+ assert(optlen == sizeof(struct ipv6_mreq));
+ ipv6_mreq_opt = (struct ipv6_mreq *)optval;
+ imr_multiaddr.kind = IPv6;
+ ipv6_addr_to_wasi_ipv6_addr(
+ (uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
+ &imr_multiaddr.addr.ip6);
+ error = __wasi_sock_set_ip_drop_membership(
+ sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+int
+setsockopt(int sockfd, int level, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+
+ switch (level) {
+ case SOL_SOCKET:
+ return set_sol_socket_option(sockfd, optname, optval, optlen);
+ case IPPROTO_TCP:
+ return set_ipproto_tcp_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IP:
+ return set_ipproto_ip_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IPV6:
+ return set_ipproto_ipv6_option(sockfd, optname, optval, optlen);
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh
new file mode 100755
index 000000000..24f5ee676
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set -eo pipefail
+CC="${CC:=/opt/wasi-sdk/bin/clang}"
+files=("tcp_udp.c" "nslookup.c")
+
+for file in "${files[@]}"
+do
+ echo $file
+ $CC \
+ --target=wasm32-wasi-threads \
+ -I../inc \
+ ../src/wasi/wasi_socket_ext.c -pthread -ftls-model=local-exec \
+ -Wl,--allow-undefined \
+ -Wl,--strip-all,--no-entry \
+ -Wl,--export=__heap_base \
+ -Wl,--export=__data_end \
+ -Wl,--shared-memory,--max-memory=10485760 \
+ -Wl,--export=malloc \
+ -Wl,--export=free \
+ -o "${file%.*}.wasm" "$file"
+done \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c
new file mode 100644
index 000000000..37150f1eb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <assert.h>
+#include <string.h>
+#ifdef __wasi__
+#include <wasi/api.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <wasi_socket_ext.h>
+#else
+#include <netdb.h>
+#endif
+
+void
+test_nslookup(int af)
+{
+ struct addrinfo *res;
+ int count = 0;
+ struct addrinfo hints;
+ char *url = "google-public-dns-a.google.com";
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_STREAM;
+ int ret = getaddrinfo(url, 0, &hints, &res);
+ assert(ret == 0);
+ struct addrinfo *address = res;
+ while (address) {
+ assert(address->ai_family == af);
+ assert(address->ai_socktype == SOCK_STREAM);
+ count++;
+ address = address->ai_next;
+ }
+
+ assert(count > 0);
+ freeaddrinfo(res);
+}
+
+int
+main()
+{
+ test_nslookup(AF_INET); /* for ipv4 */
+ test_nslookup(AF_INET6); /* for ipv6 */
+
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c
new file mode 100644
index 000000000..49231de89
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#ifdef __wasi__
+#include <wasi/api.h>
+#include <sys/socket.h>
+#include <wasi_socket_ext.h>
+#endif
+#include <arpa/inet.h>
+#include <pthread.h>
+#define SERVER_MSG "Message from server."
+#define PORT 8989
+pthread_mutex_t mut;
+pthread_cond_t cond;
+int server_init_complete = 0;
+char buffer[sizeof(SERVER_MSG) + 1];
+
+struct socket_info {
+ union {
+ struct sockaddr_in addr_ipv4;
+ struct sockaddr_in6 addr_ipv6;
+ } addr;
+ int sock;
+};
+
+struct thread_args {
+ int family;
+ int protocol;
+};
+
+struct socket_info
+init_socket_addr(int family, int protocol)
+{
+ int sock = socket(family, protocol, 0);
+ assert(sock != -1);
+
+ struct socket_info info;
+ if (family == AF_INET) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(PORT);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ info.addr.addr_ipv4 = addr;
+ }
+ else if (family == AF_INET6) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = htons(PORT);
+ addr.sin6_addr = in6addr_loopback;
+ info.addr.addr_ipv6 = addr;
+ }
+ info.sock = sock;
+ return info;
+}
+
+void
+assert_thread_args(struct thread_args *args)
+{
+ assert(args->family == AF_INET || args->family == AF_INET6);
+ assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM);
+}
+
+void *
+server(void *arg)
+{
+ server_init_complete = 0;
+ struct thread_args *args = (struct thread_args *)arg;
+ assert_thread_args(args);
+
+ struct socket_info init_server_sock =
+ init_socket_addr(args->family, args->protocol);
+
+ int server_sock = init_server_sock.sock;
+ socklen_t addr_size;
+ struct sockaddr_storage client_addr;
+ strcpy(buffer, SERVER_MSG);
+
+ struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr;
+ int ret = bind(server_sock, server_addr,
+ args->family == AF_INET ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6));
+ assert(ret == 0);
+
+ (args->protocol == SOCK_STREAM) && listen(server_sock, 1);
+ pthread_mutex_lock(&mut);
+ server_init_complete = 1;
+ pthread_mutex_unlock(&mut);
+ pthread_cond_signal(&cond);
+
+ addr_size = sizeof(client_addr);
+ if (args->protocol == SOCK_STREAM) {
+ int client_sock =
+ accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
+ assert(client_sock >= 0);
+ sendto(client_sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&client_addr, addr_size);
+
+ assert(close(client_sock) == 0);
+ }
+ else {
+ recvfrom(server_sock, buffer, sizeof(buffer), 0,
+ (struct sockaddr *)&client_addr, &addr_size);
+ sendto(server_sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&client_addr, addr_size);
+
+ assert(close(server_sock) == 0);
+ }
+
+ return NULL;
+}
+
+void *
+client(void *arg)
+{
+ struct thread_args *args = (struct thread_args *)arg;
+ assert_thread_args(args);
+
+ pthread_mutex_lock(&mut);
+
+ while (server_init_complete == 0) {
+ pthread_cond_wait(&cond, &mut);
+ }
+
+ struct socket_info init_client_sock =
+ init_socket_addr(args->family, args->protocol);
+ int sock = init_client_sock.sock;
+ pthread_mutex_unlock(&mut);
+
+ if (args->family == AF_INET) {
+ struct sockaddr_in addr = init_client_sock.addr.addr_ipv4;
+ if (args->protocol == SOCK_STREAM) {
+ assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
+ }
+ else {
+ assert(sendto(sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&addr, sizeof(addr))
+ != -1);
+ }
+ }
+ else {
+ struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6;
+ if (args->protocol == SOCK_STREAM) {
+ assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
+ }
+ else {
+ assert(sendto(sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&addr, sizeof(addr))
+ != -1);
+ }
+ }
+
+ recv(sock, buffer, sizeof(buffer), 0);
+ assert(strcmp(buffer, SERVER_MSG) == 0);
+ assert(close(sock) == 0);
+ return NULL;
+}
+
+void
+test_protocol(int family, int protocol)
+{
+ pthread_t server_thread, client_thread;
+ assert(pthread_cond_init(&cond, NULL) == 0);
+ assert(pthread_mutex_init(&mut, NULL) == 0);
+
+ struct thread_args args = { family, protocol };
+ assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0);
+ assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0);
+ assert(pthread_join(server_thread, NULL) == 0);
+ assert(pthread_join(client_thread, NULL) == 0);
+
+ assert(pthread_mutex_destroy(&mut) == 0);
+ assert(pthread_cond_destroy(&cond) == 0);
+}
+
+int
+main(int argc, char **argv)
+{
+ /* test tcp with ipv4 and ipv6 */
+ test_protocol(AF_INET, SOCK_STREAM);
+ test_protocol(AF_INET6, SOCK_STREAM);
+
+ /* test udp with ipv4 and ipv6 */
+ test_protocol(AF_INET, SOCK_DGRAM);
+ test_protocol(AF_INET6, SOCK_DGRAM);
+
+ return 0;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
new file mode 100644
index 000000000..54d2ba902
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_WASI_THREADS_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIB_WASI_THREADS=1 -DWASM_ENABLE_HEAP_AUX_STACK_ALLOCATION=1)
+
+include_directories(${LIB_WASI_THREADS_DIR})
+
+set (LIB_WASI_THREADS_SOURCE
+ ${LIB_WASI_THREADS_DIR}/lib_wasi_threads_wrapper.c
+ ${LIB_WASI_THREADS_DIR}/tid_allocator.c) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
new file mode 100644
index 000000000..6b36c9073
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "thread_manager.h"
+#include "tid_allocator.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+static const char *THREAD_START_FUNCTION = "wasi_thread_start";
+static korp_mutex thread_id_lock;
+static TidAllocator tid_allocator;
+
+typedef struct {
+ /* app's entry function */
+ wasm_function_inst_t start_func;
+ /* arg of the app's entry function */
+ uint32 arg;
+ /* thread id passed to the app */
+ int32 thread_id;
+} ThreadStartArg;
+
+static int32
+allocate_thread_id()
+{
+ os_mutex_lock(&thread_id_lock);
+ int32 id = tid_allocator_get_tid(&tid_allocator);
+ os_mutex_unlock(&thread_id_lock);
+
+ return id;
+}
+
+void
+deallocate_thread_id(int32 thread_id)
+{
+ os_mutex_lock(&thread_id_lock);
+ tid_allocator_release_tid(&tid_allocator, thread_id);
+ os_mutex_unlock(&thread_id_lock);
+}
+
+static void *
+thread_start(void *arg)
+{
+ wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
+ ThreadStartArg *thread_arg = exec_env->thread_arg;
+ uint32 argv[2];
+
+ wasm_exec_env_set_thread_info(exec_env);
+ argv[0] = thread_arg->thread_id;
+ argv[1] = thread_arg->arg;
+
+ if (!wasm_runtime_call_wasm(exec_env, thread_arg->start_func, 2, argv)) {
+ /* Exception has already been spread during throwing */
+ }
+
+ // Routine exit
+ deallocate_thread_id(thread_arg->thread_id);
+ wasm_runtime_free(thread_arg);
+ exec_env->thread_arg = NULL;
+
+ return NULL;
+}
+
+static int32
+thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
+{
+ wasm_module_t module = wasm_exec_env_get_module(exec_env);
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_inst_t new_module_inst = NULL;
+ ThreadStartArg *thread_start_arg = NULL;
+ wasm_function_inst_t start_func;
+ int32 thread_id;
+ uint32 stack_size = 8192;
+ int32 ret = -1;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIContext *wasi_ctx;
+#endif
+
+ bh_assert(module);
+ bh_assert(module_inst);
+
+ stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
+
+ if (!(new_module_inst = wasm_runtime_instantiate_internal(
+ module, true, exec_env, stack_size, 0, NULL, 0)))
+ return -1;
+
+ wasm_runtime_set_custom_data_internal(
+ new_module_inst, wasm_runtime_get_custom_data(module_inst));
+
+ if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
+ goto thread_preparation_fail;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ if (wasi_ctx)
+ wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
+#endif
+
+ start_func = wasm_runtime_lookup_function(new_module_inst,
+ THREAD_START_FUNCTION, NULL);
+ if (!start_func) {
+ LOG_ERROR("Failed to find thread start function %s",
+ THREAD_START_FUNCTION);
+ goto thread_preparation_fail;
+ }
+
+ if (!(thread_start_arg = wasm_runtime_malloc(sizeof(ThreadStartArg)))) {
+ LOG_ERROR("Runtime args allocation failed");
+ goto thread_preparation_fail;
+ }
+
+ thread_start_arg->thread_id = thread_id = allocate_thread_id();
+ if (thread_id < 0) {
+ LOG_ERROR("Failed to get thread identifier");
+ goto thread_preparation_fail;
+ }
+ thread_start_arg->arg = start_arg;
+ thread_start_arg->start_func = start_func;
+
+ ret = wasm_cluster_create_thread(exec_env, new_module_inst, false,
+ thread_start, thread_start_arg);
+ if (ret != 0) {
+ LOG_ERROR("Failed to spawn a new thread");
+ goto thread_spawn_fail;
+ }
+
+ return thread_id;
+
+thread_spawn_fail:
+ deallocate_thread_id(thread_id);
+
+thread_preparation_fail:
+ if (new_module_inst)
+ wasm_runtime_deinstantiate_internal(new_module_inst, true);
+ if (thread_start_arg)
+ wasm_runtime_free(thread_start_arg);
+
+ return -1;
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(name, func_name, signature) \
+ { name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_wasi_threads[] = { REG_NATIVE_FUNC(
+ "thread-spawn", thread_spawn, "(i)i") };
+
+uint32
+get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis)
+{
+ *p_lib_wasi_threads_apis = native_symbols_lib_wasi_threads;
+ return sizeof(native_symbols_lib_wasi_threads) / sizeof(NativeSymbol);
+}
+
+bool
+lib_wasi_threads_init(void)
+{
+ if (0 != os_mutex_init(&thread_id_lock))
+ return false;
+
+ if (!tid_allocator_init(&tid_allocator)) {
+ os_mutex_destroy(&thread_id_lock);
+ return false;
+ }
+
+ return true;
+}
+
+void
+lib_wasi_threads_destroy(void)
+{
+ tid_allocator_deinit(&tid_allocator);
+ os_mutex_destroy(&thread_id_lock);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh
new file mode 100755
index 000000000..32586c20c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+set -eo pipefail
+CC=${CC:=/opt/wasi-sdk/bin/clang}
+WAMR_DIR=../../../../..
+
+for test_c in *.c; do
+ test_wasm="$(basename $test_c .c).wasm"
+
+ if [ $test_wasm = "linear_memory_size_update.wasm" ]; then
+ thread_start_file=""
+ else
+ thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S
+ fi
+
+ echo "Compiling $test_c to $test_wasm"
+ $CC \
+ -target wasm32-wasi-threads \
+ -pthread -ftls-model=local-exec \
+ -z stack-size=32768 \
+ -Wl,--export=__heap_base \
+ -Wl,--export=__data_end \
+ -Wl,--shared-memory,--max-memory=1966080 \
+ -Wl,--export=wasi_thread_start \
+ -Wl,--export=malloc \
+ -Wl,--export=free \
+ -I $WAMR_DIR/samples/wasi-threads/wasm-apps \
+ $thread_start_file \
+ $test_c -o $test_wasm
+done \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h
new file mode 100644
index 000000000..01ca932c5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <limits.h>
+
+#if USE_CUSTOM_SYNC_PRIMITIVES != 0
+#include "sync_primitives.h"
+#else
+#include <pthread.h>
+#endif
+
+#include "wasi_thread_start.h"
+
+typedef enum {
+ BLOCKING_TASK_BUSY_WAIT,
+ BLOCKING_TASK_ATOMIC_WAIT,
+ BLOCKING_TASK_POLL_ONEOFF
+} blocking_task_type_t;
+
+/* Parameter to change test behavior */
+static bool termination_by_trap;
+static bool termination_in_main_thread;
+static blocking_task_type_t blocking_task_type;
+
+#define NUM_THREADS 3
+static pthread_barrier_t barrier;
+
+typedef struct {
+ start_args_t base;
+ bool throw_exception;
+} shared_t;
+
+void
+run_long_task()
+{
+ if (blocking_task_type == BLOCKING_TASK_BUSY_WAIT) {
+ for (;;) {
+ }
+ }
+ else if (blocking_task_type == BLOCKING_TASK_ATOMIC_WAIT) {
+ __builtin_wasm_memory_atomic_wait32(0, 0, -1);
+ }
+ else {
+ sleep(UINT_MAX);
+ }
+}
+
+void
+start_job()
+{
+ /* Wait for all threads (including the main thread) to be ready */
+ pthread_barrier_wait(&barrier);
+ run_long_task(); /* Task to be interrupted */
+ assert(false && "Thread termination test failed");
+}
+
+void
+terminate_process()
+{
+ /* Wait for all threads (including the main thread) to be ready */
+ pthread_barrier_wait(&barrier);
+
+ if (termination_by_trap)
+ __builtin_trap();
+ else
+ __wasi_proc_exit(33);
+}
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ if (data->throw_exception) {
+ terminate_process();
+ }
+ else {
+ start_job();
+ }
+}
+
+void
+test_termination(bool trap, bool main, blocking_task_type_t task_type)
+{
+ termination_by_trap = trap;
+ termination_in_main_thread = main;
+ blocking_task_type = task_type;
+
+ int thread_id = -1, i;
+ shared_t data[NUM_THREADS] = { 0 };
+ assert(pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1) == 0
+ && "Failed to init barrier");
+
+ for (i = 0; i < NUM_THREADS; i++) {
+ /* No graceful memory free to simplify the test */
+ assert(start_args_init(&data[i].base)
+ && "Failed to allocate thread's stack");
+ }
+
+ /* Create a thread that forces termination through trap or `proc_exit` */
+ data[0].throw_exception = !termination_in_main_thread;
+ thread_id = __wasi_thread_spawn(&data[0]);
+ assert(thread_id > 0 && "Failed to create thread");
+
+ /* Create two additional threads to test exception propagation */
+ data[1].throw_exception = false;
+ thread_id = __wasi_thread_spawn(&data[1]);
+ assert(thread_id > 0 && "Failed to create thread");
+ data[2].throw_exception = false;
+ thread_id = __wasi_thread_spawn(&data[2]);
+ assert(thread_id > 0 && "Failed to create thread");
+
+ if (termination_in_main_thread) {
+ terminate_process();
+ }
+ else {
+ start_job();
+ }
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c
new file mode 100644
index 000000000..23ba5f627
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ MAX_NUM_THREADS = 4, /* Should be the same as "--max-threads" */
+ NUM_RETRY = 5,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+int g_count = 0;
+
+typedef struct {
+ start_args_t base;
+ int th_ready;
+ int th_continue;
+ int th_done;
+ bool no_ops;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ if (data->no_ops) {
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, 2 * SECOND);
+ return;
+ }
+
+ __atomic_store_n(&data->th_ready, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
+
+ if (__builtin_wasm_memory_atomic_wait32(&data->th_continue, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ __atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[MAX_NUM_THREADS] = { 0 };
+ int thread_ids[MAX_NUM_THREADS];
+
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base));
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ printf("Thread created with id=%d\n", thread_ids[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+
+ for (int j = 0; j < i; j++) {
+ assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs");
+ }
+
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_ready, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+ }
+
+ printf("Attempt to create thread when not possible\n");
+ shared_t data_fail = { 0 };
+ assert(start_args_init(&data_fail.base));
+ int thread_id = __wasi_thread_spawn(&data_fail);
+ start_args_deinit(&data_fail.base);
+ assert(thread_id < 0 && "Thread creation should fail");
+
+ printf("Unlock created threads\n");
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ __atomic_store_n(&data[i].th_continue, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data[i].th_continue, 1);
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ printf("Value of count after update: %d\n", g_count);
+ assert(g_count == (MAX_NUM_THREADS)
+ && "Global count not updated correctly");
+
+ /* --------------------------------------------------- */
+
+ printf("Create new threads without waiting from them to finish\n");
+ shared_t data_no_join[MAX_NUM_THREADS] = { 0 };
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ /* No graceful memory free to simplify the test */
+ assert(start_args_init(&data_no_join[i].base));
+ data_no_join[i].no_ops = true;
+
+ int thread_id = -1;
+ for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
+ thread_id = __wasi_thread_spawn(&data_no_join[i]);
+ if (thread_id < 0)
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
+ }
+
+ printf("Thread created with id=%d\n", thread_id);
+ assert(thread_id > 0 && "Thread creation should succeed");
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
new file mode 100644
index 000000000..a38e75364
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_THREADS = 4,
+ NUM_ITER = 1000,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+int g_count = 0;
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ for (int i = 0; i < NUM_ITER; i++)
+ __atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[NUM_THREADS] = { 0 };
+ int thread_ids[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base));
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ printf("Value of count after update: %d\n", g_count);
+ assert(g_count == (NUM_THREADS * NUM_ITER)
+ && "Global count not updated correctly");
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
new file mode 100644
index 000000000..f81fca49b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#if USE_CUSTOM_SYNC_PRIMITIVES != 0
+#include "sync_primitives.h"
+#else
+#include <pthread.h>
+#endif
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_THREADS = 4,
+ NUM_ITER = 200,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+pthread_mutex_t mutex;
+int g_count = 0;
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ for (int i = 0; i < NUM_ITER; i++) {
+ pthread_mutex_lock(&mutex);
+ g_count++;
+ pthread_mutex_unlock(&mutex);
+ }
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[NUM_THREADS] = { 0 };
+ int thread_ids[NUM_THREADS];
+
+ assert(pthread_mutex_init(&mutex, NULL) == 0 && "Failed to init mutex");
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base));
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ printf("Value of count after update: %d\n", g_count);
+ assert(g_count == (NUM_THREADS * NUM_ITER)
+ && "Global count not updated correctly");
+
+ assert(pthread_mutex_destroy(&mutex) == 0 && "Failed to destroy mutex");
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c
new file mode 100644
index 000000000..9dcb34a6c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <stdlib.h>
+#include <pthread.h>
+
+typedef enum {
+ APP_STARTED,
+ THREAD_STARTED,
+ MEMORY_ALLOCATED,
+} app_state_t;
+typedef struct {
+
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ app_state_t state;
+ char *data;
+} context_t;
+
+void
+context_init(context_t *ctx)
+{
+ pthread_cond_init(&ctx->cond, NULL);
+ pthread_mutex_init(&ctx->mutex, NULL);
+ ctx->state = APP_STARTED;
+ ctx->data = NULL;
+}
+
+void
+context_destroy(context_t *ctx)
+{
+ pthread_cond_destroy(&ctx->cond);
+ pthread_mutex_destroy(&ctx->mutex);
+ if (ctx->data) {
+ free(ctx->data);
+ }
+}
+
+void
+context_set_state(context_t *ctx, app_state_t state)
+{
+ pthread_mutex_lock(&ctx->mutex);
+ ctx->state = state;
+ pthread_mutex_unlock(&ctx->mutex);
+ pthread_cond_signal(&ctx->cond);
+}
+
+void
+context_wait_for_state(context_t *ctx, app_state_t state)
+{
+ pthread_mutex_lock(&ctx->mutex);
+ while (ctx->state != state) {
+ pthread_cond_wait(&ctx->cond, &ctx->mutex);
+ }
+ pthread_mutex_unlock(&ctx->mutex);
+}
+
+void *
+fnc(void *p)
+{
+ context_t *ctx = (context_t *)p;
+ context_set_state(ctx, THREAD_STARTED);
+
+ context_wait_for_state(ctx, MEMORY_ALLOCATED);
+
+ // trigger memory.copy
+ __builtin_memcpy(ctx->data + 512 * 1024, ctx->data + 1024, 1024);
+
+ return NULL;
+}
+
+int
+main()
+{
+ context_t ctx;
+ context_init(&ctx);
+
+ pthread_t th;
+ pthread_create(&th, NULL, fnc, &ctx);
+
+ context_wait_for_state(&ctx, THREAD_STARTED);
+
+ // trigger memory.grow
+ ctx.data = calloc(1024 * 1024, 1);
+
+ context_set_state(&ctx, MEMORY_ALLOCATED);
+
+ pthread_join(th, NULL);
+
+ context_destroy(&ctx);
+
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c
new file mode 100644
index 000000000..19d3ec256
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, true, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c
new file mode 100644
index 000000000..a667e9122
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, true, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c
new file mode 100644
index 000000000..dc8615adb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, true, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
new file mode 100644
index 000000000..bb0ac8fa0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, true, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
new file mode 100644
index 000000000..a2c248882
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, true, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
new file mode 100644
index 000000000..0904f34bb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, true, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c
new file mode 100644
index 000000000..71fdcb817
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, false, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c
new file mode 100644
index 000000000..14352cf41
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, false, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c
new file mode 100644
index 000000000..0963aa02f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, false, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c
new file mode 100644
index 000000000..b3e3af7dc
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, false, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c
new file mode 100644
index 000000000..a68ae8be5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, false, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c
new file mode 100644
index 000000000..52c684a51
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, false, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c
new file mode 100644
index 000000000..24664c470
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_ITER = 50,
+ NUM_RETRY = 5,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 5LL * SECOND
+};
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+} shared_t;
+
+int g_count = 0;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ g_count++;
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data = { 0 };
+ assert(start_args_init(&data.base) && "Stack allocation for thread failed");
+
+ for (int i = 0; i < NUM_ITER; i++) {
+ data.th_done = 0;
+
+ printf("Creating thread\n");
+ int thread_id = -1;
+ for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
+ thread_id = __wasi_thread_spawn(&data);
+ if (thread_id < 0)
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
+ }
+ assert(thread_id > 0 && "Thread creation should succeed");
+
+ printf("Waiting for thread to finish\n");
+ if (__builtin_wasm_memory_atomic_wait32(&data.th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+ printf("Thread has finished\n");
+ }
+
+ assert(g_count == NUM_ITER && "Count has not been updated correctly");
+
+ start_args_deinit(&data.base);
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h
new file mode 100644
index 000000000..4b7dac8ec
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdbool.h>
+
+/* Mutex */
+
+typedef int pthread_mutex_t;
+
+int
+pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
+{
+ *mutex = 0;
+ return 0;
+}
+
+int
+pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+ return 0;
+}
+
+static bool
+try_pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ int expected = 0;
+ return __atomic_compare_exchange_n(mutex, &expected, 1, false,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ while (!try_pthread_mutex_lock(mutex))
+ __builtin_wasm_memory_atomic_wait32(mutex, 1, -1);
+ return 0;
+}
+
+int
+pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+ __atomic_store_n(mutex, 0, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(mutex, 1);
+ return 0;
+}
+
+/* Barrier */
+
+typedef struct {
+ int count;
+ int num_threads;
+ int mutex;
+ int ready;
+} pthread_barrier_t;
+
+int
+pthread_barrier_init(pthread_barrier_t *barrier, void *unused, int num_threads)
+{
+ barrier->count = 0;
+ barrier->num_threads = num_threads;
+ barrier->ready = 0;
+ pthread_mutex_init(&barrier->mutex, NULL);
+
+ return 0;
+}
+
+int
+pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+ bool no_wait = false;
+ int count;
+
+ pthread_mutex_lock(&barrier->mutex);
+ count = barrier->count++;
+ if (barrier->count >= barrier->num_threads) {
+ no_wait = true;
+ barrier->count = 0;
+ }
+ pthread_mutex_unlock(&barrier->mutex);
+
+ if (no_wait) {
+ __atomic_store_n(&barrier->ready, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&barrier->ready, count);
+ return 0;
+ }
+
+ __builtin_wasm_memory_atomic_wait32(&barrier->ready, 0, -1);
+ return 0;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c
new file mode 100644
index 000000000..69e125d40
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 1LL * SECOND
+};
+
+typedef struct {
+ start_args_t base;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ /* Wait so that the exception is raised after the main thread has finished
+ * already */
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, TIMEOUT);
+ __builtin_trap();
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data = { 0 };
+
+ assert(start_args_init(&data.base));
+ int thread_id = __wasi_thread_spawn(&data);
+ assert(thread_id > 0 && "Thread creation failed");
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json
new file mode 100644
index 000000000..9dc1e30d2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c
new file mode 100644
index 000000000..b7fb9afba
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_THREADS = 4,
+ NUM_ITER = 30,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+ int *count;
+ int iteration;
+ int *pval;
+} shared_t;
+
+pthread_mutex_t mutex;
+int *vals[NUM_THREADS];
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ for (int i = 0; i < NUM_ITER; i++)
+ __atomic_fetch_add(data->count, 1, __ATOMIC_SEQ_CST);
+
+ *vals[data->iteration] = data->iteration;
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[NUM_THREADS] = { 0 };
+ int thread_ids[NUM_THREADS];
+ int *count = calloc(1, sizeof(int));
+
+ assert(count != NULL && "Failed to call calloc");
+ assert(pthread_mutex_init(&mutex, NULL) == 0 && "Failed to init mutex");
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ vals[i] = malloc(sizeof(int));
+ assert(vals[i] != NULL && "Failed to call calloc");
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base)
+ && "Stack allocation for thread failed");
+ __atomic_store_n(&data[i].count, count, __ATOMIC_SEQ_CST);
+ data[i].iteration = i;
+
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ assert(*count == (NUM_THREADS * NUM_ITER) && "Count not updated correctly");
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ printf("val=%d\n", *vals[i]);
+ assert(*vals[i] == i && "Value not updated correctly");
+ free(vals[i]);
+ }
+
+ free(count);
+ assert(pthread_mutex_destroy(&mutex) == 0 && "Failed to destroy mutex");
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c
new file mode 100644
index 000000000..4d53da0c9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "tid_allocator.h"
+#include "wasm_export.h"
+#include "bh_log.h"
+
+bh_static_assert(TID_MIN <= TID_MAX);
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+bool
+tid_allocator_init(TidAllocator *tid_allocator)
+{
+ tid_allocator->size = MIN(TID_ALLOCATOR_INIT_SIZE, TID_MAX - TID_MIN + 1);
+ tid_allocator->pos = tid_allocator->size;
+ tid_allocator->ids =
+ wasm_runtime_malloc(tid_allocator->size * sizeof(int32));
+ if (tid_allocator->ids == NULL)
+ return false;
+
+ for (int64 i = tid_allocator->pos - 1; i >= 0; i--)
+ tid_allocator->ids[i] = TID_MIN + (tid_allocator->pos - 1 - i);
+
+ return true;
+}
+
+void
+tid_allocator_deinit(TidAllocator *tid_allocator)
+{
+ wasm_runtime_free(tid_allocator->ids);
+}
+
+int32
+tid_allocator_get_tid(TidAllocator *tid_allocator)
+{
+ if (tid_allocator->pos == 0) { // Resize stack and push new thread ids
+ if (tid_allocator->size == TID_MAX - TID_MIN + 1) {
+ LOG_ERROR("Maximum thread identifier reached");
+ return -1;
+ }
+
+ uint32 old_size = tid_allocator->size;
+ uint32 new_size = MIN(tid_allocator->size * 2, TID_MAX - TID_MIN + 1);
+ if (new_size != TID_MAX - TID_MIN + 1
+ && new_size / 2 != tid_allocator->size) {
+ LOG_ERROR("Overflow detected during new size calculation");
+ return -1;
+ }
+
+ size_t realloc_size = new_size * sizeof(int32);
+ if (realloc_size / sizeof(int32) != new_size) {
+ LOG_ERROR("Overflow detected during realloc");
+ return -1;
+ }
+ int32 *tmp = wasm_runtime_realloc(tid_allocator->ids, realloc_size);
+ if (tmp == NULL) {
+ LOG_ERROR("Thread ID allocator realloc failed");
+ return -1;
+ }
+
+ tid_allocator->size = new_size;
+ tid_allocator->pos = new_size - old_size;
+ tid_allocator->ids = tmp;
+ for (int64 i = tid_allocator->pos - 1; i >= 0; i--)
+ tid_allocator->ids[i] = TID_MIN + (tid_allocator->size - 1 - i);
+ }
+
+ // Pop available thread identifier from the stack
+ return tid_allocator->ids[--tid_allocator->pos];
+}
+
+void
+tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id)
+{
+ // Release thread identifier by pushing it into the stack
+ bh_assert(tid_allocator->pos < tid_allocator->size);
+ tid_allocator->ids[tid_allocator->pos++] = thread_id;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h
new file mode 100644
index 000000000..53af1719f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _TID_ALLOCATOR_H
+#define _TID_ALLOCATOR_H
+
+#include "platform_common.h"
+
+#define TID_ALLOCATOR_INIT_SIZE CLUSTER_MAX_THREAD_NUM
+enum {
+ TID_MIN = 1,
+ TID_MAX = 0x1FFFFFFF
+}; // Reserved TIDs (WASI specification)
+
+/* Stack data structure to track available thread identifiers */
+typedef struct {
+ int32 *ids; // Array used to store the stack
+ uint32 size; // Stack capacity
+ uint32 pos; // Index of the element after the stack top
+} TidAllocator;
+
+bool
+tid_allocator_init(TidAllocator *tid_allocator);
+
+void
+tid_allocator_deinit(TidAllocator *tid_allocator);
+
+int32
+tid_allocator_get_tid(TidAllocator *tid_allocator);
+
+void
+tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id);
+
+#endif /* _TID_ALLOCATOR_H */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript
new file mode 100644
index 000000000..8dd004382
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+#src = Split('''
+#libc_builtin_wrapper.c
+#''')
+
+src = Glob('*.c')
+
+CPPDEFINES = ['WASM_ENABLE_LIBC_BUILTIN=1']
+
+CPPPATH = [cwd]
+
+
+group = DefineGroup('iwasm_libc_builtin', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake
new file mode 100644
index 000000000..0838712b8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
new file mode 100644
index 000000000..55916deb4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+
+#if defined(_WIN32) || defined(_WIN32_)
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#endif
+
+void
+wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
+
+uint32
+wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size,
+ void **p_native_addr);
+
+/* clang-format off */
+#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)
+
+#define validate_app_str_addr(offset) \
+ wasm_runtime_validate_app_str_addr(module_inst, offset)
+
+#define validate_native_addr(addr, size) \
+ wasm_runtime_validate_native_addr(module_inst, addr, size)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+
+#define module_malloc(size, p_native_addr) \
+ wasm_runtime_module_malloc(module_inst, size, p_native_addr)
+
+#define module_free(offset) \
+ wasm_runtime_module_free(module_inst, offset)
+/* clang-format on */
+
+typedef int (*out_func_t)(int c, void *ctx);
+
+typedef char *_va_list;
+#define _INTSIZEOF(n) (((uint32)sizeof(n) + 3) & (uint32)~3)
+#define _va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
+
+#define CHECK_VA_ARG(ap, t) \
+ do { \
+ if ((uint8 *)ap + _INTSIZEOF(t) > native_end_addr) { \
+ if (fmt_buf != temp_fmt) { \
+ wasm_runtime_free(fmt_buf); \
+ } \
+ goto fail; \
+ } \
+ } while (0)
+
+/* clang-format off */
+#define PREPARE_TEMP_FORMAT() \
+ char temp_fmt[32], *s, *fmt_buf = temp_fmt; \
+ uint32 fmt_buf_len = (uint32)sizeof(temp_fmt); \
+ int32 n; \
+ \
+ /* additional 2 bytes: one is the format char, \
+ the other is `\0` */ \
+ if ((uint32)(fmt - fmt_start_addr + 2) >= fmt_buf_len) { \
+ bh_assert((uint32)(fmt - fmt_start_addr) <= \
+ UINT32_MAX - 2); \
+ fmt_buf_len = (uint32)(fmt - fmt_start_addr + 2); \
+ if (!(fmt_buf = wasm_runtime_malloc(fmt_buf_len))) { \
+ print_err(out, ctx); \
+ break; \
+ } \
+ } \
+ \
+ memset(fmt_buf, 0, fmt_buf_len); \
+ bh_memcpy_s(fmt_buf, fmt_buf_len, fmt_start_addr, \
+ (uint32)(fmt - fmt_start_addr + 1));
+/* clang-format on */
+
+#define OUTPUT_TEMP_FORMAT() \
+ do { \
+ if (n > 0) { \
+ s = buf; \
+ while (*s) \
+ out((int)(*s++), ctx); \
+ } \
+ \
+ if (fmt_buf != temp_fmt) { \
+ wasm_runtime_free(fmt_buf); \
+ } \
+ } while (0)
+
+static void
+print_err(out_func_t out, void *ctx)
+{
+ out('E', ctx);
+ out('R', ctx);
+ out('R', ctx);
+}
+
+static bool
+_vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap,
+ wasm_module_inst_t module_inst)
+{
+ int might_format = 0; /* 1 if encountered a '%' */
+ int long_ctr = 0;
+ uint8 *native_end_addr;
+ const char *fmt_start_addr = NULL;
+
+ if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)ap, NULL,
+ &native_end_addr))
+ goto fail;
+
+ /* fmt has already been adjusted if needed */
+
+ while (*fmt) {
+ if (!might_format) {
+ if (*fmt != '%') {
+ out((int)*fmt, ctx);
+ }
+ else {
+ might_format = 1;
+ long_ctr = 0;
+ fmt_start_addr = fmt;
+ }
+ }
+ else {
+ switch (*fmt) {
+ case '.':
+ case '+':
+ case '-':
+ case ' ':
+ case '#':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ goto still_might_format;
+
+ case 't': /* ptrdiff_t */
+ case 'z': /* size_t (32bit on wasm) */
+ long_ctr = 1;
+ goto still_might_format;
+
+ case 'j':
+ /* intmax_t/uintmax_t */
+ long_ctr = 2;
+ goto still_might_format;
+
+ case 'l':
+ long_ctr++;
+ /* Fall through */
+ case 'h':
+ /* FIXME: do nothing for these modifiers */
+ goto still_might_format;
+
+ case 'o':
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'p':
+ case 'x':
+ case 'X':
+ case 'c':
+ {
+ char buf[64];
+ PREPARE_TEMP_FORMAT();
+
+ if (long_ctr < 2) {
+ int32 d;
+
+ CHECK_VA_ARG(ap, uint32);
+ d = _va_arg(ap, int32);
+
+ if (long_ctr == 1) {
+ uint32 fmt_end_idx = (uint32)(fmt - fmt_start_addr);
+
+ if (fmt_buf[fmt_end_idx - 1] == 'l'
+ || fmt_buf[fmt_end_idx - 1] == 'z'
+ || fmt_buf[fmt_end_idx - 1] == 't') {
+ /* The %ld, %zd and %td should be treated as
+ * 32bit integer in wasm */
+ fmt_buf[fmt_end_idx - 1] = fmt_buf[fmt_end_idx];
+ fmt_buf[fmt_end_idx] = '\0';
+ }
+ }
+
+ n = snprintf(buf, sizeof(buf), fmt_buf, d);
+ }
+ else {
+ int64 lld;
+
+ /* Make 8-byte aligned */
+ ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7);
+ CHECK_VA_ARG(ap, uint64);
+ lld = _va_arg(ap, int64);
+ n = snprintf(buf, sizeof(buf), fmt_buf, lld);
+ }
+
+ OUTPUT_TEMP_FORMAT();
+ break;
+ }
+
+ case 's':
+ {
+ char buf_tmp[128], *buf = buf_tmp;
+ char *start;
+ uint32 s_offset, str_len, buf_len;
+
+ PREPARE_TEMP_FORMAT();
+
+ CHECK_VA_ARG(ap, int32);
+ s_offset = _va_arg(ap, uint32);
+
+ if (!validate_app_str_addr(s_offset)) {
+ if (fmt_buf != temp_fmt) {
+ wasm_runtime_free(fmt_buf);
+ }
+ return false;
+ }
+
+ s = start = addr_app_to_native(s_offset);
+
+ str_len = (uint32)strlen(start);
+ if (str_len >= UINT32_MAX - 64) {
+ print_err(out, ctx);
+ if (fmt_buf != temp_fmt) {
+ wasm_runtime_free(fmt_buf);
+ }
+ break;
+ }
+
+ /* reserve 64 more bytes as there may be width description
+ * in the fmt */
+ buf_len = str_len + 64;
+
+ if (buf_len > (uint32)sizeof(buf_tmp)) {
+ if (!(buf = wasm_runtime_malloc(buf_len))) {
+ print_err(out, ctx);
+ if (fmt_buf != temp_fmt) {
+ wasm_runtime_free(fmt_buf);
+ }
+ break;
+ }
+ }
+
+ n = snprintf(buf, buf_len, fmt_buf,
+ (s_offset == 0 && str_len == 0) ? NULL
+ : start);
+
+ OUTPUT_TEMP_FORMAT();
+
+ if (buf != buf_tmp) {
+ wasm_runtime_free(buf);
+ }
+
+ break;
+ }
+
+ case '%':
+ {
+ out((int)'%', ctx);
+ break;
+ }
+
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'f':
+ case 'F':
+ {
+ float64 f64;
+ char buf[64];
+ PREPARE_TEMP_FORMAT();
+
+ /* Make 8-byte aligned */
+ ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7);
+ CHECK_VA_ARG(ap, float64);
+ f64 = _va_arg(ap, float64);
+ n = snprintf(buf, sizeof(buf), fmt_buf, f64);
+
+ OUTPUT_TEMP_FORMAT();
+ break;
+ }
+
+ case 'n':
+ /* print nothing */
+ break;
+
+ default:
+ out((int)'%', ctx);
+ out((int)*fmt, ctx);
+ break;
+ }
+
+ might_format = 0;
+ }
+
+ still_might_format:
+ ++fmt;
+ }
+ return true;
+
+fail:
+ wasm_runtime_set_exception(module_inst, "out of bounds memory access");
+ return false;
+}
+
+struct str_context {
+ char *str;
+ uint32 max;
+ uint32 count;
+};
+
+static int
+sprintf_out(int c, struct str_context *ctx)
+{
+ if (!ctx->str || ctx->count >= ctx->max) {
+ ctx->count++;
+ return c;
+ }
+
+ if (ctx->count == ctx->max - 1) {
+ ctx->str[ctx->count++] = '\0';
+ }
+ else {
+ ctx->str[ctx->count++] = (char)c;
+ }
+
+ return c;
+}
+
+#ifndef BUILTIN_LIBC_BUFFERED_PRINTF
+#define BUILTIN_LIBC_BUFFERED_PRINTF 0
+#endif
+
+#ifndef BUILTIN_LIBC_BUFFERED_PRINT_SIZE
+#define BUILTIN_LIBC_BUFFERED_PRINT_SIZE 128
+#endif
+#ifndef BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+#define BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+#endif
+
+#if BUILTIN_LIBC_BUFFERED_PRINTF != 0
+
+BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+static char print_buf[BUILTIN_LIBC_BUFFERED_PRINT_SIZE] = { 0 };
+
+BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+static int print_buf_size = 0;
+
+static int
+printf_out(int c, struct str_context *ctx)
+{
+ if (c == '\n') {
+ print_buf[print_buf_size] = '\0';
+ os_printf("%s\n", print_buf);
+ print_buf_size = 0;
+ }
+ else if (print_buf_size >= sizeof(print_buf) - 2) {
+ print_buf[print_buf_size++] = (char)c;
+ print_buf[print_buf_size] = '\0';
+ os_printf("%s\n", print_buf);
+ print_buf_size = 0;
+ }
+ else {
+ print_buf[print_buf_size++] = (char)c;
+ }
+ ctx->count++;
+ return c;
+}
+#else
+static int
+printf_out(int c, struct str_context *ctx)
+{
+ os_printf("%c", c);
+ ctx->count++;
+ return c;
+}
+#endif
+
+static int
+printf_wrapper(wasm_exec_env_t exec_env, const char *format, _va_list va_args)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ struct str_context ctx = { NULL, 0, 0 };
+
+ /* format has been checked by runtime */
+ if (!validate_native_addr(va_args, sizeof(int32)))
+ return 0;
+
+ if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args,
+ module_inst))
+ return 0;
+
+ return (int)ctx.count;
+}
+
+static int
+sprintf_wrapper(wasm_exec_env_t exec_env, char *str, const char *format,
+ _va_list va_args)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint8 *native_end_offset;
+ struct str_context ctx;
+
+ /* str and format have been checked by runtime */
+ if (!validate_native_addr(va_args, sizeof(uint32)))
+ return 0;
+
+ if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)str, NULL,
+ &native_end_offset)) {
+ wasm_runtime_set_exception(module_inst, "out of bounds memory access");
+ return false;
+ }
+
+ ctx.str = str;
+ ctx.max = (uint32)(native_end_offset - (uint8 *)str);
+ ctx.count = 0;
+
+ if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
+ module_inst))
+ return 0;
+
+ if (ctx.count < ctx.max) {
+ str[ctx.count] = '\0';
+ }
+
+ return (int)ctx.count;
+}
+
+static int
+snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size,
+ const char *format, _va_list va_args)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ struct str_context ctx;
+
+ /* str and format have been checked by runtime */
+ if (!validate_native_addr(va_args, sizeof(uint32)))
+ return 0;
+
+ ctx.str = str;
+ ctx.max = size;
+ ctx.count = 0;
+
+ if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
+ module_inst))
+ return 0;
+
+ if (ctx.count < ctx.max) {
+ str[ctx.count] = '\0';
+ }
+
+ return (int)ctx.count;
+}
+
+static int
+puts_wrapper(wasm_exec_env_t exec_env, const char *str)
+{
+ return os_printf("%s\n", str);
+}
+
+static int
+putchar_wrapper(wasm_exec_env_t exec_env, int c)
+{
+ os_printf("%c", c);
+ return 1;
+}
+
+static uint32
+strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char *str_ret;
+ uint32 len;
+ uint32 str_ret_offset = 0;
+
+ /* str has been checked by runtime */
+ if (str) {
+ len = (uint32)strlen(str) + 1;
+
+ str_ret_offset = module_malloc(len, (void **)&str_ret);
+ if (str_ret_offset) {
+ bh_memcpy_s(str_ret, len, str, len);
+ }
+ }
+
+ return str_ret_offset;
+}
+
+static uint32
+_strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
+{
+ return strdup_wrapper(exec_env, str);
+}
+
+static int32
+memcmp_wrapper(wasm_exec_env_t exec_env, const void *s1, const void *s2,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ /* s2 has been checked by runtime */
+ if (!validate_native_addr((void *)s1, size))
+ return 0;
+
+ return memcmp(s1, s2, size);
+}
+
+static uint32
+memcpy_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 dst_offset = addr_native_to_app(dst);
+
+ if (size == 0)
+ return dst_offset;
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return dst_offset;
+
+ bh_memcpy_s(dst, size, src, size);
+ return dst_offset;
+}
+
+static uint32
+memmove_wrapper(wasm_exec_env_t exec_env, void *dst, void *src, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 dst_offset = addr_native_to_app(dst);
+
+ if (size == 0)
+ return dst_offset;
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return dst_offset;
+
+ memmove(dst, src, size);
+ return dst_offset;
+}
+
+static uint32
+memset_wrapper(wasm_exec_env_t exec_env, void *s, int32 c, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 s_offset = addr_native_to_app(s);
+
+ if (!validate_native_addr(s, size))
+ return s_offset;
+
+ memset(s, c, size);
+ return s_offset;
+}
+
+static uint32
+strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char *ret;
+
+ /* s has been checked by runtime */
+ ret = strchr(s, c);
+ return ret ? addr_native_to_app(ret) : 0;
+}
+
+static int32
+strcmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2)
+{
+ /* s1 and s2 have been checked by runtime */
+ return strcmp(s1, s2);
+}
+
+static int32
+strncmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ /* s2 has been checked by runtime */
+ if (!validate_native_addr((void *)s1, size))
+ return 0;
+
+ return strncmp(s1, s2, size);
+}
+
+static uint32
+strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 len = (uint32)strlen(src) + 1;
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, len))
+ return 0;
+
+#ifndef BH_PLATFORM_WINDOWS
+ strncpy(dst, src, len);
+#else
+ strncpy_s(dst, len, src, len);
+#endif
+ return addr_native_to_app(dst);
+}
+
+static uint32
+strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return 0;
+
+#ifndef BH_PLATFORM_WINDOWS
+ strncpy(dst, src, size);
+#else
+ strncpy_s(dst, size, src, size);
+#endif
+ return addr_native_to_app(dst);
+}
+
+static uint32
+strlen_wrapper(wasm_exec_env_t exec_env, const char *s)
+{
+ /* s has been checked by runtime */
+ return (uint32)strlen(s);
+}
+
+static uint32
+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, NULL);
+}
+
+static uint32
+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;
+ uint32 ret_offset = 0;
+ uint8 *ret_ptr;
+
+ if (total_size >= UINT32_MAX)
+ return 0;
+
+ ret_offset = module_malloc((uint32)total_size, (void **)&ret_ptr);
+ if (ret_offset) {
+ memset(ret_ptr, 0, (uint32)total_size);
+ }
+
+ return ret_offset;
+}
+
+static uint32
+realloc_wrapper(wasm_exec_env_t exec_env, uint32 ptr, uint32 new_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ return wasm_runtime_module_realloc(module_inst, ptr, new_size, NULL);
+}
+
+static void
+free_wrapper(wasm_exec_env_t exec_env, void *ptr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (!validate_native_addr(ptr, sizeof(uint32)))
+ return;
+
+ module_free(addr_native_to_app(ptr));
+}
+
+static int32
+atoi_wrapper(wasm_exec_env_t exec_env, const char *s)
+{
+ /* s has been checked by runtime */
+ return atoi(s);
+}
+
+static void
+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(%" PRId32 ")", status);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static int32
+strtol_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
+ int32 base)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ int32 num = 0;
+
+ /* nptr has been checked by runtime */
+ if (!validate_native_addr(endptr, sizeof(uint32)))
+ return 0;
+
+ num = (int32)strtol(nptr, endptr, base);
+ *(uint32 *)endptr = addr_native_to_app(*endptr);
+
+ return num;
+}
+
+static uint32
+strtoul_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
+ int32 base)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 num = 0;
+
+ /* nptr has been checked by runtime */
+ if (!validate_native_addr(endptr, sizeof(uint32)))
+ return 0;
+
+ num = (uint32)strtoul(nptr, endptr, base);
+ *(uint32 *)endptr = addr_native_to_app(*endptr);
+
+ return num;
+}
+
+static uint32
+memchr_wrapper(wasm_exec_env_t exec_env, const void *s, int32 c, uint32 n)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ void *res;
+
+ if (!validate_native_addr((void *)s, n))
+ return 0;
+
+ res = memchr(s, c, n);
+ return addr_native_to_app(res);
+}
+
+static int32
+strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
+ uint32 n)
+{
+ /* s1 and s2 have been checked by runtime */
+ return strncasecmp(s1, s2, n);
+}
+
+static uint32
+strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept)
+{
+ /* s and accept have been checked by runtime */
+ return (uint32)strspn(s, accept);
+}
+
+static uint32
+strcspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *reject)
+{
+ /* s and reject have been checked by runtime */
+ return (uint32)strcspn(s, reject);
+}
+
+static uint32
+strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ /* s and find have been checked by runtime */
+ char *res = strstr(s, find);
+ return addr_native_to_app(res);
+}
+
+static int32
+isupper_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isupper(c);
+}
+
+static int32
+isalpha_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isalpha(c);
+}
+
+static int32
+isspace_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isspace(c);
+}
+
+static int32
+isgraph_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isgraph(c);
+}
+
+static int32
+isprint_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isprint(c);
+}
+
+static int32
+isdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isdigit(c);
+}
+
+static int32
+isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isxdigit(c);
+}
+
+static int32
+tolower_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return tolower(c);
+}
+
+static int32
+toupper_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return toupper(c);
+}
+
+static int32
+isalnum_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isalnum(c);
+}
+
+static uint32
+emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst,
+ const void *src, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 dst_offset = addr_native_to_app(dst);
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return dst_offset;
+
+ bh_memcpy_s(dst, size, src, size);
+ return dst_offset;
+}
+
+static void
+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(%" PRId32 ")", code);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static void
+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(%" PRId32 ")", code);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static void
+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(%" PRId32 ")", code);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static uint32
+__cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 exception = module_malloc(thrown_size, NULL);
+ if (!exception)
+ return 0;
+
+ return exception;
+}
+
+static void
+__cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, void *exception_object)
+{}
+
+static void
+__cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception,
+ void *tinfo, 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++");
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+struct timespec_app {
+ int64 tv_sec;
+ int32 tv_nsec;
+};
+
+static uint32
+clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id,
+ struct timespec_app *ts_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint64 time;
+
+ if (!validate_native_addr(ts_app, sizeof(struct timespec_app)))
+ return (uint32)-1;
+
+ time = os_time_get_boot_microsecond();
+ ts_app->tv_sec = time / 1000000;
+ ts_app->tv_nsec = (time % 1000000) * 1000;
+
+ return (uint32)0;
+}
+
+static uint64
+clock_wrapper(wasm_exec_env_t exec_env)
+{
+ /* Convert to nano seconds as CLOCKS_PER_SEC in wasi-sdk */
+
+ return os_time_get_boot_microsecond() * 1000;
+}
+
+#if WASM_ENABLE_SPEC_TEST != 0
+static void
+print_wrapper(wasm_exec_env_t exec_env)
+{
+ os_printf("in specttest.print()\n");
+}
+
+static void
+print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
+{
+ os_printf("in specttest.print_i32(%" PRId32 ")\n", i32);
+}
+
+static void
+print_i32_f32_wrapper(wasm_exec_env_t exec_env, int32 i32, float f32)
+{
+ os_printf("in specttest.print_i32_f32(%" PRId32 ", %f)\n", i32, f32);
+}
+
+static void
+print_f64_f64_wrapper(wasm_exec_env_t exec_env, double f64_1, double f64_2)
+{
+ os_printf("in specttest.print_f64_f64(%f, %f)\n", f64_1, f64_2);
+}
+
+static void
+print_f32_wrapper(wasm_exec_env_t exec_env, float f32)
+{
+ os_printf("in specttest.print_f32(%f)\n", f32);
+}
+
+static void
+print_f64_wrapper(wasm_exec_env_t exec_env, double f64)
+{
+ os_printf("in specttest.print_f64(%f)\n", f64);
+}
+#endif /* WASM_ENABLE_SPEC_TEST */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_libc_builtin[] = {
+ REG_NATIVE_FUNC(printf, "($*)i"),
+ REG_NATIVE_FUNC(sprintf, "($$*)i"),
+ REG_NATIVE_FUNC(snprintf, "(*~$*)i"),
+ { "vprintf", printf_wrapper, "($*)i", NULL },
+ { "vsprintf", sprintf_wrapper, "($$*)i", NULL },
+ { "vsnprintf", snprintf_wrapper, "(*~$*)i", NULL },
+ REG_NATIVE_FUNC(puts, "($)i"),
+ REG_NATIVE_FUNC(putchar, "(i)i"),
+ REG_NATIVE_FUNC(memcmp, "(**~)i"),
+ REG_NATIVE_FUNC(memcpy, "(**~)i"),
+ REG_NATIVE_FUNC(memmove, "(**~)i"),
+ REG_NATIVE_FUNC(memset, "(*ii)i"),
+ REG_NATIVE_FUNC(strchr, "($i)i"),
+ REG_NATIVE_FUNC(strcmp, "($$)i"),
+ REG_NATIVE_FUNC(strcpy, "(*$)i"),
+ REG_NATIVE_FUNC(strlen, "($)i"),
+ REG_NATIVE_FUNC(strncmp, "(**~)i"),
+ REG_NATIVE_FUNC(strncpy, "(**~)i"),
+ REG_NATIVE_FUNC(malloc, "(i)i"),
+ REG_NATIVE_FUNC(realloc, "(ii)i"),
+ REG_NATIVE_FUNC(calloc, "(ii)i"),
+ REG_NATIVE_FUNC(strdup, "($)i"),
+ /* clang may introduce __strdup */
+ REG_NATIVE_FUNC(_strdup, "($)i"),
+ REG_NATIVE_FUNC(free, "(*)"),
+ REG_NATIVE_FUNC(atoi, "($)i"),
+ REG_NATIVE_FUNC(exit, "(i)"),
+ REG_NATIVE_FUNC(strtol, "($*i)i"),
+ REG_NATIVE_FUNC(strtoul, "($*i)i"),
+ REG_NATIVE_FUNC(memchr, "(*ii)i"),
+ REG_NATIVE_FUNC(strncasecmp, "($$i)i"),
+ REG_NATIVE_FUNC(strspn, "($$)i"),
+ REG_NATIVE_FUNC(strcspn, "($$)i"),
+ REG_NATIVE_FUNC(strstr, "($$)i"),
+ REG_NATIVE_FUNC(isupper, "(i)i"),
+ REG_NATIVE_FUNC(isalpha, "(i)i"),
+ REG_NATIVE_FUNC(isspace, "(i)i"),
+ REG_NATIVE_FUNC(isgraph, "(i)i"),
+ REG_NATIVE_FUNC(isprint, "(i)i"),
+ REG_NATIVE_FUNC(isdigit, "(i)i"),
+ REG_NATIVE_FUNC(isxdigit, "(i)i"),
+ REG_NATIVE_FUNC(tolower, "(i)i"),
+ REG_NATIVE_FUNC(toupper, "(i)i"),
+ REG_NATIVE_FUNC(isalnum, "(i)i"),
+ REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"),
+ REG_NATIVE_FUNC(abort, "(i)"),
+ REG_NATIVE_FUNC(abortStackOverflow, "(i)"),
+ REG_NATIVE_FUNC(nullFunc_X, "(i)"),
+ REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"),
+ REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"),
+ REG_NATIVE_FUNC(__cxa_throw, "(**i)"),
+ REG_NATIVE_FUNC(clock_gettime, "(i*)i"),
+ REG_NATIVE_FUNC(clock, "()I"),
+};
+
+#if WASM_ENABLE_SPEC_TEST != 0
+static NativeSymbol native_symbols_spectest[] = {
+ REG_NATIVE_FUNC(print, "()"),
+ REG_NATIVE_FUNC(print_i32, "(i)"),
+ REG_NATIVE_FUNC(print_i32_f32, "(if)"),
+ REG_NATIVE_FUNC(print_f64_f64, "(FF)"),
+ REG_NATIVE_FUNC(print_f32, "(f)"),
+ REG_NATIVE_FUNC(print_f64, "(F)")
+};
+#endif
+
+uint32
+get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
+{
+ *p_libc_builtin_apis = native_symbols_libc_builtin;
+ return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
+}
+
+#if WASM_ENABLE_SPEC_TEST != 0
+uint32
+get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
+{
+ *p_libc_builtin_apis = native_symbols_spectest;
+ return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
+}
+#endif
+
+/*************************************
+ * Global Variables *
+ *************************************/
+
+typedef struct WASMNativeGlobalDef {
+ const char *module_name;
+ const char *global_name;
+ uint8 type;
+ bool is_mutable;
+ WASMValue value;
+} WASMNativeGlobalDef;
+
+static WASMNativeGlobalDef native_global_defs[] = {
+#if WASM_ENABLE_SPEC_TEST != 0
+ { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 },
+ { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 },
+ { "spectest", "global_f32", VALUE_TYPE_F32, false, .value.f32 = 666.6 },
+ { "spectest", "global_f64", VALUE_TYPE_F64, false, .value.f64 = 666.6 },
+ { "test", "global-i32", VALUE_TYPE_I32, false, .value.i32 = 0 },
+ { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 },
+ { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
+ { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
+#endif
+ { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL },
+ { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL }
+};
+
+bool
+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;
+ WASMNativeGlobalDef *global_def_end = global_def + size;
+
+ if (!module_name || !global_name || !global)
+ return false;
+
+ /* Lookup constant globals which can be defined by table */
+ while (global_def < global_def_end) {
+ if (!strcmp(global_def->module_name, module_name)
+ && !strcmp(global_def->global_name, global_name)) {
+ global->type = global_def->type;
+ global->is_mutable = global_def->is_mutable;
+ global->global_data_linked = global_def->value;
+ return true;
+ }
+ global_def++;
+ }
+
+ return false;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript
new file mode 100644
index 000000000..432ed4a05
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+libc_emcc_wrapper.c
+''')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_libc_emcc', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake
new file mode 100644
index 000000000..d237a16ee
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIBC_EMCC_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIBC_EMCC=1)
+
+include_directories(${LIBC_EMCC_DIR})
+
+file (GLOB source_all ${LIBC_EMCC_DIR}/*.c)
+
+set (LIBC_EMCC_SOURCE ${source_all}) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c
new file mode 100644
index 000000000..23c02aad3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+#if !defined(_DEFAULT_SOURCE) && !defined(BH_PLATFORM_LINUX_SGX)
+#include "sys/syscall.h"
+#endif
+
+/* clang-format off */
+#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)
+
+#define validate_app_str_addr(offset) \
+ wasm_runtime_validate_app_str_addr(module_inst, offset)
+
+#define validate_native_addr(addr, size) \
+ wasm_runtime_validate_native_addr(module_inst, addr, size)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+
+#define module_malloc(size, p_native_addr) \
+ wasm_runtime_module_malloc(module_inst, size, p_native_addr)
+
+#define module_free(offset) \
+ wasm_runtime_module_free(module_inst, offset)
+/* clang-format on */
+
+static void
+invoke_viiii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1, int arg2, int arg3)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ argv[2] = arg2;
+ argv[3] = arg3;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 4, argv);
+ (void)ret;
+}
+
+static void
+invoke_viii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1, int arg2)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ argv[2] = arg2;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 3, argv);
+ (void)ret;
+}
+
+static void
+invoke_vii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 2, argv);
+ (void)ret;
+}
+
+static void
+invoke_vi_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 1, argv);
+ (void)ret;
+}
+
+static int
+invoke_iii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 2, argv);
+ return ret ? argv[0] : 0;
+}
+
+static int
+invoke_ii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 1, argv);
+ return ret ? argv[0] : 0;
+}
+
+struct timespec_emcc {
+ int tv_sec;
+ int tv_nsec;
+};
+
+struct stat_emcc {
+ unsigned st_dev;
+ int __st_dev_padding;
+ unsigned __st_ino_truncated;
+ unsigned st_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned st_rdev;
+ int __st_rdev_padding;
+ int64 st_size;
+ int st_blksize;
+ int st_blocks;
+ struct timespec_emcc st_atim;
+ struct timespec_emcc st_mtim;
+ struct timespec_emcc st_ctim;
+ int64 st_ino;
+};
+
+static int
+open_wrapper(wasm_exec_env_t exec_env, const char *pathname, int flags,
+ int mode)
+{
+ if (pathname == NULL)
+ return -1;
+ return open(pathname, flags, mode);
+}
+
+static int
+__sys_read_wrapper(wasm_exec_env_t exec_env, int fd, void *buf, uint32 count)
+{
+ return read(fd, buf, count);
+}
+
+static void
+statbuf_native2app(const struct stat *statbuf_native,
+ struct stat_emcc *statbuf_app)
+{
+ statbuf_app->st_dev = (unsigned)statbuf_native->st_dev;
+ statbuf_app->__st_ino_truncated = (unsigned)statbuf_native->st_ino;
+ statbuf_app->st_mode = (unsigned)statbuf_native->st_mode;
+ statbuf_app->st_nlink = (unsigned)statbuf_native->st_nlink;
+ statbuf_app->st_uid = (unsigned)statbuf_native->st_uid;
+ statbuf_app->st_gid = (unsigned)statbuf_native->st_gid;
+ statbuf_app->st_rdev = (unsigned)statbuf_native->st_rdev;
+ statbuf_app->st_size = (int64)statbuf_native->st_size;
+ statbuf_app->st_blksize = (unsigned)statbuf_native->st_blksize;
+ statbuf_app->st_blocks = (unsigned)statbuf_native->st_blocks;
+ statbuf_app->st_ino = (int64)statbuf_native->st_ino;
+ statbuf_app->st_atim.tv_sec = (int)statbuf_native->st_atim.tv_sec;
+ statbuf_app->st_atim.tv_nsec = (int)statbuf_native->st_atim.tv_nsec;
+ statbuf_app->st_mtim.tv_sec = (int)statbuf_native->st_mtim.tv_sec;
+ statbuf_app->st_mtim.tv_nsec = (int)statbuf_native->st_mtim.tv_nsec;
+ statbuf_app->st_ctim.tv_sec = (int)statbuf_native->st_ctim.tv_sec;
+ statbuf_app->st_ctim.tv_nsec = (int)statbuf_native->st_ctim.tv_nsec;
+}
+
+static int
+__sys_stat64_wrapper(wasm_exec_env_t exec_env, const char *pathname,
+ struct stat_emcc *statbuf_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ int ret;
+ struct stat statbuf;
+
+ if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc)))
+ return -1;
+
+ if (pathname == NULL)
+ return -1;
+
+ ret = stat(pathname, &statbuf);
+ if (ret == 0)
+ statbuf_native2app(&statbuf, statbuf_app);
+ return ret;
+}
+
+static int
+__sys_fstat64_wrapper(wasm_exec_env_t exec_env, int fd,
+ struct stat_emcc *statbuf_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ int ret;
+ struct stat statbuf;
+
+ if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc)))
+ return -1;
+
+ if (fd <= 0)
+ return -1;
+
+ ret = fstat(fd, &statbuf);
+ if (ret == 0)
+ statbuf_native2app(&statbuf, statbuf_app);
+ return ret;
+}
+
+static int
+mmap_wrapper(wasm_exec_env_t exec_env, void *addr, int length, int prot,
+ int flags, int fd, int64 offset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 buf_offset;
+ char *buf;
+ int size_read;
+
+ buf_offset = module_malloc(length, (void **)&buf);
+ if (buf_offset == 0)
+ return -1;
+
+ if (fd <= 0)
+ return -1;
+
+ if (lseek(fd, offset, SEEK_SET) == -1)
+ return -1;
+
+ size_read = read(fd, buf, length);
+ (void)size_read;
+ return buf_offset;
+}
+
+static int
+munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ module_free(buf_offset);
+ return 0;
+}
+
+static int
+__munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length)
+{
+ return munmap_wrapper(exec_env, buf_offset, length);
+}
+
+static int
+getentropy_wrapper(wasm_exec_env_t exec_env, void *buffer, uint32 length)
+{
+ if (buffer == NULL)
+ return -1;
+#if defined(_DEFAULT_SOURCE) || defined(BH_PLATFORM_LINUX_SGX)
+ return getentropy(buffer, length);
+#else
+ return syscall(SYS_getrandom, buffer, length, 0);
+#endif
+}
+
+static int
+setjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf)
+{
+ os_printf("setjmp() called\n");
+ return 0;
+}
+
+static void
+longjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf, int val)
+{
+ os_printf("longjmp() called\n");
+}
+
+#if !defined(BH_PLATFORM_LINUX_SGX)
+static FILE *file_list[32] = { 0 };
+
+static int
+get_free_file_slot()
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(file_list) / sizeof(FILE *); i++) {
+ if (file_list[i] == NULL)
+ return (int)i;
+ }
+ return -1;
+}
+
+static int
+fopen_wrapper(wasm_exec_env_t exec_env, const char *pathname, const char *mode)
+{
+ FILE *file;
+ int file_id;
+
+ if (pathname == NULL || mode == NULL)
+ return 0;
+
+ if ((file_id = get_free_file_slot()) == -1)
+ return 0;
+
+ file = fopen(pathname, mode);
+ if (!file)
+ return 0;
+
+ file_list[file_id] = file;
+ return file_id + 1;
+}
+
+static uint32
+fread_wrapper(wasm_exec_env_t exec_env, void *ptr, uint32 size, uint32 nmemb,
+ int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
+ return 0;
+ }
+ if ((file = file_list[file_id]) == NULL) {
+ return 0;
+ }
+ return (uint32)fread(ptr, size, nmemb, file);
+}
+
+static int
+fseeko_wrapper(wasm_exec_env_t exec_env, int file_id, int64 offset, int whence)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
+ return -1;
+ }
+ if ((file = file_list[file_id]) == NULL) {
+ return -1;
+ }
+ return (uint32)fseek(file, offset, whence);
+}
+
+static uint32
+emcc_fwrite_wrapper(wasm_exec_env_t exec_env, const void *ptr, uint32 size,
+ uint32 nmemb, int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
+ return 0;
+ }
+ if ((file = file_list[file_id]) == NULL) {
+ return 0;
+ }
+ return (uint32)fwrite(ptr, size, nmemb, file);
+}
+
+static int
+feof_wrapper(wasm_exec_env_t exec_env, int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *))
+ return 1;
+ if ((file = file_list[file_id]) == NULL)
+ return 1;
+ return feof(file);
+}
+
+static int
+fclose_wrapper(wasm_exec_env_t exec_env, int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *))
+ return -1;
+ if ((file = file_list[file_id]) == NULL)
+ return -1;
+ file_list[file_id] = NULL;
+ return fclose(file);
+}
+
+static int
+__sys_mkdir_wrapper(wasm_exec_env_t exec_env, const char *pathname, int mode)
+{
+ if (!pathname)
+ return -1;
+ return mkdir(pathname, mode);
+}
+
+static int
+__sys_rmdir_wrapper(wasm_exec_env_t exec_env, const char *pathname)
+{
+ if (!pathname)
+ return -1;
+ return rmdir(pathname);
+}
+
+static int
+__sys_unlink_wrapper(wasm_exec_env_t exec_env, const char *pathname)
+{
+ if (!pathname)
+ return -1;
+ return unlink(pathname);
+}
+
+static uint32
+__sys_getcwd_wrapper(wasm_exec_env_t exec_env, char *buf, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char *ret;
+
+ if (!buf)
+ return -1;
+
+ ret = getcwd(buf, size);
+ return ret ? addr_native_to_app(ret) : 0;
+}
+
+#include <sys/utsname.h>
+
+struct utsname_app {
+ char sysname[64];
+ char nodename[64];
+ char release[64];
+ char version[64];
+ char machine[64];
+ char domainname[64];
+};
+
+static int
+__sys_uname_wrapper(wasm_exec_env_t exec_env, struct utsname_app *uname_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ struct utsname uname_native = { 0 };
+ uint32 length;
+
+ if (!validate_native_addr(uname_app, sizeof(struct utsname_app)))
+ return -1;
+
+ if (uname(&uname_native) != 0) {
+ return -1;
+ }
+
+ memset(uname_app, 0, sizeof(struct utsname_app));
+
+ length = strlen(uname_native.sysname);
+ if (length > sizeof(uname_app->sysname) - 1)
+ length = sizeof(uname_app->sysname) - 1;
+ bh_memcpy_s(uname_app->sysname, sizeof(uname_app->sysname),
+ uname_native.sysname, length);
+
+ length = strlen(uname_native.nodename);
+ if (length > sizeof(uname_app->nodename) - 1)
+ length = sizeof(uname_app->nodename) - 1;
+ bh_memcpy_s(uname_app->nodename, sizeof(uname_app->nodename),
+ uname_native.nodename, length);
+
+ length = strlen(uname_native.release);
+ if (length > sizeof(uname_app->release) - 1)
+ length = sizeof(uname_app->release) - 1;
+ bh_memcpy_s(uname_app->release, sizeof(uname_app->release),
+ uname_native.release, length);
+
+ length = strlen(uname_native.version);
+ if (length > sizeof(uname_app->version) - 1)
+ length = sizeof(uname_app->version) - 1;
+ bh_memcpy_s(uname_app->version, sizeof(uname_app->version),
+ uname_native.version, length);
+
+#ifdef _GNU_SOURCE
+ length = strlen(uname_native.domainname);
+ if (length > sizeof(uname_app->domainname) - 1)
+ length = sizeof(uname_app->domainname) - 1;
+ bh_memcpy_s(uname_app->domainname, sizeof(uname_app->domainname),
+ uname_native.domainname, length);
+#endif
+
+ return 0;
+}
+
+static void
+emscripten_notify_memory_growth_wrapper(wasm_exec_env_t exec_env, int i)
+{
+ (void)i;
+}
+
+static void
+emscripten_thread_sleep_wrapper(wasm_exec_env_t exec_env, double timeout_ms)
+{
+ uint64 ms = (uint64)timeout_ms;
+ uint64 sec = ms / 1000, us = (ms % 1000) * 1000;
+
+ if (sec > 0)
+ sleep(sec);
+ if (us > 0)
+ usleep(us);
+}
+
+#endif /* end of BH_PLATFORM_LINUX_SGX */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format off */
+
+static NativeSymbol native_symbols_libc_emcc[] = {
+ REG_NATIVE_FUNC(invoke_viiii, "(iiiii)"),
+ REG_NATIVE_FUNC(invoke_viii, "(iiii)"),
+ REG_NATIVE_FUNC(invoke_vii, "(iii)"),
+ REG_NATIVE_FUNC(invoke_vi, "(ii)"),
+ REG_NATIVE_FUNC(invoke_iii, "(iii)i"),
+ REG_NATIVE_FUNC(invoke_ii, "(ii)i"),
+ REG_NATIVE_FUNC(open, "($ii)i"),
+ REG_NATIVE_FUNC(__sys_read, "(i*~)i"),
+ REG_NATIVE_FUNC(__sys_stat64, "($*)i"),
+ REG_NATIVE_FUNC(__sys_fstat64, "(i*)i"),
+ REG_NATIVE_FUNC(mmap, "(*iiiiI)i"),
+ REG_NATIVE_FUNC(munmap, "(ii)i"),
+ REG_NATIVE_FUNC(__munmap, "(ii)i"),
+ REG_NATIVE_FUNC(getentropy, "(*~)i"),
+ REG_NATIVE_FUNC(setjmp, "(*)i"),
+ REG_NATIVE_FUNC(longjmp, "(*i)"),
+#if !defined(BH_PLATFORM_LINUX_SGX)
+ REG_NATIVE_FUNC(fopen, "($$)i"),
+ REG_NATIVE_FUNC(fread, "(*iii)i"),
+ REG_NATIVE_FUNC(fseeko, "(iIi)i"),
+ REG_NATIVE_FUNC(emcc_fwrite, "(*iii)i"),
+ REG_NATIVE_FUNC(feof, "(i)i"),
+ REG_NATIVE_FUNC(fclose, "(i)i"),
+ REG_NATIVE_FUNC(__sys_mkdir, "($i)i"),
+ REG_NATIVE_FUNC(__sys_rmdir, "($)i"),
+ REG_NATIVE_FUNC(__sys_unlink, "($)i"),
+ REG_NATIVE_FUNC(__sys_getcwd, "(*~)i"),
+ REG_NATIVE_FUNC(__sys_uname, "(*)i"),
+ REG_NATIVE_FUNC(emscripten_notify_memory_growth, "(i)"),
+ REG_NATIVE_FUNC(emscripten_thread_sleep, "(F)"),
+#endif /* end of BH_PLATFORM_LINUX_SGX */
+};
+
+uint32
+get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis)
+{
+ *p_libc_emcc_apis = native_symbols_libc_emcc;
+ return sizeof(native_symbols_libc_emcc) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV
new file mode 100644
index 000000000..eb126dab3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV
@@ -0,0 +1,66 @@
+libuv is licensed for use as follows:
+
+====
+Copyright (c) 2015-present libuv project 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.
+====
+
+This license applies to parts of libuv originating from the
+https://github.com/joyent/libuv repository:
+
+====
+
+Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+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.
+
+====
+
+This license applies to all parts of libuv that are not externally
+maintained libraries.
+
+The externally maintained libraries used by libuv are:
+
+ - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
+
+ - inet_pton and inet_ntop implementations, contained in src/inet.c, are
+ copyright the Internet Systems Consortium, Inc., and licensed under the ISC
+ license.
+
+ - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
+ clause BSD license.
+
+ - pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
+ Three clause BSD license.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI
new file mode 100644
index 000000000..dfb8546af
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Colin Ihrig and 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.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake
new file mode 100644
index 000000000..e0c8afa21
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake
@@ -0,0 +1,44 @@
+# 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})
+
+set (LIBUV_VERSION v1.44.2)
+
+add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1)
+
+include(FetchContent)
+
+## libuv
+FetchContent_Declare(
+ libuv
+ GIT_REPOSITORY https://github.com/libuv/libuv.git
+ GIT_TAG ${LIBUV_VERSION}
+)
+FetchContent_GetProperties(libuv)
+if (NOT libuv_POPULATED)
+ message("-- Fetching libuv ..")
+ FetchContent_Populate(libuv)
+ include_directories("${libuv_SOURCE_DIR}/include")
+ add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL)
+ set (UV_A_LIBS uv_a)
+ set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1)
+endif()
+
+## uvwasi
+FetchContent_Declare(
+ uvwasi
+ GIT_REPOSITORY https://github.com/nodejs/uvwasi.git
+ GIT_TAG main
+)
+FetchContent_GetProperties(uvwasi)
+if (NOT uvwasi_POPULATED)
+ message("-- Fetching uvwasi ..")
+ FetchContent_Populate(uvwasi)
+ include_directories("${uvwasi_SOURCE_DIR}/include")
+ add_subdirectory(${uvwasi_SOURCE_DIR} ${uvwasi_BINARY_DIR} EXCLUDE_FROM_ALL)
+endif()
+
+file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c ${uvwasi_SOURCE_DIR}/src/*.c)
+
+set (LIBC_WASI_SOURCE ${source_all})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c
new file mode 100644
index 000000000..504ff7f93
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c
@@ -0,0 +1,1150 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "uvwasi.h"
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+/* clang-format off */
+#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)
+
+#define validate_native_addr(addr, size) \
+ wasm_runtime_validate_native_addr(module_inst, addr, size)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+
+#define module_malloc(size, p_native_addr) \
+ wasm_runtime_module_malloc(module_inst, size, p_native_addr)
+
+#define module_free(offset) \
+ wasm_runtime_module_free(module_inst, offset)
+/* clang-format on */
+
+#define wasi_errno_t uvwasi_errno_t
+#define wasi_fd_t uvwasi_fd_t
+#define wasi_clockid_t uvwasi_clockid_t
+#define wasi_timestamp_t uvwasi_timestamp_t
+#define wasi_filesize_t uvwasi_filesize_t
+#define wasi_prestat_app_t uvwasi_prestat_app_t
+#define wasi_filedelta_t uvwasi_filedelta_t
+#define wasi_whence_t uvwasi_whence_t
+#define wasi_fdflags_t uvwasi_fdflags_t
+#define wasi_rights_t uvwasi_rights_t
+#define wasi_advice_t uvwasi_advice_t
+#define wasi_lookupflags_t uvwasi_lookupflags_t
+#define wasi_preopentype_t uvwasi_preopentype_t
+#define wasi_fdstat_t uvwasi_fdstat_t
+#define wasi_oflags_t uvwasi_oflags_t
+#define wasi_dircookie_t uvwasi_dircookie_t
+#define wasi_filestat_t uvwasi_filestat_t
+#define wasi_fstflags_t uvwasi_fstflags_t
+#define wasi_subscription_t uvwasi_subscription_t
+#define wasi_event_t uvwasi_event_t
+#define wasi_exitcode_t uvwasi_exitcode_t
+#define wasi_signal_t uvwasi_signal_t
+#define wasi_riflags_t uvwasi_riflags_t
+#define wasi_roflags_t uvwasi_roflags_t
+#define wasi_siflags_t uvwasi_siflags_t
+#define wasi_sdflags_t uvwasi_sdflags_t
+#define wasi_iovec_t uvwasi_iovec_t
+#define wasi_ciovec_t uvwasi_ciovec_t
+
+typedef struct wasi_prestat_app {
+ wasi_preopentype_t pr_type;
+ uint32 pr_name_len;
+} wasi_prestat_app_t;
+
+typedef struct iovec_app {
+ uint32 buf_offset;
+ uint32 buf_len;
+} iovec_app_t;
+
+typedef struct WASIContext {
+ uvwasi_t uvwasi;
+ uint32_t exit_code;
+} WASIContext;
+
+void *
+wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
+
+static uvwasi_t *
+get_wasi_ctx(wasm_module_inst_t module_inst)
+{
+ WASIContext *ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ if (ctx == NULL) {
+ return NULL;
+ }
+ return &ctx->uvwasi;
+}
+
+static wasi_errno_t
+wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t argc, argv_buf_size, i;
+ char **argv;
+ uint64 total_size;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_args_sizes_get(uvwasi, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ total_size = sizeof(int32) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(argv_offsets, (uint32)total_size)
+ || argv_buf_size >= UINT32_MAX
+ || !validate_native_addr(argv_buf, (uint32)argv_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !(argv = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_args_get(uvwasi, argv, argv_buf);
+ if (err) {
+ wasm_runtime_free(argv);
+ return err;
+ }
+
+ for (i = 0; i < argc; i++)
+ argv_offsets[i] = addr_native_to_app(argv[i]);
+
+ wasm_runtime_free(argv);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app,
+ uint32 *argv_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t argc, argv_buf_size;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(argc_app, sizeof(uint32))
+ || !validate_native_addr(argv_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_args_sizes_get(uvwasi, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ *argc_app = (uint32)argc;
+ *argv_buf_size_app = (uint32)argv_buf_size;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_clock_res_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id,
+ wasi_timestamp_t *resolution)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_clock_res_get(uvwasi, clock_id, resolution);
+}
+
+static wasi_errno_t
+wasi_clock_time_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id,
+ wasi_timestamp_t precision, wasi_timestamp_t *time)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!validate_native_addr(time, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_clock_time_get(uvwasi, clock_id, precision, time);
+}
+
+static wasi_errno_t
+wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets,
+ char *environ_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t environ_count, environ_buf_size, i;
+ uint64 total_size;
+ char **environs;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_environ_sizes_get(uvwasi, &environ_count, &environ_buf_size);
+ if (err)
+ return err;
+
+ if (environ_count == 0)
+ return 0;
+
+ total_size = sizeof(int32) * ((uint64)environ_count + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(environ_offsets, (uint32)total_size)
+ || environ_buf_size >= UINT32_MAX
+ || !validate_native_addr(environ_buf, (uint32)environ_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * (((uint64)environ_count + 1));
+
+ if (total_size >= UINT32_MAX
+ || !(environs = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_environ_get(uvwasi, environs, environ_buf);
+ if (err) {
+ wasm_runtime_free(environs);
+ return err;
+ }
+
+ for (i = 0; i < environ_count; i++)
+ environ_offsets[i] = addr_native_to_app(environs[i]);
+
+ wasm_runtime_free(environs);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app,
+ uint32 *environ_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t environ_count, environ_buf_size;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(environ_count_app, sizeof(uint32))
+ || !validate_native_addr(environ_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_environ_sizes_get(uvwasi, &environ_count, &environ_buf_size);
+ if (err)
+ return err;
+
+ *environ_count_app = (uint32)environ_count;
+ *environ_buf_size_app = (uint32)environ_buf_size;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_prestat_app_t *prestat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_prestat_t prestat;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_fd_prestat_get(uvwasi, fd, &prestat);
+ if (err)
+ return err;
+
+ prestat_app->pr_type = prestat.pr_type;
+ prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_prestat_dir_name(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_close(uvwasi, fd);
+}
+
+static wasi_errno_t
+wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_datasync(uvwasi, fd);
+}
+
+static wasi_errno_t
+wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app,
+ uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr(iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = uvwasi_fd_pread(uvwasi, fd, iovec_begin, iovs_len, offset, &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ wasi_filesize_t offset, uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+ err =
+ uvwasi_fd_pwrite(uvwasi, fd, ciovec_begin, iovs_len, offset, &nwritten);
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = uvwasi_fd_read(uvwasi, fd, iovec_begin, iovs_len, &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_renumber(uvwasi, from, to);
+}
+
+static wasi_errno_t
+wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset,
+ wasi_whence_t whence, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_seek(uvwasi, fd, offset, whence, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_tell(uvwasi, fd, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_fdstat_t *fdstat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_fdstat_t fdstat;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_fd_fdstat_get(uvwasi, fd, &fdstat);
+ if (err)
+ return err;
+
+ memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t));
+ return 0;
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_fdstat_set_flags(uvwasi, fd, flags);
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_fdstat_set_rights(uvwasi, fd, fs_rights_base,
+ fs_rights_inheriting);
+}
+
+static wasi_errno_t
+wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_sync(uvwasi, fd);
+}
+
+static wasi_errno_t
+wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+#ifndef BH_VPRINTF
+ err = uvwasi_fd_write(uvwasi, fd, ciovec_begin, iovs_len, &nwritten);
+#else
+ /* redirect stdout/stderr output to BH_VPRINTF function */
+ if (fd == 1 || fd == 2) {
+ int i;
+ const struct iovec *iov1 = (const struct iovec *)ciovec_begin;
+
+ nwritten = 0;
+ for (i = 0; i < (int)iovs_len; i++, iov1++) {
+ if (iov1->iov_len > 0 && iov1->iov_base) {
+ char format[16];
+
+ /* make up format string "%.ns" */
+ snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len);
+ nwritten += (uvwasi_size_t)os_printf(format, iov1->iov_base);
+ }
+ }
+ err = 0;
+ }
+ else {
+ err = uvwasi_fd_write(uvwasi, fd, ciovec_begin, iovs_len, &nwritten);
+ }
+#endif /* end of BH_VPRINTF */
+
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_advise(uvwasi, fd, offset, len, advice);
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_allocate(uvwasi, fd, offset, len);
+}
+
+static wasi_errno_t
+wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_create_directory(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ wasi_lookupflags_t old_flags, const char *old_path,
+ uint32 old_path_len, wasi_fd_t new_fd, const char *new_path,
+ uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_link(uvwasi, old_fd, old_flags, old_path, old_path_len,
+ new_fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd,
+ wasi_lookupflags_t dirflags, const char *path, uint32 path_len,
+ wasi_oflags_t oflags, wasi_rights_t fs_rights_base,
+ wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags,
+ wasi_fd_t *fd_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_fd_t fd = (wasi_fd_t)-1; /* set fd_app -1 if path open failed */
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fd_app, sizeof(wasi_fd_t)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_path_open(uvwasi, dirfd, dirflags, path, path_len, oflags,
+ fs_rights_base, fs_rights_inheriting, fs_flags, &fd);
+
+ *fd_app = fd;
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf,
+ uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t bufused;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_fd_readdir(uvwasi, fd, buf, buf_len, cookie, &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len, char *buf, uint32 buf_len,
+ uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t bufused;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_path_readlink(uvwasi, fd, path, path_len, buf, buf_len,
+ &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ const char *old_path, uint32 old_path_len, wasi_fd_t new_fd,
+ const char *new_path, uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_rename(uvwasi, old_fd, old_path, old_path_len, new_fd,
+ new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_filestat_get(uvwasi, fd, filestat);
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_filestat_set_times(uvwasi, fd, st_atim, st_mtim, fstflags);
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_filestat_set_size(uvwasi, fd, st_size);
+}
+
+static wasi_errno_t
+wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_filestat_get(uvwasi, fd, flags, path, path_len,
+ filestat);
+}
+
+static wasi_errno_t
+wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, 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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_filestat_set_times(uvwasi, fd, flags, path, path_len,
+ st_atim, st_mtim, fstflags);
+}
+
+static wasi_errno_t
+wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path,
+ uint32 old_path_len, wasi_fd_t fd, const char *new_path,
+ uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_symlink(uvwasi, old_path, old_path_len, fd, new_path,
+ new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_unlink_file(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_remove_directory(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
+ wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t nevents;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t))
+ || !validate_native_addr(out, sizeof(wasi_event_t))
+ || !validate_native_addr(nevents_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_poll_oneoff(uvwasi, in, out, nsubscriptions, &nevents);
+ if (err)
+ return err;
+
+ *nevents_app = (uint32)nevents;
+ return 0;
+}
+
+static 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);
+ WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ /* Here throwing exception is just to let wasm app exit,
+ the upper layer should clear the exception and return
+ as normal */
+ wasm_runtime_set_exception(module_inst, "wasi proc exit");
+ wasi_ctx->exit_code = rval;
+}
+
+static wasi_errno_t
+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);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ return uvwasi_random_get(uvwasi, buf, buf_len);
+}
+
+static wasi_errno_t
+wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
+ uint32 ri_data_len, wasi_riflags_t ri_flags,
+ uint32 *ro_datalen_app, wasi_roflags_t *ro_flags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ uvwasi_size_t ro_datalen;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)ri_data_len;
+ if (!validate_native_addr(ro_datalen_app, (uint32)sizeof(uint32))
+ || !validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr(ri_data, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+ for (i = 0; i < ri_data_len; i++, ri_data++, iovec++) {
+ if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset);
+ iovec->buf_len = ri_data->buf_len;
+ }
+
+ err = uvwasi_sock_recv(uvwasi, sock, iovec_begin, ri_data_len, ri_flags,
+ &ro_datalen, ro_flags);
+ if (err)
+ goto fail;
+
+ *(uint32 *)ro_datalen_app = (uint32)ro_datalen;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ wasi_siflags_t si_flags, uint32 *so_datalen_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ uvwasi_size_t so_datalen;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)si_data_len;
+ if (!validate_native_addr(so_datalen_app, sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)si_data, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+ for (i = 0; i < si_data_len; i++, si_data++, ciovec++) {
+ if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset);
+ ciovec->buf_len = si_data->buf_len;
+ }
+
+ err = uvwasi_sock_send(uvwasi, sock, ciovec_begin, si_data_len, si_flags,
+ &so_datalen);
+ if (err)
+ goto fail;
+
+ *so_datalen_app = (uint32)so_datalen;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+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);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_sock_shutdown(uvwasi, sock, how);
+}
+
+static wasi_errno_t
+wasi_sched_yield(wasm_exec_env_t exec_env)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ return uvwasi_sched_yield(uvwasi);
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, wasi_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_libc_wasi[] = {
+ REG_NATIVE_FUNC(args_get, "(**)i"),
+ REG_NATIVE_FUNC(args_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(clock_res_get, "(i*)i"),
+ REG_NATIVE_FUNC(clock_time_get, "(iI*)i"),
+ REG_NATIVE_FUNC(environ_get, "(**)i"),
+ REG_NATIVE_FUNC(environ_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(fd_prestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_prestat_dir_name, "(i*~)i"),
+ REG_NATIVE_FUNC(fd_close, "(i)i"),
+ REG_NATIVE_FUNC(fd_datasync, "(i)i"),
+ REG_NATIVE_FUNC(fd_pread, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_pwrite, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_read, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_renumber, "(ii)i"),
+ REG_NATIVE_FUNC(fd_seek, "(iIi*)i"),
+ REG_NATIVE_FUNC(fd_tell, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_flags, "(ii)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_rights, "(iII)i"),
+ REG_NATIVE_FUNC(fd_sync, "(i)i"),
+ REG_NATIVE_FUNC(fd_write, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_advise, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_allocate, "(iII)i"),
+ REG_NATIVE_FUNC(path_create_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(path_link, "(ii*~i*~)i"),
+ REG_NATIVE_FUNC(path_open, "(ii*~iIIi*)i"),
+ REG_NATIVE_FUNC(fd_readdir, "(i*~I*)i"),
+ REG_NATIVE_FUNC(path_readlink, "(i*~*~*)i"),
+ REG_NATIVE_FUNC(path_rename, "(i*~i*~)i"),
+ REG_NATIVE_FUNC(fd_filestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_times, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_size, "(iI)i"),
+ REG_NATIVE_FUNC(path_filestat_get, "(ii*~*)i"),
+ REG_NATIVE_FUNC(path_filestat_set_times, "(ii*~IIi)i"),
+ REG_NATIVE_FUNC(path_symlink, "(*~i*~)i"),
+ REG_NATIVE_FUNC(path_unlink_file, "(i*~)i"),
+ REG_NATIVE_FUNC(path_remove_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(poll_oneoff, "(**i*)i"),
+ REG_NATIVE_FUNC(proc_exit, "(i)"),
+ REG_NATIVE_FUNC(proc_raise, "(i)i"),
+ REG_NATIVE_FUNC(random_get, "(*~)i"),
+ REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
+ REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
+ REG_NATIVE_FUNC(sched_yield, "()i"),
+};
+
+uint32
+get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+ *p_libc_wasi_apis = native_symbols_libc_wasi;
+ return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript
new file mode 100644
index 000000000..6ed3799e0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import os
+
+cwd = GetCurrentDir()
+
+src = Split('''
+''')
+
+CPPPATH = [cwd,
+ cwd+'/sandboxed-system-primitives/include',
+ cwd+'/sandboxed-system-primitives/src']
+
+def addSrcFiles(arr, path):
+ for f in os.listdir(path):
+ fpath = os.path.join(path, f);
+ if os.path.isfile(fpath):
+ ext = os.path.splitext(fpath)[-1]
+ if ext == '.c' or ext == '.cpp':
+ arr += [fpath]
+ elif os.path.isdir(fpath):
+ addSrcFiles(arr, fpath)
+
+
+addSrcFiles(src, cwd)
+
+group = DefineGroup('iwasm_libc_wasi', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake
new file mode 100644
index 000000000..d72c42a06
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
new file mode 100644
index 000000000..afb11925a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
@@ -0,0 +1,2329 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "libc_wasi_wrapper.h"
+#include "bh_platform.h"
+#include "wasm_export.h"
+#include "wasm_runtime_common.h"
+
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../../../thread-mgr/thread_manager.h"
+#endif
+
+void
+wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
+
+/* clang-format off */
+#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)
+
+#define validate_app_addr(offset, size) \
+ wasm_runtime_validate_app_addr(module_inst, offset, size)
+
+#define validate_native_addr(addr, size) \
+ wasm_runtime_validate_native_addr(module_inst, addr, size)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+
+#define module_malloc(size, p_native_addr) \
+ wasm_runtime_module_malloc(module_inst, size, p_native_addr)
+
+#define module_free(offset) \
+ wasm_runtime_module_free(module_inst, offset)
+/* clang-format on */
+
+typedef struct wasi_prestat_app {
+ wasi_preopentype_t pr_type;
+ uint32 pr_name_len;
+} wasi_prestat_app_t;
+
+typedef struct iovec_app {
+ uint32 buf_offset;
+ uint32 buf_len;
+} iovec_app_t;
+
+typedef struct WASIContext *wasi_ctx_t;
+
+wasi_ctx_t
+wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
+
+static inline uint64_t
+min_uint64(uint64_t a, uint64_t b)
+{
+ return a > b ? b : a;
+}
+
+static inline uint32_t
+min_uint32(uint32_t a, uint32_t b)
+{
+ return a > b ? b : a;
+}
+
+static inline struct fd_table *
+wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->curfds;
+}
+
+static inline struct argv_environ_values *
+wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->argv_environ;
+}
+
+static inline struct fd_prestats *
+wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->prestats;
+}
+
+static inline struct addr_pool *
+wasi_ctx_get_addr_pool(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->addr_pool;
+}
+
+static inline char **
+wasi_ctx_get_ns_lookup_list(wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->ns_lookup_list;
+}
+
+static wasi_errno_t
+wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ =
+ wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
+ size_t argc, argv_buf_size, i;
+ char **argv;
+ uint64 total_size;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ total_size = sizeof(int32) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(argv_offsets, (uint32)total_size)
+ || argv_buf_size >= UINT32_MAX
+ || !validate_native_addr(argv_buf, (uint32)argv_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !(argv = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_args_get(argv_environ, argv, argv_buf);
+ if (err) {
+ wasm_runtime_free(argv);
+ return err;
+ }
+
+ for (i = 0; i < argc; i++)
+ argv_offsets[i] = addr_native_to_app(argv[i]);
+
+ wasm_runtime_free(argv);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app,
+ uint32 *argv_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ;
+ size_t argc, argv_buf_size;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(argc_app, sizeof(uint32))
+ || !validate_native_addr(argv_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ argv_environ = wasi_ctx->argv_environ;
+
+ err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ *argc_app = (uint32)argc;
+ *argv_buf_size_app = (uint32)argv_buf_size;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_clock_res_get(wasm_exec_env_t exec_env,
+ wasi_clockid_t clock_id, /* uint32 clock_id */
+ wasi_timestamp_t *resolution /* uint64 *resolution */)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_clock_res_get(clock_id, resolution);
+}
+
+static wasi_errno_t
+wasi_clock_time_get(wasm_exec_env_t exec_env,
+ wasi_clockid_t clock_id, /* uint32 clock_id */
+ wasi_timestamp_t precision, /* uint64 precision */
+ wasi_timestamp_t *time /* uint64 *time */)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (!validate_native_addr(time, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_clock_time_get(clock_id, precision, time);
+}
+
+static wasi_errno_t
+wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets,
+ char *environ_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ =
+ wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
+ size_t environ_count, environ_buf_size, i;
+ uint64 total_size;
+ char **environs;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count,
+ &environ_buf_size);
+ if (err)
+ return err;
+
+ total_size = sizeof(int32) * ((uint64)environ_count + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(environ_offsets, (uint32)total_size)
+ || environ_buf_size >= UINT32_MAX
+ || !validate_native_addr(environ_buf, (uint32)environ_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * (((uint64)environ_count + 1));
+
+ if (total_size >= UINT32_MAX
+ || !(environs = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_environ_get(argv_environ, environs, environ_buf);
+ if (err) {
+ wasm_runtime_free(environs);
+ return err;
+ }
+
+ for (i = 0; i < environ_count; i++)
+ environ_offsets[i] = addr_native_to_app(environs[i]);
+
+ wasm_runtime_free(environs);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app,
+ uint32 *environ_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ =
+ wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
+ size_t environ_count, environ_buf_size;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(environ_count_app, sizeof(uint32))
+ || !validate_native_addr(environ_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count,
+ &environ_buf_size);
+ if (err)
+ return err;
+
+ *environ_count_app = (uint32)environ_count;
+ *environ_buf_size_app = (uint32)environ_buf_size;
+
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_prestat_app_t *prestat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+ wasi_prestat_t prestat;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_fd_prestat_get(prestats, fd, &prestat);
+ if (err)
+ return err;
+
+ prestat_app->pr_type = prestat.pr_type;
+ prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_prestat_dir_name(prestats, fd, path, path_len);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_close(curfds, prestats, fd);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_datasync(curfds, fd);
+}
+
+static wasi_errno_t
+wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app,
+ uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr(iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset,
+ &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ wasi_filesize_t offset, uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset,
+ &nwritten);
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_renumber(curfds, prestats, from, to);
+}
+
+static wasi_errno_t
+wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset,
+ wasi_whence_t whence, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_tell(curfds, fd, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_fdstat_t *fdstat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_fdstat_t fdstat;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat);
+ if (err)
+ return err;
+
+ memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t));
+ return 0;
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base,
+ fs_rights_inheriting);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_sync(curfds, fd);
+}
+
+static wasi_errno_t
+wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten);
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_allocate(curfds, fd, offset, len);
+}
+
+static wasi_errno_t
+wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ wasi_lookupflags_t old_flags, const char *old_path,
+ uint32 old_path_len, wasi_fd_t new_fd, const char *new_path,
+ 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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path,
+ old_path_len, new_fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd,
+ wasi_lookupflags_t dirflags, const char *path, uint32 path_len,
+ wasi_oflags_t oflags, wasi_rights_t fs_rights_base,
+ wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags,
+ wasi_fd_t *fd_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_fd_t fd = (wasi_fd_t)-1; /* set fd_app -1 if path open failed */
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fd_app, sizeof(wasi_fd_t)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len,
+ oflags, fs_rights_base, fs_rights_inheriting,
+ fs_flags, &fd);
+
+ *fd_app = fd;
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf,
+ uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ size_t bufused;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len, char *buf, uint32 buf_len,
+ uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ size_t bufused;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len,
+ &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ const char *old_path, uint32 old_path_len, wasi_fd_t new_fd,
+ const char *new_path, 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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len,
+ new_fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim,
+ fstflags);
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size);
+}
+
+static wasi_errno_t
+wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len,
+ filestat);
+}
+
+static wasi_errno_t
+wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, 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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_filestat_set_times(
+ curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags);
+}
+
+static wasi_errno_t
+wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path,
+ uint32 old_path_len, wasi_fd_t fd, const char *new_path,
+ 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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len,
+ fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len);
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+static __wasi_timestamp_t
+get_timeout_for_poll_oneoff(const wasi_subscription_t *in,
+ uint32 nsubscriptions)
+{
+ __wasi_timestamp_t timeout = (__wasi_timestamp_t)-1;
+ uint32 i = 0;
+
+ for (i = 0; i < nsubscriptions; ++i) {
+ const __wasi_subscription_t *s = &in[i];
+ if (s->u.type == __WASI_EVENTTYPE_CLOCK
+ && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) {
+ timeout = min_uint64(timeout, s->u.u.clock.timeout);
+ }
+ }
+ return timeout;
+}
+
+static void
+update_clock_subscription_data(wasi_subscription_t *in, uint32 nsubscriptions,
+ const wasi_timestamp_t new_timeout)
+{
+ uint32 i = 0;
+ for (i = 0; i < nsubscriptions; ++i) {
+ __wasi_subscription_t *s = &in[i];
+ if (s->u.type == __WASI_EVENTTYPE_CLOCK) {
+ s->u.u.clock.timeout = new_timeout;
+ }
+ }
+}
+
+static wasi_errno_t
+execute_interruptible_poll_oneoff(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions,
+ size_t *nevents, wasm_exec_env_t exec_env)
+{
+ if (nsubscriptions == 0) {
+ *nevents = 0;
+ return __WASI_ESUCCESS;
+ }
+
+ wasi_errno_t err;
+ __wasi_timestamp_t elapsed = 0;
+ bool all_outs_are_type_clock;
+ uint32 i;
+
+ const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff(
+ in, nsubscriptions),
+ time_quant = 1e9;
+ const uint64 size_to_copy =
+ nsubscriptions * (uint64)sizeof(wasi_subscription_t);
+ __wasi_subscription_t *in_copy = NULL;
+
+ if (size_to_copy >= UINT32_MAX
+ || !(in_copy = (__wasi_subscription_t *)wasm_runtime_malloc(
+ (uint32)size_to_copy))) {
+ return __WASI_ENOMEM;
+ }
+
+ bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy);
+
+ while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) {
+ /* update timeout for clock subscription events */
+ update_clock_subscription_data(
+ in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed));
+ err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions,
+ nevents);
+ elapsed += time_quant;
+
+ if (err) {
+ wasm_runtime_free(in_copy);
+ return err;
+ }
+
+ if (wasm_cluster_is_thread_terminated(exec_env)) {
+ wasm_runtime_free(in_copy);
+ return EINTR;
+ }
+ else if (*nevents > 0) {
+ all_outs_are_type_clock = true;
+ for (i = 0; i < *nevents; i++) {
+ if (out[i].type != __WASI_EVENTTYPE_CLOCK) {
+ all_outs_are_type_clock = false;
+ break;
+ }
+ }
+
+ if (!all_outs_are_type_clock) {
+ wasm_runtime_free(in_copy);
+ return __WASI_ESUCCESS;
+ }
+ }
+ }
+
+ wasm_runtime_free(in_copy);
+ return __WASI_ESUCCESS;
+}
+#endif
+
+static wasi_errno_t
+wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
+ wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ size_t nevents = 0;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t))
+ || !validate_native_addr(out, sizeof(wasi_event_t))
+ || !validate_native_addr(nevents_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+#if WASM_ENABLE_THREAD_MGR == 0
+ err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
+#else
+ err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions,
+ &nevents, exec_env);
+#endif
+ if (err)
+ return err;
+
+ *nevents_app = (uint32)nevents;
+ return 0;
+}
+
+static 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);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ /* Here throwing exception is just to let wasm app exit,
+ the upper layer should clear the exception and return
+ as normal */
+ wasm_runtime_set_exception(module_inst, "wasi proc exit");
+ wasi_ctx->exit_code = rval;
+}
+
+static wasi_errno_t
+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);
+
+ return 0;
+}
+
+static wasi_errno_t
+wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
+{
+ return wasmtime_ssp_random_get(buf, buf_len);
+}
+
+static wasi_errno_t
+wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags,
+ wasi_fd_t *fd_new)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_accept(curfds, fd, flags, fd_new);
+}
+
+static wasi_errno_t
+wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(addr, sizeof(__wasi_addr_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_addr_local(curfds, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(addr, sizeof(__wasi_addr_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_addr_remote(curfds, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_addr_resolve(wasm_exec_env_t exec_env, const char *host,
+ const char *service, __wasi_addr_info_hints_t *hints,
+ __wasi_addr_info_t *addr_info,
+ __wasi_size_t addr_info_size,
+ __wasi_size_t *max_info_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+ char **ns_lookup_list = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx);
+
+ return wasi_ssp_sock_addr_resolve(curfds, ns_lookup_list, host, service,
+ hints, addr_info, addr_info_size,
+ max_info_size);
+}
+
+static wasi_errno_t
+wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+ struct addr_pool *addr_pool = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ return __WASI_ENOSYS;
+}
+
+static wasi_errno_t
+wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+ struct addr_pool *addr_pool = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled,
+ int *linger_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool))
+ || !validate_native_addr(linger_s, sizeof(int)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ size_t *size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(size, sizeof(wasi_size_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t *timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(timeout_us, sizeof(uint64_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ size_t *size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(size, sizeof(__wasi_size_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t *timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(timeout_us, sizeof(uint64_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t *time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(time_s, sizeof(uint32_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t *time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(time_s, sizeof(uint32_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool ipv6, bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6,
+ is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(ttl_s, sizeof(uint8_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint8_t *ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(ttl_s, sizeof(uint8_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_listen(curfds, fd, backlog);
+}
+
+static wasi_errno_t
+wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd,
+ wasi_address_family_t af, wasi_sock_type_t socktype,
+ wasi_fd_t *sockfd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd);
+}
+
+static wasi_errno_t
+wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled,
+ int linger_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool ipv6, bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6,
+ is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr,
+ imr_interface);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr,
+ imr_interface);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint8_t ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+allocate_iovec_app_buffer(wasm_module_inst_t module_inst,
+ const iovec_app_t *data, uint32 data_len,
+ uint8 **buf_ptr, uint64 *buf_len)
+{
+ uint64 total_size = 0;
+ uint32 i;
+ uint8 *buf_begin = NULL;
+
+ if (data_len == 0) {
+ return __WASI_EINVAL;
+ }
+
+ total_size = sizeof(iovec_app_t) * (uint64)data_len;
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr((void *)data, (uint32)total_size))
+ return __WASI_EINVAL;
+
+ for (total_size = 0, i = 0; i < data_len; i++, data++) {
+ total_size += data->buf_len;
+ }
+
+ if (total_size == 0) {
+ return __WASI_EINVAL;
+ }
+
+ if (total_size >= UINT32_MAX
+ || !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
+ return __WASI_ENOMEM;
+ }
+
+ *buf_len = total_size;
+ *buf_ptr = buf_begin;
+
+ return __WASI_ESUCCESS;
+}
+
+static wasi_errno_t
+copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
+ uint32 buf_size, iovec_app_t *data, uint32 data_len,
+ uint32 size_to_copy)
+{
+ uint8 *buf = buf_begin;
+ uint32 i;
+ uint32 size_to_copy_into_iovec;
+
+ if (buf_size < size_to_copy) {
+ return __WASI_EINVAL;
+ }
+
+ for (i = 0; i < data_len; data++, i++) {
+ char *native_addr;
+
+ if (!validate_app_addr(data->buf_offset, data->buf_len)) {
+ return __WASI_EINVAL;
+ }
+
+ if (buf >= buf_begin + buf_size
+ || buf + data->buf_len < buf /* integer overflow */
+ || buf + data->buf_len > buf_begin + buf_size
+ || size_to_copy == 0) {
+ break;
+ }
+
+ /**
+ * If our app buffer size is smaller than the amount to be copied,
+ * only copy the amount in the app buffer. Otherwise, we fill the iovec
+ * buffer and reduce size to copy on the next iteration
+ */
+ size_to_copy_into_iovec = min_uint32(data->buf_len, size_to_copy);
+
+ native_addr = (void *)addr_app_to_native(data->buf_offset);
+ bh_memcpy_s(native_addr, size_to_copy_into_iovec, buf,
+ size_to_copy_into_iovec);
+ buf += size_to_copy_into_iovec;
+ size_to_copy -= size_to_copy_into_iovec;
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+static wasi_errno_t
+wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ iovec_app_t *ri_data, uint32 ri_data_len,
+ wasi_riflags_t ri_flags, __wasi_addr_t *src_addr,
+ uint32 *ro_data_len)
+{
+ /**
+ * ri_data_len is the length of a list of iovec_app_t, which head is
+ * ri_data. ro_data_len is the number of bytes received
+ **/
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ uint64 total_size;
+ uint8 *buf_begin = NULL;
+ wasi_errno_t err;
+ size_t recv_bytes = 0;
+
+ if (!wasi_ctx) {
+ return __WASI_EINVAL;
+ }
+
+ if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32)))
+ return __WASI_EINVAL;
+
+ err = allocate_iovec_app_buffer(module_inst, ri_data, ri_data_len,
+ &buf_begin, &total_size);
+ if (err != __WASI_ESUCCESS) {
+ goto fail;
+ }
+
+ memset(buf_begin, 0, total_size);
+
+ *ro_data_len = 0;
+ err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size,
+ ri_flags, src_addr, &recv_bytes);
+ if (err != __WASI_ESUCCESS) {
+ goto fail;
+ }
+ *ro_data_len = (uint32)recv_bytes;
+
+ err = copy_buffer_to_iovec_app(module_inst, buf_begin, (uint32)total_size,
+ ri_data, ri_data_len, (uint32)recv_bytes);
+
+fail:
+ if (buf_begin) {
+ wasm_runtime_free(buf_begin);
+ }
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
+ uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len,
+ wasi_roflags_t *ro_flags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ __wasi_addr_t src_addr;
+ wasi_errno_t error;
+
+ if (!validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t)))
+ return __WASI_EINVAL;
+
+ error = wasi_sock_recv_from(exec_env, sock, ri_data, ri_data_len, ri_flags,
+ &src_addr, ro_data_len);
+ *ro_flags = ri_flags;
+
+ return error;
+}
+
+static wasi_errno_t
+convert_iovec_app_to_buffer(wasm_module_inst_t module_inst,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ uint8 **buf_ptr, uint64 *buf_len)
+{
+ uint32 i;
+ const iovec_app_t *si_data_orig = si_data;
+ uint8 *buf = NULL;
+ wasi_errno_t error;
+
+ error = allocate_iovec_app_buffer(module_inst, si_data, si_data_len,
+ buf_ptr, buf_len);
+ if (error != __WASI_ESUCCESS) {
+ return error;
+ }
+
+ buf = *buf_ptr;
+ si_data = si_data_orig;
+ for (i = 0; i < si_data_len; i++, si_data++) {
+ char *native_addr;
+
+ if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
+ wasm_runtime_free(*buf_ptr);
+ return __WASI_EINVAL;
+ }
+
+ native_addr = (char *)addr_app_to_native(si_data->buf_offset);
+ bh_memcpy_s(buf, si_data->buf_len, native_addr, si_data->buf_len);
+ buf += si_data->buf_len;
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+static wasi_errno_t
+wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ wasi_siflags_t si_flags, uint32 *so_data_len)
+{
+ /**
+ * si_data_len is the length of a list of iovec_app_t, which head is
+ * si_data. so_data_len is the number of bytes sent
+ **/
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ uint64 buf_size = 0;
+ uint8 *buf = NULL;
+ wasi_errno_t err;
+ size_t send_bytes = 0;
+
+ if (!wasi_ctx) {
+ return __WASI_EINVAL;
+ }
+
+ if (!validate_native_addr(so_data_len, sizeof(uint32)))
+ return __WASI_EINVAL;
+
+ err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
+ &buf_size);
+ if (err != __WASI_ESUCCESS)
+ return err;
+
+ *so_data_len = 0;
+ err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes);
+ *so_data_len = (uint32)send_bytes;
+
+ wasm_runtime_free(buf);
+
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr,
+ uint32 *so_data_len)
+{
+ /**
+ * si_data_len is the length of a list of iovec_app_t, which head is
+ * si_data. so_data_len is the number of bytes sent
+ **/
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ uint64 buf_size = 0;
+ uint8 *buf = NULL;
+ wasi_errno_t err;
+ size_t send_bytes = 0;
+ struct addr_pool *addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
+
+ if (!wasi_ctx) {
+ return __WASI_EINVAL;
+ }
+
+ if (!validate_native_addr(so_data_len, sizeof(uint32)))
+ return __WASI_EINVAL;
+
+ err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
+ &buf_size);
+ if (err != __WASI_ESUCCESS)
+ return err;
+
+ *so_data_len = 0;
+ err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size,
+ si_flags, dest_addr, &send_bytes);
+ *so_data_len = (uint32)send_bytes;
+
+ wasm_runtime_free(buf);
+
+ return err;
+}
+
+static wasi_errno_t
+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);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return __WASI_EINVAL;
+
+ return wasmtime_ssp_sock_shutdown(curfds, sock);
+}
+
+static wasi_errno_t
+wasi_sched_yield(wasm_exec_env_t exec_env)
+{
+ return wasmtime_ssp_sched_yield();
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, wasi_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_libc_wasi[] = {
+ REG_NATIVE_FUNC(args_get, "(**)i"),
+ REG_NATIVE_FUNC(args_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(clock_res_get, "(i*)i"),
+ REG_NATIVE_FUNC(clock_time_get, "(iI*)i"),
+ REG_NATIVE_FUNC(environ_get, "(**)i"),
+ REG_NATIVE_FUNC(environ_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(fd_prestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_prestat_dir_name, "(i*~)i"),
+ REG_NATIVE_FUNC(fd_close, "(i)i"),
+ REG_NATIVE_FUNC(fd_datasync, "(i)i"),
+ REG_NATIVE_FUNC(fd_pread, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_pwrite, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_read, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_renumber, "(ii)i"),
+ REG_NATIVE_FUNC(fd_seek, "(iIi*)i"),
+ REG_NATIVE_FUNC(fd_tell, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_flags, "(ii)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_rights, "(iII)i"),
+ REG_NATIVE_FUNC(fd_sync, "(i)i"),
+ REG_NATIVE_FUNC(fd_write, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_advise, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_allocate, "(iII)i"),
+ REG_NATIVE_FUNC(path_create_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(path_link, "(ii*~i*~)i"),
+ REG_NATIVE_FUNC(path_open, "(ii*~iIIi*)i"),
+ REG_NATIVE_FUNC(fd_readdir, "(i*~I*)i"),
+ REG_NATIVE_FUNC(path_readlink, "(i*~*~*)i"),
+ REG_NATIVE_FUNC(path_rename, "(i*~i*~)i"),
+ REG_NATIVE_FUNC(fd_filestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_times, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_size, "(iI)i"),
+ REG_NATIVE_FUNC(path_filestat_get, "(ii*~*)i"),
+ REG_NATIVE_FUNC(path_filestat_set_times, "(ii*~IIi)i"),
+ REG_NATIVE_FUNC(path_symlink, "(*~i*~)i"),
+ REG_NATIVE_FUNC(path_unlink_file, "(i*~)i"),
+ REG_NATIVE_FUNC(path_remove_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(poll_oneoff, "(**i*)i"),
+ REG_NATIVE_FUNC(proc_exit, "(i)"),
+ REG_NATIVE_FUNC(proc_raise, "(i)i"),
+ REG_NATIVE_FUNC(random_get, "(*~)i"),
+ REG_NATIVE_FUNC(sock_accept, "(ii*)i"),
+ REG_NATIVE_FUNC(sock_addr_local, "(i*)i"),
+ REG_NATIVE_FUNC(sock_addr_remote, "(i*)i"),
+ REG_NATIVE_FUNC(sock_addr_resolve, "($$**i*)i"),
+ REG_NATIVE_FUNC(sock_bind, "(i*)i"),
+ REG_NATIVE_FUNC(sock_close, "(i)i"),
+ REG_NATIVE_FUNC(sock_connect, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_broadcast, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_keep_alive, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_linger, "(i**)i"),
+ REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_recv_timeout, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_send_timeout, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_fastopen_connect, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_keep_idle, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_keep_intvl, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_no_delay, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_quick_ack, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_ip_multicast_loop, "(ii*)i"),
+ REG_NATIVE_FUNC(sock_get_ip_multicast_ttl, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_ip_ttl, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_ipv6_only, "(i*)i"),
+ REG_NATIVE_FUNC(sock_listen, "(ii)i"),
+ REG_NATIVE_FUNC(sock_open, "(iii*)i"),
+ REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_recv_from, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
+ REG_NATIVE_FUNC(sock_send_to, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_set_broadcast, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_keep_alive, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_linger, "(iii)i"),
+ REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"),
+ REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_send_timeout, "(iI)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_fastopen_connect, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_keep_idle, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_keep_intvl, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_no_delay, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_quick_ack, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_ip_multicast_loop, "(iii)i"),
+ REG_NATIVE_FUNC(sock_set_ip_multicast_ttl, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_ip_add_membership, "(i*i)i"),
+ REG_NATIVE_FUNC(sock_set_ip_drop_membership, "(i*i)i"),
+ REG_NATIVE_FUNC(sock_set_ip_ttl, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_ipv6_only, "(ii)i"),
+ REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
+ REG_NATIVE_FUNC(sched_yield, "()i"),
+};
+
+uint32
+get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+ *p_libc_wasi_apis = native_symbols_libc_wasi;
+ return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h
new file mode 100644
index 000000000..be509576b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _LIBC_WASI_WRAPPER_H
+#define _LIBC_WASI_WRAPPER_H
+
+#include "wasmtime_ssp.h"
+#include "posix.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef __wasi_address_family_t wasi_address_family_t;
+typedef __wasi_addr_t wasi_addr_t;
+typedef __wasi_advice_t wasi_advice_t;
+typedef __wasi_ciovec_t wasi_ciovec_t;
+typedef __wasi_clockid_t wasi_clockid_t;
+typedef __wasi_dircookie_t wasi_dircookie_t;
+typedef __wasi_errno_t wasi_errno_t;
+typedef __wasi_event_t wasi_event_t;
+typedef __wasi_exitcode_t wasi_exitcode_t;
+typedef __wasi_fdflags_t wasi_fdflags_t;
+typedef __wasi_fdstat_t wasi_fdstat_t;
+typedef __wasi_fd_t wasi_fd_t;
+typedef __wasi_filedelta_t wasi_filedelta_t;
+typedef __wasi_filesize_t wasi_filesize_t;
+typedef __wasi_filestat_t wasi_filestat_t;
+typedef __wasi_filetype_t wasi_filetype_t;
+typedef __wasi_fstflags_t wasi_fstflags_t;
+typedef __wasi_iovec_t wasi_iovec_t;
+typedef __wasi_ip_port_t wasi_ip_port_t;
+typedef __wasi_lookupflags_t wasi_lookupflags_t;
+typedef __wasi_oflags_t wasi_oflags_t;
+typedef __wasi_preopentype_t wasi_preopentype_t;
+typedef __wasi_prestat_t wasi_prestat_t;
+typedef __wasi_riflags_t wasi_riflags_t;
+typedef __wasi_rights_t wasi_rights_t;
+typedef __wasi_roflags_t wasi_roflags_t;
+typedef __wasi_sdflags_t wasi_sdflags_t;
+typedef __wasi_siflags_t wasi_siflags_t;
+typedef __wasi_signal_t wasi_signal_t;
+typedef __wasi_size_t wasi_size_t;
+typedef __wasi_sock_type_t wasi_sock_type_t;
+typedef __wasi_subscription_t wasi_subscription_t;
+typedef __wasi_timestamp_t wasi_timestamp_t;
+typedef __wasi_whence_t wasi_whence_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _LIBC_WASI_WRAPPER_H */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE
new file mode 100644
index 000000000..83386f80a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE
@@ -0,0 +1,7 @@
+Please see the LICENSE file in each top-level directory for the terms applicable to that directory and its relative sub-directories.
+
+The relevant directories and licenses are:
+
+src/ - BSD-2-Clause; see src/LICENSE for details
+include/ - CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
+polyfill/clang/ - MIT; see the header of polyfill/clang/stdatomic.h for details
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
new file mode 100644
index 000000000..feadf2f95
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
@@ -0,0 +1,1508 @@
+/*
+ * Part of the Wasmtime Project, under the Apache License v2.0 with
+ * LLVM Exceptions. See
+ * https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE
+ * for license information.
+ *
+ * This file declares an interface similar to WASI, but augmented to expose
+ * some implementation details such as the curfds arguments that we pass
+ * around to avoid storing them in TLS.
+ */
+
+/**
+ * The defitions of type, macro and structure in this file should be
+ * consistent with those in wasi-libc:
+ * https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/wasi/api.h
+ */
+
+#ifndef WASMTIME_SSP_H
+#define WASMTIME_SSP_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* clang-format off */
+
+#ifdef __cplusplus
+#ifndef _Static_assert
+#define _Static_assert static_assert
+#endif /* _Static_assert */
+
+#ifndef _Alignof
+#define _Alignof alignof
+#endif /* _Alignof */
+
+#ifndef _Noreturn
+#define _Noreturn [[ noreturn ]]
+#endif /* _Noreturn */
+extern "C" {
+#endif
+
+_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout");
+_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout");
+_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
+
+typedef uint32_t __wasi_size_t;
+_Static_assert(_Alignof(__wasi_size_t) == 4, "non-wasi data layout");
+
+typedef uint8_t __wasi_advice_t;
+#define __WASI_ADVICE_NORMAL (0)
+#define __WASI_ADVICE_SEQUENTIAL (1)
+#define __WASI_ADVICE_RANDOM (2)
+#define __WASI_ADVICE_WILLNEED (3)
+#define __WASI_ADVICE_DONTNEED (4)
+#define __WASI_ADVICE_NOREUSE (5)
+
+typedef uint32_t __wasi_clockid_t;
+#define __WASI_CLOCK_REALTIME (0)
+#define __WASI_CLOCK_MONOTONIC (1)
+#define __WASI_CLOCK_PROCESS_CPUTIME_ID (2)
+#define __WASI_CLOCK_THREAD_CPUTIME_ID (3)
+
+typedef uint64_t __wasi_device_t;
+
+typedef uint64_t __wasi_dircookie_t;
+#define __WASI_DIRCOOKIE_START (0)
+
+typedef uint32_t __wasi_dirnamlen_t;
+
+typedef uint16_t __wasi_errno_t;
+#define __WASI_ESUCCESS (0)
+#define __WASI_E2BIG (1)
+#define __WASI_EACCES (2)
+#define __WASI_EADDRINUSE (3)
+#define __WASI_EADDRNOTAVAIL (4)
+#define __WASI_EAFNOSUPPORT (5)
+#define __WASI_EAGAIN (6)
+#define __WASI_EALREADY (7)
+#define __WASI_EBADF (8)
+#define __WASI_EBADMSG (9)
+#define __WASI_EBUSY (10)
+#define __WASI_ECANCELED (11)
+#define __WASI_ECHILD (12)
+#define __WASI_ECONNABORTED (13)
+#define __WASI_ECONNREFUSED (14)
+#define __WASI_ECONNRESET (15)
+#define __WASI_EDEADLK (16)
+#define __WASI_EDESTADDRREQ (17)
+#define __WASI_EDOM (18)
+#define __WASI_EDQUOT (19)
+#define __WASI_EEXIST (20)
+#define __WASI_EFAULT (21)
+#define __WASI_EFBIG (22)
+#define __WASI_EHOSTUNREACH (23)
+#define __WASI_EIDRM (24)
+#define __WASI_EILSEQ (25)
+#define __WASI_EINPROGRESS (26)
+#define __WASI_EINTR (27)
+#define __WASI_EINVAL (28)
+#define __WASI_EIO (29)
+#define __WASI_EISCONN (30)
+#define __WASI_EISDIR (31)
+#define __WASI_ELOOP (32)
+#define __WASI_EMFILE (33)
+#define __WASI_EMLINK (34)
+#define __WASI_EMSGSIZE (35)
+#define __WASI_EMULTIHOP (36)
+#define __WASI_ENAMETOOLONG (37)
+#define __WASI_ENETDOWN (38)
+#define __WASI_ENETRESET (39)
+#define __WASI_ENETUNREACH (40)
+#define __WASI_ENFILE (41)
+#define __WASI_ENOBUFS (42)
+#define __WASI_ENODEV (43)
+#define __WASI_ENOENT (44)
+#define __WASI_ENOEXEC (45)
+#define __WASI_ENOLCK (46)
+#define __WASI_ENOLINK (47)
+#define __WASI_ENOMEM (48)
+#define __WASI_ENOMSG (49)
+#define __WASI_ENOPROTOOPT (50)
+#define __WASI_ENOSPC (51)
+#define __WASI_ENOSYS (52)
+#define __WASI_ENOTCONN (53)
+#define __WASI_ENOTDIR (54)
+#define __WASI_ENOTEMPTY (55)
+#define __WASI_ENOTRECOVERABLE (56)
+#define __WASI_ENOTSOCK (57)
+#define __WASI_ENOTSUP (58)
+#define __WASI_ENOTTY (59)
+#define __WASI_ENXIO (60)
+#define __WASI_EOVERFLOW (61)
+#define __WASI_EOWNERDEAD (62)
+#define __WASI_EPERM (63)
+#define __WASI_EPIPE (64)
+#define __WASI_EPROTO (65)
+#define __WASI_EPROTONOSUPPORT (66)
+#define __WASI_EPROTOTYPE (67)
+#define __WASI_ERANGE (68)
+#define __WASI_EROFS (69)
+#define __WASI_ESPIPE (70)
+#define __WASI_ESRCH (71)
+#define __WASI_ESTALE (72)
+#define __WASI_ETIMEDOUT (73)
+#define __WASI_ETXTBSY (74)
+#define __WASI_EXDEV (75)
+#define __WASI_ENOTCAPABLE (76)
+
+typedef uint16_t __wasi_eventrwflags_t;
+#define __WASI_EVENT_FD_READWRITE_HANGUP (0x0001)
+
+typedef uint8_t __wasi_eventtype_t;
+#define __WASI_EVENTTYPE_CLOCK (0)
+#define __WASI_EVENTTYPE_FD_READ (1)
+#define __WASI_EVENTTYPE_FD_WRITE (2)
+
+typedef uint32_t __wasi_exitcode_t;
+
+typedef uint32_t __wasi_fd_t;
+
+typedef uint16_t __wasi_fdflags_t;
+#define __WASI_FDFLAG_APPEND (0x0001)
+#define __WASI_FDFLAG_DSYNC (0x0002)
+#define __WASI_FDFLAG_NONBLOCK (0x0004)
+#define __WASI_FDFLAG_RSYNC (0x0008)
+#define __WASI_FDFLAG_SYNC (0x0010)
+
+typedef int64_t __wasi_filedelta_t;
+
+typedef uint64_t __wasi_filesize_t;
+
+typedef uint8_t __wasi_filetype_t;
+#define __WASI_FILETYPE_UNKNOWN (0)
+#define __WASI_FILETYPE_BLOCK_DEVICE (1)
+#define __WASI_FILETYPE_CHARACTER_DEVICE (2)
+#define __WASI_FILETYPE_DIRECTORY (3)
+#define __WASI_FILETYPE_REGULAR_FILE (4)
+#define __WASI_FILETYPE_SOCKET_DGRAM (5)
+#define __WASI_FILETYPE_SOCKET_STREAM (6)
+#define __WASI_FILETYPE_SYMBOLIC_LINK (7)
+
+typedef uint16_t __wasi_fstflags_t;
+#define __WASI_FILESTAT_SET_ATIM (0x0001)
+#define __WASI_FILESTAT_SET_ATIM_NOW (0x0002)
+#define __WASI_FILESTAT_SET_MTIM (0x0004)
+#define __WASI_FILESTAT_SET_MTIM_NOW (0x0008)
+
+typedef uint64_t __wasi_inode_t;
+
+typedef uint64_t __wasi_linkcount_t __attribute__((aligned(8)));
+
+typedef uint32_t __wasi_lookupflags_t;
+#define __WASI_LOOKUP_SYMLINK_FOLLOW (0x00000001)
+
+typedef uint16_t __wasi_oflags_t;
+#define __WASI_O_CREAT (0x0001)
+#define __WASI_O_DIRECTORY (0x0002)
+#define __WASI_O_EXCL (0x0004)
+#define __WASI_O_TRUNC (0x0008)
+
+typedef uint16_t __wasi_riflags_t;
+#define __WASI_SOCK_RECV_PEEK (0x0001)
+#define __WASI_SOCK_RECV_WAITALL (0x0002)
+
+typedef uint64_t __wasi_rights_t;
+
+/**
+ * Observe that WASI defines rights in the plural form
+ * TODO: refactor to use RIGHTS instead of RIGHT
+ */
+#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(UINT64_C(1) << 0))
+#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(UINT64_C(1) << 1))
+#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(UINT64_C(1) << 2))
+#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(UINT64_C(1) << 3))
+#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(UINT64_C(1) << 4))
+#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(UINT64_C(1) << 5))
+#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(UINT64_C(1) << 6))
+#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(UINT64_C(1) << 7))
+#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(UINT64_C(1) << 8))
+#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 9))
+#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(UINT64_C(1) << 10))
+#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 11))
+#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(UINT64_C(1) << 12))
+#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(UINT64_C(1) << 13))
+#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(UINT64_C(1) << 14))
+#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(UINT64_C(1) << 15))
+#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 16))
+#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(UINT64_C(1) << 17))
+#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 18))
+#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 19))
+#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 20))
+#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 21))
+#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 22))
+#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 23))
+#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(UINT64_C(1) << 24))
+#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 25))
+#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(UINT64_C(1) << 26))
+#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(UINT64_C(1) << 27))
+#define __WASI_RIGHT_SOCK_CONNECT ((__wasi_rights_t)(UINT64_C(1) << 28))
+#define __WASI_RIGHT_SOCK_LISTEN ((__wasi_rights_t)(UINT64_C(1) << 29))
+#define __WASI_RIGHT_SOCK_BIND ((__wasi_rights_t)(UINT64_C(1) << 30))
+#define __WASI_RIGHT_SOCK_ACCEPT ((__wasi_rights_t)(UINT64_C(1) << 31))
+#define __WASI_RIGHT_SOCK_RECV ((__wasi_rights_t)(UINT64_C(1) << 32))
+#define __WASI_RIGHT_SOCK_SEND ((__wasi_rights_t)(UINT64_C(1) << 33))
+#define __WASI_RIGHT_SOCK_ADDR_LOCAL ((__wasi_rights_t)(UINT64_C(1) << 34))
+#define __WASI_RIGHT_SOCK_ADDR_REMOTE ((__wasi_rights_t)(UINT64_C(1) << 35))
+#define __WASI_RIGHT_SOCK_RECV_FROM ((__wasi_rights_t)(UINT64_C(1) << 36))
+#define __WASI_RIGHT_SOCK_SEND_TO ((__wasi_rights_t)(UINT64_C(1) << 37))
+
+typedef uint16_t __wasi_roflags_t;
+#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001)
+
+typedef uint8_t __wasi_sdflags_t;
+#define __WASI_SHUT_RD (0x01)
+#define __WASI_SHUT_WR (0x02)
+
+typedef uint16_t __wasi_siflags_t;
+
+typedef uint8_t __wasi_signal_t;
+// 0 is reserved; POSIX has special semantics for kill(pid, 0).
+#define __WASI_SIGHUP (1)
+#define __WASI_SIGINT (2)
+#define __WASI_SIGQUIT (3)
+#define __WASI_SIGILL (4)
+#define __WASI_SIGTRAP (5)
+#define __WASI_SIGABRT (6)
+#define __WASI_SIGBUS (7)
+#define __WASI_SIGFPE (8)
+#define __WASI_SIGKILL (9)
+#define __WASI_SIGUSR1 (10)
+#define __WASI_SIGSEGV (11)
+#define __WASI_SIGUSR2 (12)
+#define __WASI_SIGPIPE (13)
+#define __WASI_SIGALRM (14)
+#define __WASI_SIGTERM (15)
+#define __WASI_SIGCHLD (16)
+#define __WASI_SIGCONT (17)
+#define __WASI_SIGSTOP (18)
+#define __WASI_SIGTSTP (19)
+#define __WASI_SIGTTIN (20)
+#define __WASI_SIGTTOU (21)
+#define __WASI_SIGURG (22)
+#define __WASI_SIGXCPU (23)
+#define __WASI_SIGXFSZ (24)
+#define __WASI_SIGVTALRM (25)
+#define __WASI_SIGPROF (26)
+#define __WASI_SIGWINCH (27)
+#define __WASI_SIGPOLL (28)
+#define __WASI_SIGPWR (29)
+#define __WASI_SIGSYS (30)
+
+typedef uint16_t __wasi_subclockflags_t;
+#define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001)
+
+typedef uint64_t __wasi_timestamp_t;
+
+typedef uint64_t __wasi_userdata_t;
+
+typedef uint8_t __wasi_whence_t;
+#define __WASI_WHENCE_SET (0)
+#define __WASI_WHENCE_CUR (1)
+#define __WASI_WHENCE_END (2)
+
+typedef uint8_t __wasi_preopentype_t;
+#define __WASI_PREOPENTYPE_DIR (0)
+
+struct fd_table;
+struct fd_prestats;
+struct argv_environ_values;
+struct addr_pool;
+
+typedef struct __wasi_dirent_t {
+ __wasi_dircookie_t d_next;
+ __wasi_inode_t d_ino;
+ __wasi_dirnamlen_t d_namlen;
+ __wasi_filetype_t d_type;
+} __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");
+_Static_assert(offsetof(__wasi_dirent_t, d_type) == 20, "non-wasi data layout");
+_Static_assert(sizeof(__wasi_dirent_t) == 24, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_dirent_t) == 8, "non-wasi data layout");
+
+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 __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");
+_Static_assert(
+ offsetof(__wasi_event_t, u.fd_readwrite.nbytes) == 16, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_event_t, u.fd_readwrite.flags) == 24, "non-wasi data layout");
+_Static_assert(sizeof(__wasi_event_t) == 32, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_event_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_prestat_t {
+ __wasi_preopentype_t pr_type;
+ union __wasi_prestat_u {
+ struct __wasi_prestat_u_dir_t {
+ size_t pr_name_len;
+ } dir;
+ } u;
+} __wasi_prestat_t;
+_Static_assert(offsetof(__wasi_prestat_t, pr_type) == 0, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ sizeof(__wasi_prestat_t) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ sizeof(__wasi_prestat_t) == 16, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ _Alignof(__wasi_prestat_t) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ _Alignof(__wasi_prestat_t) == 8, "non-wasi data layout");
+
+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 __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");
+_Static_assert(
+ offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16,
+ "non-wasi data layout");
+_Static_assert(sizeof(__wasi_fdstat_t) == 24, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_fdstat_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_filestat_t {
+ __wasi_device_t st_dev;
+ __wasi_inode_t st_ino;
+ __wasi_filetype_t st_filetype;
+ __wasi_linkcount_t st_nlink;
+ __wasi_filesize_t st_size;
+ __wasi_timestamp_t st_atim;
+ __wasi_timestamp_t st_mtim;
+ __wasi_timestamp_t st_ctim;
+} __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(
+ offsetof(__wasi_filestat_t, st_filetype) == 16, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_nlink) == 24, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_size) == 32, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_atim) == 40, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_mtim) == 48, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_ctim) == 56, "non-wasi data layout");
+_Static_assert(sizeof(__wasi_filestat_t) == 64, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_filestat_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_ciovec_t {
+ const void *buf;
+ size_t buf_len;
+} __wasi_ciovec_t;
+_Static_assert(offsetof(__wasi_ciovec_t, buf) == 0, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ offsetof(__wasi_ciovec_t, buf_len) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ offsetof(__wasi_ciovec_t, buf_len) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ sizeof(__wasi_ciovec_t) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ sizeof(__wasi_ciovec_t) == 16, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ _Alignof(__wasi_ciovec_t) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ _Alignof(__wasi_ciovec_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_iovec_t {
+ void *buf;
+ size_t buf_len;
+} __wasi_iovec_t;
+_Static_assert(offsetof(__wasi_iovec_t, buf) == 0, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ offsetof(__wasi_iovec_t, buf_len) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ offsetof(__wasi_iovec_t, buf_len) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ sizeof(__wasi_iovec_t) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ sizeof(__wasi_iovec_t) == 16, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ _Alignof(__wasi_iovec_t) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ _Alignof(__wasi_iovec_t) == 8, "non-wasi data layout");
+
+/**
+ * The contents of a `subscription` when type is `eventtype::clock`.
+ */
+typedef struct __wasi_subscription_clock_t {
+ /**
+ * The clock against which to compare the timestamp.
+ */
+ __wasi_clockid_t clock_id;
+
+ uint8_t __paddings1[4];
+
+ /**
+ * The absolute or relative timestamp.
+ */
+ __wasi_timestamp_t timeout;
+
+ /**
+ * The amount of time that the implementation may wait additionally
+ * to coalesce with other events.
+ */
+ __wasi_timestamp_t precision;
+
+ /**
+ * Flags specifying whether the timeout is absolute or relative
+ */
+ __wasi_subclockflags_t flags;
+
+ uint8_t __paddings2[4];
+
+} __wasi_subscription_clock_t __attribute__((aligned(8)));
+
+_Static_assert(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_clock_t, clock_id) == 0, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset");
+
+/**
+ * The contents of a `subscription` when type is type is
+ * `eventtype::fd_read` or `eventtype::fd_write`.
+ */
+typedef struct __wasi_subscription_fd_readwrite_t {
+ /**
+ * The file descriptor on which to wait for it to become ready for reading or writing.
+ */
+ __wasi_fd_t fd;
+
+} __wasi_subscription_fd_readwrite_t;
+
+_Static_assert(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, fd) == 0, "witx calculated offset");
+
+/**
+ * The contents of a `subscription`.
+ */
+typedef union __wasi_subscription_u_u_t {
+ __wasi_subscription_clock_t clock;
+ __wasi_subscription_fd_readwrite_t fd_readwrite;
+} __wasi_subscription_u_u_t ;
+
+typedef struct __wasi_subscription_u_t {
+ __wasi_eventtype_t type;
+ __wasi_subscription_u_u_t u;
+} __wasi_subscription_u_t __attribute__((aligned(8)));
+
+_Static_assert(sizeof(__wasi_subscription_u_t) == 40, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_u_t, u) == 8, "witx calculated union offset");
+_Static_assert(sizeof(__wasi_subscription_u_u_t) == 32, "witx calculated union size");
+_Static_assert(_Alignof(__wasi_subscription_u_u_t) == 8, "witx calculated union align");
+
+/**
+ * Subscription to an event.
+ */
+typedef struct __wasi_subscription_t {
+ /**
+ * User-provided value that is attached to the subscription in the
+ * implementation and returned through `event::userdata`.
+ */
+ __wasi_userdata_t userdata;
+
+ /**
+ * The type of the event to which to subscribe, and its contents
+ */
+ __wasi_subscription_u_t u;
+
+} __wasi_subscription_t;
+
+_Static_assert(sizeof(__wasi_subscription_t) == 48, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset");
+
+/* keep syncing with wasi_socket_ext.h */
+typedef enum {
+ SOCKET_DGRAM = 0,
+ SOCKET_STREAM,
+} __wasi_sock_type_t;
+
+typedef uint16_t __wasi_ip_port_t;
+
+typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
+
+/* n0.n1.n2.n3 */
+typedef struct __wasi_addr_ip4_t {
+ uint8_t n0;
+ uint8_t n1;
+ uint8_t n2;
+ uint8_t n3;
+} __wasi_addr_ip4_t;
+
+typedef struct __wasi_addr_ip4_port_t {
+ __wasi_addr_ip4_t addr;
+ __wasi_ip_port_t port;
+} __wasi_addr_ip4_port_t;
+
+typedef struct __wasi_addr_ip6_t {
+ uint16_t n0;
+ uint16_t n1;
+ uint16_t n2;
+ uint16_t n3;
+ uint16_t h0;
+ uint16_t h1;
+ uint16_t h2;
+ uint16_t h3;
+} __wasi_addr_ip6_t;
+
+typedef struct __wasi_addr_ip6_port_t {
+ __wasi_addr_ip6_t addr;
+ __wasi_ip_port_t port;
+} __wasi_addr_ip6_port_t;
+
+typedef struct __wasi_addr_ip_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_t ip4;
+ __wasi_addr_ip6_t ip6;
+ } addr;
+} __wasi_addr_ip_t;
+
+typedef struct __wasi_addr_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_port_t ip4;
+ __wasi_addr_ip6_port_t ip6;
+ } addr;
+} __wasi_addr_t;
+
+typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
+
+typedef struct __wasi_addr_info_t {
+ __wasi_addr_t addr;
+ __wasi_sock_type_t type;
+} __wasi_addr_info_t;
+
+typedef struct __wasi_addr_info_hints_t {
+ __wasi_sock_type_t type;
+ __wasi_address_family_t family;
+ // this is to workaround lack of optional parameters
+ uint8_t hints_enabled;
+} __wasi_addr_info_hints_t;
+
+#if defined(WASMTIME_SSP_WASI_API)
+#define WASMTIME_SSP_SYSCALL_NAME(name) \
+ asm("__wasi_" #name)
+#else
+#define WASMTIME_SSP_SYSCALL_NAME(name)
+#endif
+
+__wasi_errno_t wasmtime_ssp_args_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ char **argv,
+ char *argv_buf
+) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_args_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ size_t *argc,
+ size_t *argv_buf_size
+) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_clock_res_get(
+ __wasi_clockid_t clock_id,
+ __wasi_timestamp_t *resolution
+) WASMTIME_SSP_SYSCALL_NAME(clock_res_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_clock_time_get(
+ __wasi_clockid_t clock_id,
+ __wasi_timestamp_t precision,
+ __wasi_timestamp_t *time
+) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_environ_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ char **environ,
+ char *environ_buf
+) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_environ_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ size_t *environ_count,
+ size_t *environ_buf_size
+) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_prestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd,
+ __wasi_prestat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd,
+ char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_close(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd
+) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_datasync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd
+) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_pread(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_iovec_t *iovs,
+ size_t iovs_len,
+ __wasi_filesize_t offset,
+ size_t *nread
+) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_pwrite(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_ciovec_t *iovs,
+ size_t iovs_len,
+ __wasi_filesize_t offset,
+ size_t *nwritten
+) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_read(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_iovec_t *iovs,
+ size_t iovs_len,
+ size_t *nread
+) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_renumber(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t from,
+ __wasi_fd_t to
+) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_seek(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filedelta_t offset,
+ __wasi_whence_t whence,
+ __wasi_filesize_t *newoffset
+) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_tell(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t *newoffset
+) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_fdstat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_fdstat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_fdflags_t flags
+) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting
+) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_sync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd
+) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_write(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_ciovec_t *iovs,
+ size_t iovs_len,
+ size_t *nwritten
+) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_advise(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t offset,
+ __wasi_filesize_t len,
+ __wasi_advice_t advice
+) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_allocate(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t offset,
+ __wasi_filesize_t len
+) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_create_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_link(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t old_fd,
+ __wasi_lookupflags_t old_flags,
+ const char *old_path,
+ size_t old_path_len,
+ __wasi_fd_t new_fd,
+ const char *new_path,
+ size_t new_path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t dirfd,
+ __wasi_lookupflags_t dirflags,
+ const char *path,
+ size_t path_len,
+ __wasi_oflags_t oflags,
+ __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting,
+ __wasi_fdflags_t fs_flags,
+ __wasi_fd_t *fd
+) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_readdir(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ void *buf,
+ size_t buf_len,
+ __wasi_dircookie_t cookie,
+ size_t *bufused
+) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_readlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len,
+ char *buf,
+ size_t buf_len,
+ size_t *bufused
+) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_rename(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t old_fd,
+ const char *old_path,
+ size_t old_path_len,
+ __wasi_fd_t new_fd,
+ const char *new_path,
+ size_t new_path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filestat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_timestamp_t st_atim,
+ __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags
+) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_filestat_set_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t st_size
+) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_lookupflags_t flags,
+ const char *path,
+ size_t path_len,
+ __wasi_filestat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_lookupflags_t flags,
+ const char *path,
+ size_t path_len,
+ __wasi_timestamp_t st_atim,
+ __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags
+) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_symlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ const char *old_path,
+ size_t old_path_len,
+ __wasi_fd_t fd,
+ const char *new_path,
+ size_t new_path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_unlink_file(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_remove_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_poll_oneoff(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ const __wasi_subscription_t *in,
+ __wasi_event_t *out,
+ size_t nsubscriptions,
+ size_t *nevents
+) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__));
+
+#if 0
+/**
+ * We throw exception in libc-wasi wrapper function wasi_proc_exit()
+ * but not call this function.
+ */
+_Noreturn void wasmtime_ssp_proc_exit(
+ __wasi_exitcode_t rval
+) WASMTIME_SSP_SYSCALL_NAME(proc_exit);
+#endif
+
+__wasi_errno_t wasmtime_ssp_proc_raise(
+ __wasi_signal_t sig
+) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_random_get(
+ void *buf,
+ size_t buf_len
+) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_accept(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_addr_local(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_addr_remote(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
+ __wasi_fd_t *sockfd
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_bind(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_addr_resolve(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, char **ns_lookup_list,
+#endif
+ const char *host, const char* service,
+ __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info,
+ __wasi_size_t addr_info_size, __wasi_size_t *max_info_size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_listen(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t backlog
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_recv(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ void *buf,
+ size_t buf_len,
+ size_t *recv_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_recv_from(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ void *buf,
+ size_t buf_len,
+ __wasi_riflags_t ri_flags,
+ __wasi_addr_t *src_addr,
+ size_t *recv_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_send(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ const void *buf,
+ size_t buf_len,
+ size_t *sent_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_send_to(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t sock,
+ const void *buf,
+ size_t buf_len,
+ __wasi_siflags_t si_flags,
+ const __wasi_addr_t *dest_addr,
+ size_t *sent_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_shutdown(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock
+) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t *timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_send_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_send_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t *timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t *bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t *bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__));
+
+
+__wasi_errno_t wasmtime_ssp_sock_set_keep_alive(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_keep_alive(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled,
+ int linger_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool *is_enabled, int *linger_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_broadcast(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_broadcast(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t *time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t *time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool ipv6,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool ipv6,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ip_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t *ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t *ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ipv6_only(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ipv6_only(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sched_yield(void)
+ WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef WASMTIME_SSP_SYSCALL_NAME
+
+/* clang-format on */
+
+#endif /* end of WASMTIME_SSP_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE
new file mode 100644
index 000000000..04c6f48a2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE
@@ -0,0 +1,24 @@
+All code is distributed under the following license:
+
+ Copyright (c) 2015 Nuxi, https://nuxi.nl/
+
+ 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.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md
new file mode 100644
index 000000000..b4d55d803
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md
@@ -0,0 +1,14 @@
+This directory consists of selected files copied from the [src/libemulator]
+directory in the [cloudabi-utils] repository, with minor modifications,
+along with the accompanying LICENSE file from that repository.
+
+The modifications are marked with `WASMTIME_*` preprocessor macros.
+
+The files were copied at git revision
+223dadc53248552db43e012c67ed08cf416a2b12
+which is dated
+Tue Jun 25 17:22:07 2019 -0700
+.
+
+[libemulator]: https://github.com/NuxiNL/cloudabi-utils/tree/223dadc53248552db43e012c67ed08cf416a2b12/src/libemulator
+[cloudabi-utils]: https://github.com/NuxiNL/cloudabi-utils
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h
new file mode 100644
index 000000000..70000ae0b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if !defined(__GNUC_PREREQ) && (defined(__GNUC__) || defined(__GNUG__)) \
+ && !defined(__clang__) && defined(__GNUC_MINOR__)
+/* Depending on the platform the macro is defined in sys/features.h or
+ features.h Given the macro is simple, we re-implement it here instead of
+ dealing with two different paths.
+ */
+#define __GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h
new file mode 100644
index 000000000..40b064b81
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h
@@ -0,0 +1,265 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef LOCKING_H
+#define LOCKING_H
+
+#include "ssp_config.h"
+
+#ifndef __has_extension
+#define __has_extension(x) 0
+#endif
+
+#if __has_extension(c_thread_safety_attributes)
+#define LOCK_ANNOTATE(x) __attribute__((x))
+#else
+#define LOCK_ANNOTATE(x)
+#endif
+
+/* Lock annotation macros. */
+
+#define LOCKABLE LOCK_ANNOTATE(lockable)
+
+#define LOCKS_EXCLUSIVE(...) LOCK_ANNOTATE(exclusive_lock_function(__VA_ARGS__))
+#define LOCKS_SHARED(...) LOCK_ANNOTATE(shared_lock_function(__VA_ARGS__))
+
+#define TRYLOCKS_EXCLUSIVE(...) \
+ LOCK_ANNOTATE(exclusive_trylock_function(__VA_ARGS__))
+#define TRYLOCKS_SHARED(...) LOCK_ANNOTATE(shared_trylock_function(__VA_ARGS__))
+
+#define UNLOCKS(...) LOCK_ANNOTATE(unlock_function(__VA_ARGS__))
+
+#define REQUIRES_EXCLUSIVE(...) \
+ LOCK_ANNOTATE(exclusive_locks_required(__VA_ARGS__))
+#define REQUIRES_SHARED(...) LOCK_ANNOTATE(shared_locks_required(__VA_ARGS__))
+#define REQUIRES_UNLOCKED(...) LOCK_ANNOTATE(locks_excluded(__VA_ARGS__))
+
+#define NO_LOCK_ANALYSIS LOCK_ANNOTATE(no_thread_safety_analysis)
+
+/* Mutex that uses the lock annotations. */
+
+struct LOCKABLE mutex {
+ pthread_mutex_t object;
+};
+
+/* clang-format off */
+#define MUTEX_INITIALIZER \
+ { PTHREAD_MUTEX_INITIALIZER }
+/* clang-format on */
+
+static inline bool
+mutex_init(struct mutex *lock) REQUIRES_UNLOCKED(*lock)
+{
+ return pthread_mutex_init(&lock->object, NULL) == 0 ? true : false;
+}
+
+static inline void
+mutex_destroy(struct mutex *lock) REQUIRES_UNLOCKED(*lock)
+{
+ pthread_mutex_destroy(&lock->object);
+}
+
+static inline void
+mutex_lock(struct mutex *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_mutex_lock(&lock->object);
+}
+
+static inline void
+mutex_unlock(struct mutex *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_mutex_unlock(&lock->object);
+}
+
+/* Read-write lock that uses the lock annotations. */
+
+struct LOCKABLE rwlock {
+ pthread_rwlock_t object;
+};
+
+static inline bool
+rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock)
+{
+ return pthread_rwlock_init(&lock->object, NULL) == 0 ? true : false;
+}
+
+static inline void
+rwlock_rdlock(struct rwlock *lock) LOCKS_SHARED(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_rdlock(&lock->object);
+}
+
+static inline void
+rwlock_wrlock(struct rwlock *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_wrlock(&lock->object);
+}
+
+static inline void
+rwlock_unlock(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_unlock(&lock->object);
+}
+
+static inline void
+rwlock_destroy(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_destroy(&lock->object);
+}
+
+/* Condition variable that uses the lock annotations. */
+
+struct LOCKABLE cond {
+ pthread_cond_t object;
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \
+ || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ clockid_t clock;
+#endif
+};
+
+static inline bool
+cond_init_monotonic(struct cond *cond)
+{
+ bool ret = false;
+#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
+ pthread_condattr_t attr;
+
+ if (pthread_condattr_init(&attr) != 0)
+ return false;
+
+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0)
+ goto fail;
+
+ if (pthread_cond_init(&cond->object, &attr) != 0)
+ goto fail;
+
+ ret = true;
+fail:
+ pthread_condattr_destroy(&attr);
+#else
+ if (pthread_cond_init(&cond->object, NULL) != 0)
+ return false;
+ ret = true;
+#endif
+
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \
+ || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ cond->clock = CLOCK_MONOTONIC;
+#endif
+ return ret;
+}
+
+static inline bool
+cond_init_realtime(struct cond *cond)
+{
+ if (pthread_cond_init(&cond->object, NULL) != 0)
+ return false;
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \
+ || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ cond->clock = CLOCK_REALTIME;
+#endif
+ return true;
+}
+
+static inline void
+cond_destroy(struct cond *cond)
+{
+ pthread_cond_destroy(&cond->object);
+}
+
+static inline void
+cond_signal(struct cond *cond)
+{
+ pthread_cond_signal(&cond->object);
+}
+
+#if !CONFIG_HAS_CLOCK_NANOSLEEP
+static inline bool
+cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
+ bool abstime) REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ int ret;
+ struct timespec ts = {
+ .tv_sec = (time_t)(timeout / 1000000000),
+ .tv_nsec = (long)(timeout % 1000000000),
+ };
+
+ if (abstime) {
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
+ /**
+ * No native support for sleeping on monotonic clocks. Convert the
+ * timeout to a relative value and then to an absolute value for the
+ * realtime clock.
+ */
+ if (cond->clock != CLOCK_REALTIME) {
+ struct timespec ts_monotonic;
+ struct timespec ts_realtime;
+
+ clock_gettime(cond->clock, &ts_monotonic);
+ ts.tv_sec -= ts_monotonic.tv_sec;
+ ts.tv_nsec -= ts_monotonic.tv_nsec;
+ if (ts.tv_nsec < 0) {
+ ts.tv_nsec += 1000000000;
+ --ts.tv_sec;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &ts_realtime);
+ ts.tv_sec += ts_realtime.tv_sec;
+ ts.tv_nsec += ts_realtime.tv_nsec;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+ }
+#endif
+ }
+ else {
+#if CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ /* Implementation supports relative timeouts. */
+ ret = pthread_cond_timedwait_relative_np(&cond->object, &lock->object,
+ &ts);
+ bh_assert((ret == 0 || ret == ETIMEDOUT)
+ && "pthread_cond_timedwait_relative_np() failed");
+ return ret == ETIMEDOUT;
+#else
+ /* Convert to absolute timeout. */
+ struct timespec ts_now;
+#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
+ clock_gettime(cond->clock, &ts_now);
+#else
+ clock_gettime(CLOCK_REALTIME, &ts_now);
+#endif
+ ts.tv_sec += ts_now.tv_sec;
+ ts.tv_nsec += ts_now.tv_nsec;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+#endif
+ }
+
+ ret = pthread_cond_timedwait(&cond->object, &lock->object, &ts);
+ bh_assert((ret == 0 || ret == ETIMEDOUT)
+ && "pthread_cond_timedwait() failed");
+ return ret == ETIMEDOUT;
+}
+#endif
+
+static inline void
+cond_wait(struct cond *cond, struct mutex *lock)
+ REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_cond_wait(&cond->object, &lock->object);
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
new file mode 100644
index 000000000..61e841836
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
@@ -0,0 +1,4072 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "wasmtime_ssp.h"
+#include "locking.h"
+#include "posix.h"
+#include "random.h"
+#include "refcount.h"
+#include "rights.h"
+#include "str.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),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_base) ==
+ sizeof(((__wasi_iovec_t *)0)->buf),
+ "Size mismatch");
+static_assert(offsetof(struct iovec, iov_len) ==
+ offsetof(__wasi_iovec_t, buf_len),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_len) ==
+ sizeof(((__wasi_iovec_t *)0)->buf_len),
+ "Size mismatch");
+static_assert(sizeof(struct iovec) == sizeof(__wasi_iovec_t),
+ "Size mismatch");
+
+// struct iovec must have the same layout as __wasi_ciovec_t.
+static_assert(offsetof(struct iovec, iov_base) ==
+ offsetof(__wasi_ciovec_t, buf),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_base) ==
+ sizeof(((__wasi_ciovec_t *)0)->buf),
+ "Size mismatch");
+static_assert(offsetof(struct iovec, iov_len) ==
+ offsetof(__wasi_ciovec_t, buf_len),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_len) ==
+ sizeof(((__wasi_ciovec_t *)0)->buf_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;
+static __thread struct fd_prestats *prestats;
+static __thread struct argv_environ_values *argv_environ;
+static __thread struct addr_pool *addr_pool;
+#endif
+
+// Converts a POSIX error code to a CloudABI error code.
+static __wasi_errno_t
+convert_errno(int error)
+{
+ static const __wasi_errno_t errors[] = {
+#define X(v) [v] = __WASI_##v
+ X(E2BIG),
+ X(EACCES),
+ X(EADDRINUSE),
+ X(EADDRNOTAVAIL),
+ X(EAFNOSUPPORT),
+ X(EAGAIN),
+ X(EALREADY),
+ X(EBADF),
+ X(EBADMSG),
+ X(EBUSY),
+ X(ECANCELED),
+ X(ECHILD),
+ X(ECONNABORTED),
+ X(ECONNREFUSED),
+ X(ECONNRESET),
+ X(EDEADLK),
+ X(EDESTADDRREQ),
+ X(EDOM),
+ X(EDQUOT),
+ X(EEXIST),
+ X(EFAULT),
+ X(EFBIG),
+ X(EHOSTUNREACH),
+ X(EIDRM),
+ X(EILSEQ),
+ X(EINPROGRESS),
+ X(EINTR),
+ X(EINVAL),
+ X(EIO),
+ X(EISCONN),
+ X(EISDIR),
+ X(ELOOP),
+ X(EMFILE),
+ X(EMLINK),
+ X(EMSGSIZE),
+ X(EMULTIHOP),
+ X(ENAMETOOLONG),
+ X(ENETDOWN),
+ X(ENETRESET),
+ X(ENETUNREACH),
+ X(ENFILE),
+ X(ENOBUFS),
+ X(ENODEV),
+ X(ENOENT),
+ X(ENOEXEC),
+ X(ENOLCK),
+ X(ENOLINK),
+ X(ENOMEM),
+ X(ENOMSG),
+ X(ENOPROTOOPT),
+ X(ENOSPC),
+ X(ENOSYS),
+#ifdef ENOTCAPABLE
+ X(ENOTCAPABLE),
+#endif
+ X(ENOTCONN),
+ X(ENOTDIR),
+ X(ENOTEMPTY),
+ X(ENOTRECOVERABLE),
+ X(ENOTSOCK),
+ X(ENOTSUP),
+ X(ENOTTY),
+ X(ENXIO),
+ X(EOVERFLOW),
+ X(EOWNERDEAD),
+ X(EPERM),
+ X(EPIPE),
+ X(EPROTO),
+ X(EPROTONOSUPPORT),
+ X(EPROTOTYPE),
+ X(ERANGE),
+ X(EROFS),
+ X(ESPIPE),
+ X(ESRCH),
+ X(ESTALE),
+ X(ETIMEDOUT),
+ X(ETXTBSY),
+ X(EXDEV),
+#undef X
+#if EOPNOTSUPP != ENOTSUP
+ [EOPNOTSUPP] = __WASI_ENOTSUP,
+#endif
+#if EWOULDBLOCK != EAGAIN
+ [EWOULDBLOCK] = __WASI_EAGAIN,
+#endif
+ };
+ if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0])
+ || errors[error] == 0)
+ return __WASI_ENOSYS;
+ return errors[error];
+}
+
+static bool
+ns_lookup_list_search(char **list, const char *host)
+{
+ size_t host_len = strlen(host), suffix_len;
+
+ while (*list) {
+ if (*list[0] == '*') {
+ suffix_len = strlen(*list) - 1;
+ if (suffix_len <= host_len
+ && strncmp(host + host_len - suffix_len, *list + 1, suffix_len)
+ == 0) {
+ return true;
+ }
+ }
+ else {
+ if (strcmp(*list, host) == 0) {
+ return true;
+ }
+ }
+ list++;
+ }
+
+ return false;
+}
+
+// Converts a POSIX timespec to a CloudABI timestamp.
+static __wasi_timestamp_t
+convert_timespec(const struct timespec *ts)
+{
+ if (ts->tv_sec < 0)
+ return 0;
+ if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000)
+ return UINT64_MAX;
+ return (__wasi_timestamp_t)ts->tv_sec * 1000000000
+ + (__wasi_timestamp_t)ts->tv_nsec;
+}
+
+// Converts a CloudABI clock identifier to a POSIX clock identifier.
+static bool
+convert_clockid(__wasi_clockid_t in, clockid_t *out)
+{
+ switch (in) {
+ case __WASI_CLOCK_MONOTONIC:
+ *out = CLOCK_MONOTONIC;
+ return true;
+#if defined(CLOCK_PROCESS_CPUTIME_ID)
+ case __WASI_CLOCK_PROCESS_CPUTIME_ID:
+ *out = CLOCK_PROCESS_CPUTIME_ID;
+ return true;
+#endif
+ case __WASI_CLOCK_REALTIME:
+ *out = CLOCK_REALTIME;
+ return true;
+#if defined(CLOCK_THREAD_CPUTIME_ID)
+ case __WASI_CLOCK_THREAD_CPUTIME_ID:
+ *out = CLOCK_THREAD_CPUTIME_ID;
+ return true;
+#endif
+ default:
+ return false;
+ }
+}
+
+static void
+wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr,
+ bh_sockaddr_t *sockaddr)
+{
+ if (wasi_addr->kind == IPv4) {
+ sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24)
+ | (wasi_addr->addr.ip4.addr.n1 << 16)
+ | (wasi_addr->addr.ip4.addr.n2 << 8)
+ | wasi_addr->addr.ip4.addr.n3;
+ sockaddr->is_ipv4 = true;
+ sockaddr->port = wasi_addr->addr.ip4.port;
+ }
+ else {
+ sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0;
+ sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1;
+ sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2;
+ sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3;
+ sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0;
+ sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1;
+ sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2;
+ sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3;
+ sockaddr->is_ipv4 = false;
+ sockaddr->port = wasi_addr->addr.ip6.port;
+ }
+}
+
+// Converts an IPv6 binary address object to WASI address object.
+static void
+bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr,
+ __wasi_addr_t *wasi_addr)
+{
+ if (sockaddr->is_ipv4) {
+ wasi_addr->kind = IPv4;
+ wasi_addr->addr.ip4.port = sockaddr->port;
+ wasi_addr->addr.ip4.addr.n0 =
+ (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24;
+ wasi_addr->addr.ip4.addr.n1 =
+ (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16;
+ wasi_addr->addr.ip4.addr.n2 =
+ (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8;
+ wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF);
+ }
+ else {
+ wasi_addr->kind = IPv6;
+ wasi_addr->addr.ip6.port = sockaddr->port;
+ wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0];
+ wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1];
+ wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2];
+ wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3];
+ wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4];
+ wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5];
+ wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6];
+ wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7];
+ }
+}
+
+static void
+wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr,
+ bh_ip_addr_buffer_t *out)
+{
+ if (addr->kind == IPv4) {
+ out->ipv4 = htonl((addr->addr.ip4.n0 << 24) | (addr->addr.ip4.n1 << 16)
+ | (addr->addr.ip4.n2 << 8) | addr->addr.ip4.n3);
+ }
+ else {
+ out->ipv6[0] = htons(addr->addr.ip6.n0);
+ out->ipv6[1] = htons(addr->addr.ip6.n1);
+ out->ipv6[2] = htons(addr->addr.ip6.n2);
+ out->ipv6[3] = htons(addr->addr.ip6.n3);
+ out->ipv6[4] = htons(addr->addr.ip6.h0);
+ out->ipv6[5] = htons(addr->addr.ip6.h1);
+ out->ipv6[6] = htons(addr->addr.ip6.h2);
+ out->ipv6[7] = htons(addr->addr.ip6.h3);
+ }
+}
+
+__wasi_errno_t
+wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id,
+ __wasi_timestamp_t *resolution)
+{
+ clockid_t nclock_id;
+ if (!convert_clockid(clock_id, &nclock_id))
+ return __WASI_EINVAL;
+ struct timespec ts;
+ if (clock_getres(nclock_id, &ts) < 0)
+ return convert_errno(errno);
+ *resolution = convert_timespec(&ts);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id,
+ __wasi_timestamp_t precision,
+ __wasi_timestamp_t *time)
+{
+ clockid_t nclock_id;
+ if (!convert_clockid(clock_id, &nclock_id))
+ return __WASI_EINVAL;
+ struct timespec ts;
+ if (clock_gettime(nclock_id, &ts) < 0)
+ return convert_errno(errno);
+ *time = convert_timespec(&ts);
+ return 0;
+}
+
+struct fd_prestat {
+ const char *dir;
+};
+
+bool
+fd_prestats_init(struct fd_prestats *pt)
+{
+ if (!rwlock_init(&pt->lock))
+ return false;
+ pt->prestats = NULL;
+ pt->size = 0;
+ pt->used = 0;
+#if defined(WASMTIME_SSP_STATIC_CURFDS)
+ prestats = pt;
+#endif
+ return true;
+}
+
+// Grows the preopened resource table to a required lower bound and a
+// minimum number of free preopened resource table entries.
+static bool
+fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr)
+ REQUIRES_EXCLUSIVE(pt->lock)
+{
+ if (pt->size <= min || pt->size < (pt->used + incr) * 2) {
+ // Keep on doubling the table size until we've met our constraints.
+ size_t size = pt->size == 0 ? 1 : pt->size;
+ while (size <= min || size < (pt->used + incr) * 2)
+ size *= 2;
+
+ // Grow the file descriptor table's allocation.
+ struct fd_prestat *prestats =
+ wasm_runtime_malloc((uint32)(sizeof(*prestats) * size));
+ if (prestats == NULL)
+ return false;
+
+ if (pt->prestats && pt->size > 0) {
+ bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size),
+ pt->prestats, (uint32)(sizeof(*prestats) * pt->size));
+ }
+
+ if (pt->prestats)
+ wasm_runtime_free(pt->prestats);
+
+ // Mark all new file descriptors as unused.
+ for (size_t i = pt->size; i < size; ++i)
+ prestats[i].dir = NULL;
+ pt->prestats = prestats;
+ pt->size = size;
+ }
+ return true;
+}
+
+// Inserts a preopened resource record into the preopened resource table.
+bool
+fd_prestats_insert(struct fd_prestats *pt, const char *dir, __wasi_fd_t fd)
+{
+ // Grow the preopened resource table if needed.
+ rwlock_wrlock(&pt->lock);
+ if (!fd_prestats_grow(pt, fd, 1)) {
+ rwlock_unlock(&pt->lock);
+ return false;
+ }
+
+ pt->prestats[fd].dir = bh_strdup(dir);
+ rwlock_unlock(&pt->lock);
+
+ if (pt->prestats[fd].dir == NULL)
+ return false;
+
+ return true;
+}
+
+// Looks up a preopened resource table entry by number.
+static __wasi_errno_t
+fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd,
+ struct fd_prestat **ret) REQUIRES_SHARED(pt->lock)
+{
+ // Test for file descriptor existence.
+ if (fd >= pt->size)
+ return __WASI_EBADF;
+ struct fd_prestat *prestat = &pt->prestats[fd];
+ if (prestat->dir == NULL)
+ return __WASI_EBADF;
+
+ *ret = prestat;
+ return 0;
+}
+
+struct fd_object {
+ struct refcount refcount;
+ __wasi_filetype_t type;
+ int number;
+
+ union {
+ // Data associated with directory file descriptors.
+ struct {
+ struct mutex lock; // Lock to protect members below.
+ DIR *handle; // Directory handle.
+ __wasi_dircookie_t offset; // Offset of the directory.
+ } directory;
+ };
+};
+
+struct fd_entry {
+ struct fd_object *object;
+ __wasi_rights_t rights_base;
+ __wasi_rights_t rights_inheriting;
+};
+
+bool
+fd_table_init(struct fd_table *ft)
+{
+ if (!rwlock_init(&ft->lock))
+ return false;
+ ft->entries = NULL;
+ ft->size = 0;
+ ft->used = 0;
+#if defined(WASMTIME_SSP_STATIC_CURFDS)
+ curfds = ft;
+#endif
+ return true;
+}
+
+// Looks up a file descriptor table entry by number and required rights.
+static __wasi_errno_t
+fd_table_get_entry(struct fd_table *ft, __wasi_fd_t fd,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting, struct fd_entry **ret)
+ REQUIRES_SHARED(ft->lock)
+{
+ // Test for file descriptor existence.
+ if (fd >= ft->size)
+ return __WASI_EBADF;
+ struct fd_entry *fe = &ft->entries[fd];
+ if (fe->object == NULL)
+ return __WASI_EBADF;
+
+ // Validate rights.
+ if ((~fe->rights_base & rights_base) != 0
+ || (~fe->rights_inheriting & rights_inheriting) != 0)
+ return __WASI_ENOTCAPABLE;
+ *ret = fe;
+ return 0;
+}
+
+// Grows the file descriptor table to a required lower bound and a
+// minimum number of free file descriptor table entries.
+static bool
+fd_table_grow(struct fd_table *ft, size_t min, size_t incr)
+ REQUIRES_EXCLUSIVE(ft->lock)
+{
+ if (ft->size <= min || ft->size < (ft->used + incr) * 2) {
+ // Keep on doubling the table size until we've met our constraints.
+ size_t size = ft->size == 0 ? 1 : ft->size;
+ while (size <= min || size < (ft->used + incr) * 2)
+ size *= 2;
+
+ // Grow the file descriptor table's allocation.
+ struct fd_entry *entries =
+ wasm_runtime_malloc((uint32)(sizeof(*entries) * size));
+ if (entries == NULL)
+ return false;
+
+ if (ft->entries && ft->size > 0) {
+ bh_memcpy_s(entries, (uint32)(sizeof(*entries) * size), ft->entries,
+ (uint32)(sizeof(*entries) * ft->size));
+ }
+
+ if (ft->entries)
+ wasm_runtime_free(ft->entries);
+
+ // Mark all new file descriptors as unused.
+ for (size_t i = ft->size; i < size; ++i)
+ entries[i].object = NULL;
+ ft->entries = entries;
+ ft->size = size;
+ }
+ return true;
+}
+
+// Allocates a new file descriptor object.
+static __wasi_errno_t
+fd_object_new(__wasi_filetype_t type, struct fd_object **fo)
+ TRYLOCKS_SHARED(0, (*fo)->refcount)
+{
+ *fo = wasm_runtime_malloc(sizeof(**fo));
+ if (*fo == NULL)
+ return __WASI_ENOMEM;
+ refcount_init(&(*fo)->refcount, 1);
+ (*fo)->type = type;
+ (*fo)->number = -1;
+ return 0;
+}
+
+// Attaches a file descriptor to the file descriptor table.
+static void
+fd_table_attach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object *fo,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting)
+ REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount)
+{
+ assert(ft->size > fd && "File descriptor table too small");
+ struct fd_entry *fe = &ft->entries[fd];
+ assert(fe->object == NULL
+ && "Attempted to overwrite an existing descriptor");
+ fe->object = fo;
+ fe->rights_base = rights_base;
+ fe->rights_inheriting = rights_inheriting;
+ ++ft->used;
+ assert(ft->size >= ft->used * 2 && "File descriptor too full");
+}
+
+// Detaches a file descriptor from the file descriptor table.
+static void
+fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo)
+ REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount)
+{
+ assert(ft->size > fd && "File descriptor table too small");
+ struct fd_entry *fe = &ft->entries[fd];
+ *fo = fe->object;
+ assert(*fo != NULL && "Attempted to detach nonexistent descriptor");
+ fe->object = NULL;
+ assert(ft->used > 0 && "Reference count mismatch");
+ --ft->used;
+}
+
+// Determines the type of a file descriptor and its maximum set of
+// rights that should be attached to it.
+static __wasi_errno_t
+fd_determine_type_rights(int fd, __wasi_filetype_t *type,
+ __wasi_rights_t *rights_base,
+ __wasi_rights_t *rights_inheriting)
+{
+ struct stat sb;
+ if (fstat(fd, &sb) < 0)
+ return convert_errno(errno);
+ if (S_ISBLK(sb.st_mode)) {
+ *type = __WASI_FILETYPE_BLOCK_DEVICE;
+ *rights_base = RIGHTS_BLOCK_DEVICE_BASE;
+ *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING;
+ }
+ else if (S_ISCHR(sb.st_mode)) {
+ *type = __WASI_FILETYPE_CHARACTER_DEVICE;
+#if CONFIG_HAS_ISATTY
+ if (isatty(fd)) {
+ *rights_base = RIGHTS_TTY_BASE;
+ *rights_inheriting = RIGHTS_TTY_INHERITING;
+ }
+ else
+#endif
+ {
+ *rights_base = RIGHTS_CHARACTER_DEVICE_BASE;
+ *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING;
+ }
+ }
+ else if (S_ISDIR(sb.st_mode)) {
+ *type = __WASI_FILETYPE_DIRECTORY;
+ *rights_base = RIGHTS_DIRECTORY_BASE;
+ *rights_inheriting = RIGHTS_DIRECTORY_INHERITING;
+ }
+ else if (S_ISREG(sb.st_mode)) {
+ *type = __WASI_FILETYPE_REGULAR_FILE;
+ *rights_base = RIGHTS_REGULAR_FILE_BASE;
+ *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING;
+ }
+ else if (S_ISSOCK(sb.st_mode)) {
+ int socktype;
+ socklen_t socktypelen = sizeof(socktype);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) < 0)
+ return convert_errno(errno);
+ switch (socktype) {
+ case SOCK_DGRAM:
+ *type = __WASI_FILETYPE_SOCKET_DGRAM;
+ break;
+ case SOCK_STREAM:
+ *type = __WASI_FILETYPE_SOCKET_STREAM;
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+ *rights_base = RIGHTS_SOCKET_BASE;
+ *rights_inheriting = RIGHTS_SOCKET_INHERITING;
+ }
+ else if (S_ISFIFO(sb.st_mode)) {
+ *type = __WASI_FILETYPE_SOCKET_STREAM;
+ *rights_base = RIGHTS_SOCKET_BASE;
+ *rights_inheriting = RIGHTS_SOCKET_INHERITING;
+ }
+ else {
+ return __WASI_EINVAL;
+ }
+
+ // Strip off read/write bits based on the access mode.
+ switch (fcntl(fd, F_GETFL) & O_ACCMODE) {
+ case O_RDONLY:
+ *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE;
+ break;
+ case O_WRONLY:
+ *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ;
+ break;
+ }
+ return 0;
+}
+
+// Returns the underlying file descriptor number of a file descriptor
+// object. This function can only be applied to objects that have an
+// underlying file descriptor number.
+static int
+fd_number(const struct fd_object *fo)
+{
+ int number = fo->number;
+ assert(number >= 0 && "fd_number() called on virtual file descriptor");
+ return number;
+}
+
+#define CLOSE_NON_STD_FD(fd) \
+ do { \
+ if (fd > 2) \
+ close(fd); \
+ } while (0)
+
+// Lowers the reference count on a file descriptor object. When the
+// reference count reaches zero, its resources are cleaned up.
+static void
+fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount)
+{
+ if (refcount_release(&fo->refcount)) {
+ switch (fo->type) {
+ case __WASI_FILETYPE_DIRECTORY:
+ // For directories we may keep track of a DIR object. Calling
+ // closedir() on it also closes the underlying file descriptor.
+ mutex_destroy(&fo->directory.lock);
+ if (fo->directory.handle == NULL) {
+ CLOSE_NON_STD_FD(fd_number(fo));
+ }
+ else {
+ closedir(fo->directory.handle);
+ }
+ break;
+ default:
+ CLOSE_NON_STD_FD(fd_number(fo));
+ break;
+ }
+ wasm_runtime_free(fo);
+ }
+}
+
+// Inserts an already existing file descriptor into the file descriptor
+// table.
+bool
+fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out)
+{
+ __wasi_filetype_t type;
+ __wasi_rights_t rights_base, rights_inheriting;
+ struct fd_object *fo;
+ __wasi_errno_t error;
+
+ error =
+ fd_determine_type_rights(out, &type, &rights_base, &rights_inheriting);
+ if (error != 0) {
+#ifdef BH_PLATFORM_EGO
+ /**
+ * since it is an already opened file and we can assume the opened file
+ * has all necessary rights no matter how to get
+ */
+ if (error != __WASI_ENOTSUP)
+ return false;
+#else
+ return false;
+#endif
+ }
+
+ error = fd_object_new(type, &fo);
+ if (error != 0)
+ return false;
+ fo->number = out;
+ if (type == __WASI_FILETYPE_DIRECTORY) {
+ if (!mutex_init(&fo->directory.lock)) {
+ fd_object_release(fo);
+ return false;
+ }
+ fo->directory.handle = NULL;
+ }
+
+ // Grow the file descriptor table if needed.
+ rwlock_wrlock(&ft->lock);
+ if (!fd_table_grow(ft, in, 1)) {
+ rwlock_unlock(&ft->lock);
+ fd_object_release(fo);
+ return false;
+ }
+
+ fd_table_attach(ft, in, fo, rights_base, rights_inheriting);
+ rwlock_unlock(&ft->lock);
+ return true;
+}
+
+// Picks an unused slot from the file descriptor table.
+static __wasi_fd_t
+fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock)
+{
+ assert(ft->size > ft->used && "File descriptor table has no free slots");
+ for (;;) {
+ __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size);
+ if (ft->entries[fd].object == NULL)
+ return fd;
+ }
+}
+
+// Inserts a file descriptor object into an unused slot of the file
+// descriptor table.
+static __wasi_errno_t
+fd_table_insert(struct fd_table *ft, struct fd_object *fo,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting,
+ __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock)
+ UNLOCKS(fo->refcount)
+{
+ // Grow the file descriptor table if needed.
+ rwlock_wrlock(&ft->lock);
+ if (!fd_table_grow(ft, 0, 1)) {
+ rwlock_unlock(&ft->lock);
+ fd_object_release(fo);
+ return convert_errno(errno);
+ }
+
+ *out = fd_table_unused(ft);
+ fd_table_attach(ft, *out, fo, rights_base, rights_inheriting);
+ rwlock_unlock(&ft->lock);
+ return 0;
+}
+
+// Inserts a numerical file descriptor into the file descriptor table.
+static __wasi_errno_t
+fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting, __wasi_fd_t *out)
+ REQUIRES_UNLOCKED(ft->lock)
+{
+ struct fd_object *fo;
+
+ __wasi_errno_t error = fd_object_new(type, &fo);
+ if (error != 0) {
+ close(in);
+ return error;
+ }
+
+ fo->number = in;
+ if (type == __WASI_FILETYPE_DIRECTORY) {
+ if (!mutex_init(&fo->directory.lock)) {
+ fd_object_release(fo);
+ return (__wasi_errno_t)-1;
+ }
+ fo->directory.handle = NULL;
+ }
+ return fd_table_insert(ft, fo, rights_base, rights_inheriting, out);
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_prestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd, __wasi_prestat_t *buf)
+{
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
+ if (error != 0) {
+ rwlock_unlock(&prestats->lock);
+ return error;
+ }
+
+ *buf = (__wasi_prestat_t){
+ .pr_type = __WASI_PREOPENTYPE_DIR,
+ };
+
+ buf->u.dir.pr_name_len = strlen(prestat->dir);
+
+ rwlock_unlock(&prestats->lock);
+
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_prestat_dir_name(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd, char *path, size_t path_len)
+{
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
+ if (error != 0) {
+ rwlock_unlock(&prestats->lock);
+ return error;
+ }
+ if (path_len != strlen(prestat->dir)) {
+ rwlock_unlock(&prestats->lock);
+ return EINVAL;
+ }
+
+ bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len);
+
+ rwlock_unlock(&prestats->lock);
+
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_close(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd)
+{
+ // Don't allow closing a pre-opened resource.
+ // TODO: Eventually, we do want to permit this, once libpreopen in
+ // userspace is capable of removing entries from its tables as well.
+ {
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
+ rwlock_unlock(&prestats->lock);
+ if (error == 0) {
+ return __WASI_ENOTSUP;
+ }
+ }
+
+ // Validate the file descriptor.
+ struct fd_table *ft = curfds;
+ rwlock_wrlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ // Remove it from the file descriptor table.
+ struct fd_object *fo;
+ fd_table_detach(ft, fd, &fo);
+ rwlock_unlock(&ft->lock);
+ fd_object_release(fo);
+ return 0;
+}
+
+// Look up a file descriptor object in a locked file descriptor table
+// and increases its reference count.
+static __wasi_errno_t
+fd_object_get_locked(struct fd_object **fo, struct fd_table *ft, __wasi_fd_t fd,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting)
+ TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) REQUIRES_EXCLUSIVE(ft->lock)
+{
+ // Test whether the file descriptor number is valid.
+ struct fd_entry *fe;
+ __wasi_errno_t error =
+ fd_table_get_entry(ft, fd, rights_base, rights_inheriting, &fe);
+ if (error != 0)
+ return error;
+
+ // Increase the reference count on the file descriptor object. A copy
+ // of the rights are also stored, so callers can still access those if
+ // needed.
+ *fo = fe->object;
+ refcount_acquire(&(*fo)->refcount);
+ return 0;
+}
+
+// Temporarily locks the file descriptor table to look up a file
+// descriptor object, increases its reference count and drops the lock.
+static __wasi_errno_t
+fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting)
+ TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount)
+{
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ __wasi_errno_t error =
+ fd_object_get_locked(fo, ft, fd, rights_base, rights_inheriting);
+ rwlock_unlock(&ft->lock);
+ return error;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_datasync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_DATASYNC, 0);
+ if (error != 0)
+ return error;
+
+#if CONFIG_HAS_FDATASYNC
+ int ret = fdatasync(fd_number(fo));
+#else
+ int ret = fsync(fd_number(fo));
+#endif
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_pread(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt,
+ __wasi_filesize_t offset, size_t *nread)
+{
+ if (iovcnt == 0)
+ return __WASI_EINVAL;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0);
+ if (error != 0)
+ return error;
+
+#if CONFIG_HAS_PREADV
+ ssize_t len = preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt,
+ (off_t)offset);
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nread = (size_t)len;
+ return 0;
+#else
+ if (iovcnt == 1) {
+ ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset);
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nread = len;
+ return 0;
+ }
+ else {
+ // Allocate a single buffer to fit all data.
+ size_t totalsize = 0;
+ for (size_t i = 0; i < iovcnt; ++i)
+ totalsize += iov[i].buf_len;
+ char *buf = wasm_runtime_malloc(totalsize);
+ if (buf == NULL) {
+ fd_object_release(fo);
+ return __WASI_ENOMEM;
+ }
+
+ // Perform a single read operation.
+ ssize_t len = pread(fd_number(fo), buf, totalsize, offset);
+ fd_object_release(fo);
+ if (len < 0) {
+ wasm_runtime_free(buf);
+ return convert_errno(errno);
+ }
+
+ // Copy data back to vectors.
+ size_t bufoff = 0;
+ for (size_t i = 0; i < iovcnt; ++i) {
+ if (bufoff + iov[i].buf_len < (size_t)len) {
+ bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff,
+ iov[i].buf_len);
+ bufoff += iov[i].buf_len;
+ }
+ else {
+ bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff,
+ len - bufoff);
+ break;
+ }
+ }
+ wasm_runtime_free(buf);
+ *nread = len;
+ return 0;
+ }
+#endif
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_pwrite(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt,
+ __wasi_filesize_t offset, size_t *nwritten)
+{
+ if (iovcnt == 0)
+ return __WASI_EINVAL;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0)
+ return error;
+
+ ssize_t len;
+#if CONFIG_HAS_PWRITEV
+ len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt,
+ (off_t)offset);
+#else
+ if (iovcnt == 1) {
+ len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset);
+ }
+ else {
+ // Allocate a single buffer to fit all data.
+ size_t totalsize = 0;
+ for (size_t i = 0; i < iovcnt; ++i)
+ totalsize += iov[i].buf_len;
+ char *buf = wasm_runtime_malloc(totalsize);
+ if (buf == NULL) {
+ fd_object_release(fo);
+ return __WASI_ENOMEM;
+ }
+ size_t bufoff = 0;
+ for (size_t i = 0; i < iovcnt; ++i) {
+ bh_memcpy_s(buf + bufoff, totalsize - bufoff, iov[i].buf,
+ iov[i].buf_len);
+ bufoff += iov[i].buf_len;
+ }
+
+ // Perform a single write operation.
+ len = pwrite(fd_number(fo), buf, totalsize, offset);
+ wasm_runtime_free(buf);
+ }
+#endif
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nwritten = (size_t)len;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_read(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0);
+ if (error != 0)
+ return error;
+
+ ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt);
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nread = (size_t)len;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_renumber(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t from, __wasi_fd_t to)
+{
+ // Don't allow renumbering over a pre-opened resource.
+ // TODO: Eventually, we do want to permit this, once libpreopen in
+ // userspace is capable of removing entries from its tables as well.
+ {
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat);
+ if (error != 0) {
+ error = fd_prestats_get_entry(prestats, from, &prestat);
+ }
+ rwlock_unlock(&prestats->lock);
+ if (error == 0) {
+ return __WASI_ENOTSUP;
+ }
+ }
+
+ struct fd_table *ft = curfds;
+ rwlock_wrlock(&ft->lock);
+ struct fd_entry *fe_from;
+ __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+ struct fd_entry *fe_to;
+ error = fd_table_get_entry(ft, to, 0, 0, &fe_to);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ struct fd_object *fo;
+ fd_table_detach(ft, to, &fo);
+ refcount_acquire(&fe_from->object->refcount);
+ fd_table_attach(ft, to, fe_from->object, fe_from->rights_base,
+ fe_from->rights_inheriting);
+ fd_object_release(fo);
+
+ // Remove the old fd from the file descriptor table.
+ fd_table_detach(ft, from, &fo);
+ fd_object_release(fo);
+ --ft->used;
+
+ rwlock_unlock(&ft->lock);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_seek(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence,
+ __wasi_filesize_t *newoffset)
+{
+ int nwhence;
+ switch (whence) {
+ case __WASI_WHENCE_CUR:
+ nwhence = SEEK_CUR;
+ break;
+ case __WASI_WHENCE_END:
+ nwhence = SEEK_END;
+ break;
+ case __WASI_WHENCE_SET:
+ nwhence = SEEK_SET;
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd,
+ offset == 0 && whence == __WASI_WHENCE_CUR
+ ? __WASI_RIGHT_FD_TELL
+ : __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_TELL,
+ 0);
+ if (error != 0)
+ return error;
+
+ off_t ret = lseek(fd_number(fo), offset, nwhence);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ *newoffset = (__wasi_filesize_t)ret;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_tell(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t *newoffset)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_TELL, 0);
+ if (error != 0)
+ return error;
+
+ off_t ret = lseek(fd_number(fo), 0, SEEK_CUR);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ *newoffset = (__wasi_filesize_t)ret;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_fdstat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdstat_t *buf)
+{
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ // Extract file descriptor type and rights.
+ struct fd_object *fo = fe->object;
+ *buf = (__wasi_fdstat_t){
+ .fs_filetype = fo->type,
+ .fs_rights_base = fe->rights_base,
+ .fs_rights_inheriting = fe->rights_inheriting,
+ };
+
+ // Fetch file descriptor flags.
+ int ret;
+ switch (fo->type) {
+ default:
+ ret = fcntl(fd_number(fo), F_GETFL);
+ break;
+ }
+ rwlock_unlock(&ft->lock);
+ if (ret < 0)
+ return convert_errno(errno);
+
+ if ((ret & O_APPEND) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_APPEND;
+#ifdef O_DSYNC
+ if ((ret & O_DSYNC) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_DSYNC;
+#endif
+ if ((ret & O_NONBLOCK) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_NONBLOCK;
+#ifdef O_RSYNC
+ if ((ret & O_RSYNC) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_RSYNC;
+#endif
+ if ((ret & O_SYNC) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_SYNC;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_fdstat_set_flags(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdflags_t fs_flags)
+{
+ int noflags = 0;
+ if ((fs_flags & __WASI_FDFLAG_APPEND) != 0)
+ noflags |= O_APPEND;
+ if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0)
+#ifdef O_DSYNC
+ noflags |= O_DSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0)
+ noflags |= O_NONBLOCK;
+ if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0)
+#ifdef O_RSYNC
+ noflags |= O_RSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ if ((fs_flags & __WASI_FDFLAG_SYNC) != 0)
+ noflags |= O_SYNC;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS, 0);
+ if (error != 0)
+ return error;
+
+ int ret = fcntl(fd_number(fo), F_SETFL, noflags);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_fdstat_set_rights(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting)
+{
+ struct fd_table *ft = curfds;
+ rwlock_wrlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error =
+ fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ // Restrict the rights on the file descriptor.
+ fe->rights_base = fs_rights_base;
+ fe->rights_inheriting = fs_rights_inheriting;
+ rwlock_unlock(&ft->lock);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_sync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_SYNC, 0);
+ if (error != 0)
+ return error;
+
+ int ret = fsync(fd_number(fo));
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_write(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0)
+ return error;
+
+#ifndef BH_VPRINTF
+ ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt);
+#else
+ ssize_t len = 0;
+ /* redirect stdout/stderr output to BH_VPRINTF function */
+ if (fd_number(fo) == 1 || fd_number(fo) == 2) {
+ int i;
+ const struct iovec *iov1 = (const struct iovec *)iov;
+
+ for (i = 0; i < (int)iovcnt; i++, iov1++) {
+ if (iov1->iov_len > 0 && iov1->iov_base) {
+ char format[16];
+
+ /* make up format string "%.ns" */
+ snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len);
+ len += (ssize_t)os_printf(format, iov1->iov_base);
+ }
+ }
+ }
+ else {
+ len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt);
+ }
+#endif /* end of BH_VPRINTF */
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nwritten = (size_t)len;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_advise(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len,
+ __wasi_advice_t advice)
+{
+#ifdef POSIX_FADV_NORMAL
+ int nadvice;
+ switch (advice) {
+ case __WASI_ADVICE_DONTNEED:
+ nadvice = POSIX_FADV_DONTNEED;
+ break;
+ case __WASI_ADVICE_NOREUSE:
+ nadvice = POSIX_FADV_NOREUSE;
+ break;
+ case __WASI_ADVICE_NORMAL:
+ nadvice = POSIX_FADV_NORMAL;
+ break;
+ case __WASI_ADVICE_RANDOM:
+ nadvice = POSIX_FADV_RANDOM;
+ break;
+ case __WASI_ADVICE_SEQUENTIAL:
+ nadvice = POSIX_FADV_SEQUENTIAL;
+ break;
+ case __WASI_ADVICE_WILLNEED:
+ nadvice = POSIX_FADV_WILLNEED;
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ADVISE, 0);
+ if (error != 0)
+ return error;
+
+ int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice);
+ fd_object_release(fo);
+ if (ret != 0)
+ return convert_errno(ret);
+ return 0;
+#else
+ // Advisory information can safely be ignored if unsupported.
+ switch (advice) {
+ case __WASI_ADVICE_DONTNEED:
+ case __WASI_ADVICE_NOREUSE:
+ case __WASI_ADVICE_NORMAL:
+ case __WASI_ADVICE_RANDOM:
+ case __WASI_ADVICE_SEQUENTIAL:
+ case __WASI_ADVICE_WILLNEED:
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+
+ // At least check for file descriptor existence.
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error =
+ fd_table_get_entry(ft, fd, __WASI_RIGHT_FD_ADVISE, 0, &fe);
+ rwlock_unlock(&ft->lock);
+ return error;
+#endif
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_allocate(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0);
+ if (error != 0)
+ return error;
+
+#if CONFIG_HAS_POSIX_FALLOCATE
+ int ret = posix_fallocate(fd_number(fo), (off_t)offset, (off_t)len);
+#else
+ // At least ensure that the file is grown to the right size.
+ // TODO(ed): See if this can somehow be implemented without any race
+ // conditions. We may end up shrinking the file right now.
+ struct stat sb;
+ int ret = fstat(fd_number(fo), &sb);
+ off_t newsize = (off_t)(offset + len);
+ if (ret == 0 && sb.st_size < newsize)
+ ret = ftruncate(fd_number(fo), newsize);
+#endif
+
+ fd_object_release(fo);
+ if (ret != 0)
+ return convert_errno(ret);
+ return 0;
+}
+
+// Reads the entire contents of a symbolic link, returning the contents
+// in an allocated buffer. The allocated buffer is large enough to fit
+// at least one extra byte, so the caller may append a trailing slash to
+// it. This is needed by path_get().
+static char *
+readlinkat_dup(int fd, const char *path, size_t *p_len)
+{
+ char *buf = NULL;
+ size_t len = 32;
+ size_t len_org = len;
+
+ for (;;) {
+ char *newbuf = wasm_runtime_malloc((uint32)len);
+
+ if (newbuf == NULL) {
+ if (buf)
+ wasm_runtime_free(buf);
+ return NULL;
+ }
+
+ if (buf != NULL) {
+ bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org);
+ wasm_runtime_free(buf);
+ }
+
+ buf = newbuf;
+ ssize_t ret = readlinkat(fd, path, buf, len);
+ if (ret < 0) {
+ wasm_runtime_free(buf);
+ return NULL;
+ }
+ if ((size_t)ret + 1 < len) {
+ buf[ret] = '\0';
+ *p_len = len;
+ return buf;
+ }
+ len_org = len;
+ len *= 2;
+ }
+}
+
+// Lease to a directory, so a path underneath it can be accessed.
+//
+// This structure is used by system calls that operate on pathnames. In
+// this environment, pathnames always consist of a pair of a file
+// descriptor representing the directory where the lookup needs to start
+// and the actual pathname string.
+struct path_access {
+ int fd; // Directory file descriptor.
+ const char *path; // Pathname.
+ bool follow; // Whether symbolic links should be followed.
+ char *path_start; // Internal: pathname to free.
+ struct fd_object *fd_object; // Internal: directory file descriptor object.
+};
+
+// Creates a lease to a file descriptor and pathname pair. If the
+// operating system does not implement Capsicum, it also normalizes the
+// pathname to ensure the target path is placed underneath the
+// directory.
+static __wasi_errno_t
+path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd,
+ __wasi_lookupflags_t flags, const char *upath, size_t upathlen,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting,
+ bool needs_final_component)
+ TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount)
+{
+ char *path = str_nullterminate(upath, upathlen);
+ if (path == NULL)
+ return convert_errno(errno);
+
+ // Fetch the directory file descriptor.
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting);
+ if (error != 0) {
+ wasm_runtime_free(path);
+ return error;
+ }
+
+#if CONFIG_HAS_CAP_ENTER
+ // Rely on the kernel to constrain access to automatically constrain
+ // access to files stored underneath this directory.
+ pa->fd = fd_number(fo);
+ pa->path = pa->path_start = path;
+ pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0;
+ pa->fd_object = fo;
+ return 0;
+#else
+ // The implementation provides no mechanism to constrain lookups to a
+ // directory automatically. Emulate this logic by resolving the
+ // pathname manually.
+
+ // Stack of directory file descriptors. Index 0 always corresponds
+ // with the directory provided to this function. Entering a directory
+ // causes a file descriptor to be pushed, while handling ".." entries
+ // causes an entry to be popped. Index 0 cannot be popped, as this
+ // would imply escaping the base directory.
+ int fds[128];
+ fds[0] = fd_number(fo);
+ size_t curfd = 0;
+
+ // Stack of pathname strings used for symlink expansion. By using a
+ // stack, there is no need to concatenate any pathname strings while
+ // expanding symlinks.
+ char *paths[32];
+ char *paths_start[32];
+ paths[0] = paths_start[0] = path;
+ size_t curpath = 0;
+ size_t expansions = 0;
+ char *symlink;
+ size_t symlink_len;
+
+ for (;;) {
+ // Extract the next pathname component from 'paths[curpath]', null
+ // terminate it and store it in 'file'. 'ends_with_slashes' stores
+ // whether the pathname component is followed by one or more
+ // trailing slashes, as this requires it to be a directory.
+ char *file = paths[curpath];
+ char *file_end = file + strcspn(file, "/");
+ paths[curpath] = file_end + strspn(file_end, "/");
+ bool ends_with_slashes = *file_end == '/';
+ *file_end = '\0';
+
+ // Test for empty pathname strings and absolute paths.
+ if (file == file_end) {
+ error = ends_with_slashes ? __WASI_ENOTCAPABLE : __WASI_ENOENT;
+ goto fail;
+ }
+
+ if (strcmp(file, ".") == 0) {
+ // Skip component.
+ }
+ else if (strcmp(file, "..") == 0) {
+ // Pop a directory off the stack.
+ if (curfd == 0) {
+ // Attempted to go to parent directory of the directory file
+ // descriptor.
+ error = __WASI_ENOTCAPABLE;
+ goto fail;
+ }
+ close(fds[curfd--]);
+ }
+ else if (curpath > 0 || *paths[curpath] != '\0'
+ || (ends_with_slashes && !needs_final_component)) {
+ // A pathname component whose name we're not interested in that is
+ // followed by a slash or is followed by other pathname
+ // components. In other words, a pathname component that must be a
+ // directory. First attempt to obtain a directory file descriptor
+ // for it.
+ int newdir =
+#ifdef O_SEARCH
+ openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW);
+#else
+ openat(fds[curfd], file, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
+#endif
+ if (newdir != -1) {
+ // Success. Push it onto the directory stack.
+ if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) {
+ close(newdir);
+ error = __WASI_ENAMETOOLONG;
+ goto fail;
+ }
+ fds[++curfd] = newdir;
+ }
+ else {
+ // Failed to open it. Attempt symlink expansion.
+ if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) {
+ error = convert_errno(errno);
+ goto fail;
+ }
+ symlink = readlinkat_dup(fds[curfd], file, &symlink_len);
+ if (symlink != NULL)
+ goto push_symlink;
+
+ // readlink returns EINVAL if the path isn't a symlink. In that
+ // case, it's more informative to return ENOTDIR.
+ if (errno == EINVAL)
+ errno = ENOTDIR;
+
+ error = convert_errno(errno);
+ goto fail;
+ }
+ }
+ else {
+ // The final pathname component. Depending on whether it ends with
+ // a slash or the symlink-follow flag is set, perform symlink
+ // expansion.
+ if (ends_with_slashes
+ || (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) {
+ symlink = readlinkat_dup(fds[curfd], file, &symlink_len);
+ if (symlink != NULL)
+ goto push_symlink;
+ if (errno != EINVAL && errno != ENOENT) {
+ error = convert_errno(errno);
+ goto fail;
+ }
+ }
+
+ // Not a symlink, meaning we're done. Return the filename,
+ // together with the directory containing this file.
+ //
+ // If the file was followed by a trailing slash, we must retain
+ // it, to ensure system calls properly return ENOTDIR.
+ // Unfortunately, this opens up a race condition, because this
+ // means that users of path_get() will perform symlink expansion a
+ // second time. There is nothing we can do to mitigate this, as
+ // far as I know.
+ if (ends_with_slashes)
+ *file_end = '/';
+ pa->path = file;
+ pa->path_start = paths_start[0];
+ goto success;
+ }
+
+ if (*paths[curpath] == '\0') {
+ if (curpath == 0) {
+ // No further pathname components to process. We may end up here
+ // when called on paths like ".", "a/..", but also if the path
+ // had trailing slashes and the caller is not interested in the
+ // name of the pathname component.
+ wasm_runtime_free(paths_start[0]);
+ pa->path = ".";
+ pa->path_start = NULL;
+ goto success;
+ }
+
+ // Finished expanding symlink. Continue processing along the
+ // original path.
+ wasm_runtime_free(paths_start[curpath--]);
+ }
+ continue;
+
+ push_symlink:
+ // Prevent infinite loops by placing an upper limit on the number of
+ // symlink expansions.
+ if (++expansions == 128) {
+ wasm_runtime_free(symlink);
+ error = __WASI_ELOOP;
+ goto fail;
+ }
+
+ if (*paths[curpath] == '\0') {
+ // The original path already finished processing. Replace it by
+ // this symlink entirely.
+ wasm_runtime_free(paths_start[curpath]);
+ }
+ else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) {
+ // Too many nested symlinks. Stop processing.
+ wasm_runtime_free(symlink);
+ error = __WASI_ELOOP;
+ goto fail;
+ }
+ else {
+ // The original path still has components left. Retain the
+ // components that remain, so we can process them afterwards.
+ ++curpath;
+ }
+
+ // Append a trailing slash to the symlink if the path leading up to
+ // it also contained one. Otherwise we would not throw ENOTDIR if
+ // the target is not a directory.
+ if (ends_with_slashes)
+ bh_strcat_s(symlink, (uint32)symlink_len, "/");
+ paths[curpath] = paths_start[curpath] = symlink;
+ }
+
+success:
+ // Return the lease. Close all directories, except the one the caller
+ // needs to use.
+ for (size_t i = 1; i < curfd; ++i)
+ close(fds[i]);
+ pa->fd = fds[curfd];
+ pa->follow = false;
+ pa->fd_object = fo;
+ return 0;
+
+fail:
+ // Failure. Free all resources.
+ for (size_t i = 1; i <= curfd; ++i)
+ close(fds[i]);
+ for (size_t i = 0; i <= curpath; ++i)
+ wasm_runtime_free(paths_start[i]);
+ fd_object_release(fo);
+ return error;
+#endif
+}
+
+static __wasi_errno_t
+path_get_nofollow(struct fd_table *curfds, struct path_access *pa,
+ __wasi_fd_t fd, const char *path, size_t pathlen,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting, bool needs_final_component)
+ TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount)
+{
+ __wasi_lookupflags_t flags = 0;
+ return path_get(curfds, pa, fd, flags, path, pathlen, rights_base,
+ rights_inheriting, needs_final_component);
+}
+
+static void
+path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount)
+{
+ if (pa->path_start)
+ wasm_runtime_free(pa->path_start);
+ if (fd_number(pa->fd_object) != pa->fd)
+ close(pa->fd);
+ fd_object_release(pa->fd_object);
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_create_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen)
+{
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &pa, fd, path, pathlen,
+ __WASI_RIGHT_PATH_CREATE_DIRECTORY, 0, true);
+ if (error != 0)
+ return error;
+
+ int ret = mkdirat(pa.fd, pa.path, 0777);
+ path_put(&pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+static bool
+validate_path(const char *path, struct fd_prestats *pt)
+{
+ size_t i;
+ char path_resolved[PATH_MAX], prestat_dir_resolved[PATH_MAX];
+ char *path_real, *prestat_dir_real;
+
+ if (!(path_real = realpath(path, path_resolved)))
+ /* path doesn't exist, creating a link to this file
+ is allowed: if this file is to be created in
+ the future, WASI will strictly check whether it
+ can be created or not. */
+ return true;
+
+ for (i = 0; i < pt->size; i++) {
+ if (pt->prestats[i].dir) {
+ if (!(prestat_dir_real =
+ realpath(pt->prestats[i].dir, prestat_dir_resolved)))
+ return false;
+ if (!strncmp(path_real, prestat_dir_real, strlen(prestat_dir_real)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_link(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, const char *old_path,
+ size_t old_path_len, __wasi_fd_t new_fd, const char *new_path,
+ size_t new_path_len)
+{
+ struct path_access old_pa;
+ __wasi_errno_t error =
+ path_get(curfds, &old_pa, old_fd, old_flags, old_path, old_path_len,
+ __WASI_RIGHT_PATH_LINK_SOURCE, 0, false);
+ if (error != 0)
+ return error;
+
+ struct path_access new_pa;
+ error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len,
+ __WASI_RIGHT_PATH_LINK_TARGET, 0, true);
+ if (error != 0) {
+ path_put(&old_pa);
+ return error;
+ }
+
+ rwlock_rdlock(&prestats->lock);
+ if (!validate_path(old_pa.path, prestats)
+ || !validate_path(new_pa.path, prestats)) {
+ rwlock_unlock(&prestats->lock);
+ return __WASI_EBADF;
+ }
+ rwlock_unlock(&prestats->lock);
+
+ int ret = linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path,
+ old_pa.follow ? AT_SYMLINK_FOLLOW : 0);
+ if (ret < 0 && errno == ENOTSUP && !old_pa.follow) {
+ // OS X doesn't allow creating hardlinks to symbolic links.
+ // Duplicate the symbolic link instead.
+ size_t target_len;
+ char *target = readlinkat_dup(old_pa.fd, old_pa.path, &target_len);
+ if (target != NULL) {
+ bh_assert(target[target_len] == '\0');
+ rwlock_rdlock(&prestats->lock);
+ if (!validate_path(target, prestats)) {
+ rwlock_unlock(&prestats->lock);
+ wasm_runtime_free(target);
+ return __WASI_EBADF;
+ }
+ rwlock_unlock(&prestats->lock);
+ ret = symlinkat(target, new_pa.fd, new_pa.path);
+ wasm_runtime_free(target);
+ }
+ }
+ path_put(&old_pa);
+ path_put(&new_pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path,
+ size_t pathlen, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags,
+ __wasi_fd_t *fd)
+{
+ // Rights that should be installed on the new file descriptor.
+ __wasi_rights_t rights_base = fs_rights_base;
+ __wasi_rights_t rights_inheriting = fs_rights_inheriting;
+
+ // Which open() mode should be used to satisfy the needed rights.
+ bool read =
+ (rights_base & (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_READDIR)) != 0;
+ bool write =
+ (rights_base
+ & (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE
+ | __WASI_RIGHT_FD_ALLOCATE | __WASI_RIGHT_FD_FILESTAT_SET_SIZE))
+ != 0;
+ int noflags = write ? read ? O_RDWR : O_WRONLY : O_RDONLY;
+
+ // Which rights are needed on the directory file descriptor.
+ __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN;
+ __wasi_rights_t needed_inheriting = rights_base | rights_inheriting;
+
+ // Convert open flags.
+ if ((oflags & __WASI_O_CREAT) != 0) {
+ noflags |= O_CREAT;
+ needed_base |= __WASI_RIGHT_PATH_CREATE_FILE;
+ }
+ if ((oflags & __WASI_O_DIRECTORY) != 0)
+ noflags |= O_DIRECTORY;
+ if ((oflags & __WASI_O_EXCL) != 0)
+ noflags |= O_EXCL;
+ if ((oflags & __WASI_O_TRUNC) != 0) {
+ noflags |= O_TRUNC;
+ needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE;
+ }
+
+ // Convert file descriptor flags.
+ if ((fs_flags & __WASI_FDFLAG_APPEND) != 0)
+ noflags |= O_APPEND;
+ if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) {
+#ifdef O_DSYNC
+ noflags |= O_DSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ needed_inheriting |= __WASI_RIGHT_FD_DATASYNC;
+ }
+ if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0)
+ noflags |= O_NONBLOCK;
+ if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) {
+#ifdef O_RSYNC
+ noflags |= O_RSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ needed_inheriting |= __WASI_RIGHT_FD_SYNC;
+ }
+ if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) {
+ noflags |= O_SYNC;
+ needed_inheriting |= __WASI_RIGHT_FD_SYNC;
+ }
+ if (write && (noflags & (O_APPEND | O_TRUNC)) == 0)
+ needed_inheriting |= __WASI_RIGHT_FD_SEEK;
+
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get(curfds, &pa, dirfd, dirflags, path, pathlen, needed_base,
+ needed_inheriting, (oflags & __WASI_O_CREAT) != 0);
+ if (error != 0)
+ return error;
+ if (!pa.follow)
+ noflags |= O_NOFOLLOW;
+
+ int nfd = openat(pa.fd, pa.path, noflags, 0666);
+ if (nfd < 0) {
+ int openat_errno = errno;
+ // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket.
+ if (openat_errno == ENXIO) {
+ struct stat sb;
+ int ret = fstatat(pa.fd, pa.path, &sb,
+ pa.follow ? 0 : AT_SYMLINK_NOFOLLOW);
+ path_put(&pa);
+ return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP
+ : __WASI_ENXIO;
+ }
+ // Linux returns ENOTDIR instead of ELOOP when using
+ // O_NOFOLLOW|O_DIRECTORY on a symlink.
+ if (openat_errno == ENOTDIR
+ && (noflags & (O_NOFOLLOW | O_DIRECTORY)) != 0) {
+ struct stat sb;
+ int ret = fstatat(pa.fd, pa.path, &sb, AT_SYMLINK_NOFOLLOW);
+ if (S_ISLNK(sb.st_mode)) {
+ path_put(&pa);
+ return __WASI_ELOOP;
+ }
+ (void)ret;
+ }
+ path_put(&pa);
+ // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
+ // a symlink.
+ if (!pa.follow && openat_errno == EMLINK)
+ return __WASI_ELOOP;
+ return convert_errno(openat_errno);
+ }
+ path_put(&pa);
+
+ // Determine the type of the new file descriptor and which rights
+ // contradict with this type.
+ __wasi_filetype_t type;
+ __wasi_rights_t max_base, max_inheriting;
+ error = fd_determine_type_rights(nfd, &type, &max_base, &max_inheriting);
+ if (error != 0) {
+ close(nfd);
+ return error;
+ }
+
+ {
+ struct stat sb;
+
+ if (fstat(nfd, &sb) < 0) {
+ close(nfd);
+ return convert_errno(errno);
+ }
+
+ if (S_ISDIR(sb.st_mode))
+ rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE;
+ else if (S_ISREG(sb.st_mode))
+ rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE;
+ }
+
+ return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base,
+ rights_inheriting & max_inheriting, fd);
+}
+
+// Copies out directory entry metadata or filename, potentially
+// truncating it in the process.
+static void
+fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem,
+ size_t elemsize)
+{
+ size_t bufavail = bufsize - *bufused;
+ if (elemsize > bufavail)
+ elemsize = bufavail;
+ bh_memcpy_s((char *)buf + *bufused, (uint32)bufavail, elem,
+ (uint32)elemsize);
+ *bufused += elemsize;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_readdir(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie,
+ size_t *bufused)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ // Create a directory handle if none has been opened yet.
+ mutex_lock(&fo->directory.lock);
+ DIR *dp = fo->directory.handle;
+ if (dp == NULL) {
+ dp = fdopendir(fd_number(fo));
+ if (dp == NULL) {
+ mutex_unlock(&fo->directory.lock);
+ fd_object_release(fo);
+ return convert_errno(errno);
+ }
+ fo->directory.handle = dp;
+ fo->directory.offset = __WASI_DIRCOOKIE_START;
+ }
+
+ // Seek to the right position if the requested offset does not match
+ // the current offset.
+ if (fo->directory.offset != cookie) {
+ if (cookie == __WASI_DIRCOOKIE_START)
+ rewinddir(dp);
+ else
+ seekdir(dp, (long)cookie);
+ fo->directory.offset = cookie;
+ }
+
+ *bufused = 0;
+ while (*bufused < nbyte) {
+ // Read the next directory entry.
+ errno = 0;
+ struct dirent *de = readdir(dp);
+ if (de == NULL) {
+ mutex_unlock(&fo->directory.lock);
+ fd_object_release(fo);
+ return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno);
+ }
+ fo->directory.offset = (__wasi_dircookie_t)telldir(dp);
+
+ // Craft a directory entry and copy that back.
+ size_t namlen = strlen(de->d_name);
+ __wasi_dirent_t cde = {
+ .d_next = fo->directory.offset,
+#if CONFIG_HAS_D_INO
+ .d_ino = de->d_ino,
+#else
+ .d_ino = 0,
+#endif
+ .d_namlen = (uint32)namlen,
+ };
+ switch (de->d_type) {
+ case DT_BLK:
+ cde.d_type = __WASI_FILETYPE_BLOCK_DEVICE;
+ break;
+ case DT_CHR:
+ cde.d_type = __WASI_FILETYPE_CHARACTER_DEVICE;
+ break;
+ case DT_DIR:
+ cde.d_type = __WASI_FILETYPE_DIRECTORY;
+ break;
+ case DT_FIFO:
+ cde.d_type = __WASI_FILETYPE_SOCKET_STREAM;
+ break;
+ case DT_LNK:
+ cde.d_type = __WASI_FILETYPE_SYMBOLIC_LINK;
+ break;
+ case DT_REG:
+ cde.d_type = __WASI_FILETYPE_REGULAR_FILE;
+ break;
+#ifdef DT_SOCK
+ case DT_SOCK:
+ // Technically not correct, but good enough.
+ cde.d_type = __WASI_FILETYPE_SOCKET_STREAM;
+ break;
+#endif
+ default:
+ cde.d_type = __WASI_FILETYPE_UNKNOWN;
+ break;
+ }
+ fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde));
+ fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen);
+ }
+ mutex_unlock(&fo->directory.lock);
+ fd_object_release(fo);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_readlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize,
+ size_t *bufused)
+{
+ struct path_access pa;
+ __wasi_errno_t error = path_get_nofollow(
+ curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_READLINK, 0, false);
+ if (error != 0)
+ return error;
+
+ // Linux requires that the buffer size is positive. whereas POSIX does
+ // not. Use a fake buffer to store the results if the size is zero.
+ char fakebuf[1];
+ ssize_t len = readlinkat(pa.fd, pa.path, bufsize == 0 ? fakebuf : buf,
+ bufsize == 0 ? sizeof(fakebuf) : bufsize);
+ path_put(&pa);
+ if (len < 0)
+ return convert_errno(errno);
+ *bufused = (size_t)len < bufsize ? (size_t)len : bufsize;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_rename(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t old_fd, const char *old_path, size_t old_path_len,
+ __wasi_fd_t new_fd, const char *new_path, size_t new_path_len)
+{
+ struct path_access old_pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &old_pa, old_fd, old_path, old_path_len,
+ __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true);
+ if (error != 0)
+ return error;
+
+ struct path_access new_pa;
+ error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len,
+ __WASI_RIGHT_PATH_RENAME_TARGET, 0, true);
+ if (error != 0) {
+ path_put(&old_pa);
+ return error;
+ }
+
+ int ret = renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path);
+ path_put(&old_pa);
+ path_put(&new_pa);
+ if (ret < 0) {
+ return convert_errno(errno);
+ }
+ return 0;
+}
+
+// Converts a POSIX stat structure to a CloudABI filestat structure.
+static void
+convert_stat(const struct stat *in, __wasi_filestat_t *out)
+{
+ *out = (__wasi_filestat_t){
+ .st_dev = in->st_dev,
+ .st_ino = in->st_ino,
+ .st_nlink = (__wasi_linkcount_t)in->st_nlink,
+ .st_size = (__wasi_filesize_t)in->st_size,
+ .st_atim = convert_timespec(&in->st_atim),
+ .st_mtim = convert_timespec(&in->st_mtim),
+ .st_ctim = convert_timespec(&in->st_ctim),
+ };
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filestat_t *buf)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_GET, 0);
+ if (error != 0)
+ return error;
+
+ int ret;
+ switch (fo->type) {
+ default:
+ {
+ struct stat sb;
+ ret = fstat(fd_number(fo), &sb);
+ convert_stat(&sb, buf);
+ break;
+ }
+ }
+ buf->st_filetype = fo->type;
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+static void
+convert_timestamp(__wasi_timestamp_t in, struct timespec *out)
+{
+ // Store sub-second remainder.
+#if defined(__SYSCALL_SLONG_TYPE)
+ out->tv_nsec = (__SYSCALL_SLONG_TYPE)(in % 1000000000);
+#else
+ out->tv_nsec = (long)(in % 1000000000);
+#endif
+ in /= 1000000000;
+
+ // Clamp to the maximum in case it would overflow our system's time_t.
+ out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX;
+}
+
+// Converts the provided timestamps and flags to a set of arguments for
+// futimens() and utimensat().
+static void
+convert_utimens_arguments(__wasi_timestamp_t st_atim,
+ __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags, struct timespec *ts)
+{
+ if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) {
+ ts[0].tv_nsec = UTIME_NOW;
+ }
+ else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) {
+ convert_timestamp(st_atim, &ts[0]);
+ }
+ else {
+ ts[0].tv_nsec = UTIME_OMIT;
+ }
+
+ if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) {
+ ts[1].tv_nsec = UTIME_NOW;
+ }
+ else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) {
+ convert_timestamp(st_mtim, &ts[1]);
+ }
+ else {
+ ts[1].tv_nsec = UTIME_OMIT;
+ }
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_filestat_set_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t st_size)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_SIZE, 0);
+ if (error != 0)
+ return error;
+
+ int ret = ftruncate(fd_number(fo), (off_t)st_size);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags)
+{
+ if ((fstflags
+ & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW
+ | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW))
+ != 0)
+ return __WASI_EINVAL;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_TIMES, 0);
+ if (error != 0)
+ return error;
+
+ struct timespec ts[2];
+ convert_utimens_arguments(st_atim, st_mtim, fstflags, ts);
+ int ret = futimens(fd_number(fo), ts);
+
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path,
+ size_t pathlen, __wasi_filestat_t *buf)
+{
+ struct path_access pa;
+ __wasi_errno_t error = path_get(curfds, &pa, fd, flags, path, pathlen,
+ __WASI_RIGHT_PATH_FILESTAT_GET, 0, false);
+ if (error != 0)
+ return error;
+
+ struct stat sb;
+ int ret = fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW);
+ path_put(&pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ convert_stat(&sb, buf);
+
+ // Convert the file type. In the case of sockets there is no way we
+ // can easily determine the exact socket type.
+ if (S_ISBLK(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE;
+ else if (S_ISCHR(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE;
+ else if (S_ISDIR(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_DIRECTORY;
+ else if (S_ISFIFO(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM;
+ else if (S_ISLNK(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK;
+ else if (S_ISREG(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_REGULAR_FILE;
+ else if (S_ISSOCK(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path,
+ size_t pathlen, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags)
+{
+ if (((fstflags
+ & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW
+ | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW))
+ != 0)
+ /* ATIM & ATIM_NOW can't be set at the same time */
+ || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0
+ && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0)
+ /* MTIM & MTIM_NOW can't be set at the same time */
+ || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0
+ && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0))
+ return __WASI_EINVAL;
+
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get(curfds, &pa, fd, flags, path, pathlen,
+ __WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0, false);
+ if (error != 0)
+ return error;
+
+ struct timespec ts[2];
+ convert_utimens_arguments(st_atim, st_mtim, fstflags, ts);
+ int ret =
+ utimensat(pa.fd, pa.path, ts, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW);
+
+ path_put(&pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_symlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ const char *old_path, size_t old_path_len, __wasi_fd_t fd,
+ const char *new_path, size_t new_path_len)
+{
+ char *target = str_nullterminate(old_path, old_path_len);
+ if (target == NULL)
+ return convert_errno(errno);
+
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &pa, fd, new_path, new_path_len,
+ __WASI_RIGHT_PATH_SYMLINK, 0, true);
+ if (error != 0) {
+ wasm_runtime_free(target);
+ return error;
+ }
+
+ rwlock_rdlock(&prestats->lock);
+ if (!validate_path(target, prestats)) {
+ rwlock_unlock(&prestats->lock);
+ wasm_runtime_free(target);
+ return __WASI_EBADF;
+ }
+ rwlock_unlock(&prestats->lock);
+
+ int ret = symlinkat(target, pa.fd, pa.path);
+ path_put(&pa);
+ wasm_runtime_free(target);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_unlink_file(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen)
+{
+ struct path_access pa;
+ __wasi_errno_t error = path_get_nofollow(
+ curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_UNLINK_FILE, 0, true);
+ if (error != 0)
+ return error;
+
+ int ret = unlinkat(pa.fd, pa.path, 0);
+#ifndef __linux__
+ // Non-Linux implementations may return EPERM when attempting to remove a
+ // directory without REMOVEDIR. While that's what POSIX specifies, it's
+ // less useful. Adjust this to EISDIR. It doesn't matter that this is not
+ // atomic with the unlinkat, because if the file is removed and a directory
+ // is created before fstatat sees it, we're racing with that change anyway
+ // and unlinkat could have legitimately seen the directory if the race had
+ // turned out differently.
+ if (ret < 0 && errno == EPERM) {
+ struct stat statbuf;
+ if (fstatat(pa.fd, pa.path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0
+ && S_ISDIR(statbuf.st_mode)) {
+ errno = EISDIR;
+ }
+ }
+#endif
+ path_put(&pa);
+ if (ret < 0) {
+ return convert_errno(errno);
+ }
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_remove_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen)
+{
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &pa, fd, path, pathlen,
+ __WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0, true);
+ if (error != 0)
+ return error;
+
+ int ret = unlinkat(pa.fd, pa.path, AT_REMOVEDIR);
+#ifndef __linux__
+ // POSIX permits either EEXIST or ENOTEMPTY when the directory is not empty.
+ // Map it to ENOTEMPTY.
+ if (ret < 0 && errno == EEXIST) {
+ errno = ENOTEMPTY;
+ }
+#endif
+ path_put(&pa);
+ if (ret < 0) {
+ return convert_errno(errno);
+ }
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_poll_oneoff(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions,
+ size_t *nevents) NO_LOCK_ANALYSIS
+{
+ // Sleeping.
+ if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) {
+ out[0] = (__wasi_event_t){
+ .userdata = in[0].userdata,
+ .type = in[0].u.type,
+ };
+#if CONFIG_HAS_CLOCK_NANOSLEEP
+ clockid_t clock_id;
+ if (convert_clockid(in[0].u.u.clock.clock_id, &clock_id)) {
+ struct timespec ts;
+ convert_timestamp(in[0].u.u.clock.timeout, &ts);
+ int ret = clock_nanosleep(
+ clock_id,
+ (in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0
+ ? TIMER_ABSTIME
+ : 0,
+ &ts, NULL);
+ if (ret != 0)
+ out[0].error = convert_errno(ret);
+ }
+ else {
+ out[0].error = __WASI_ENOTSUP;
+ }
+#else
+ switch (in[0].u.u.clock.clock_id) {
+ case __WASI_CLOCK_MONOTONIC:
+ if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME)
+ != 0) {
+ // TODO(ed): Implement.
+ fputs("Unimplemented absolute sleep on monotonic clock\n",
+ stderr);
+ out[0].error = __WASI_ENOSYS;
+ }
+ else {
+ // Perform relative sleeps on the monotonic clock also using
+ // nanosleep(). This is incorrect, but good enough for now.
+ struct timespec ts;
+ convert_timestamp(in[0].u.u.clock.timeout, &ts);
+ nanosleep(&ts, NULL);
+ }
+ break;
+ case __WASI_CLOCK_REALTIME:
+ if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME)
+ != 0) {
+ // Sleeping to an absolute point in time can only be done
+ // by waiting on a condition variable.
+ struct mutex mutex;
+ struct cond cond;
+
+ if (!mutex_init(&mutex))
+ return -1;
+ if (!cond_init_realtime(&cond)) {
+ mutex_destroy(&mutex);
+ return -1;
+ }
+ mutex_lock(&mutex);
+ cond_timedwait(&cond, &mutex, in[0].u.u.clock.timeout,
+ true);
+ mutex_unlock(&mutex);
+ mutex_destroy(&mutex);
+ cond_destroy(&cond);
+ }
+ else {
+ // Relative sleeps can be done using nanosleep().
+ struct timespec ts;
+ convert_timestamp(in[0].u.u.clock.timeout, &ts);
+ nanosleep(&ts, NULL);
+ }
+ break;
+ default:
+ out[0].error = __WASI_ENOTSUP;
+ break;
+ }
+#endif
+ *nevents = 1;
+ if (out[0].error != 0)
+ return convert_errno(out[0].error);
+ return 0;
+ }
+
+ // Last option: call into poll(). This can only be done in case all
+ // subscriptions consist of __WASI_EVENTTYPE_FD_READ and
+ // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one
+ // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also
+ // the subscriptions generate by cloudlibc's poll() and select().
+ struct fd_object **fos =
+ wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos)));
+ if (fos == NULL)
+ return __WASI_ENOMEM;
+ struct pollfd *pfds =
+ wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds)));
+ if (pfds == NULL) {
+ wasm_runtime_free(fos);
+ return __WASI_ENOMEM;
+ }
+
+ // Convert subscriptions to pollfd entries. Increase the reference
+ // count on the file descriptors to ensure they remain valid across
+ // the call to poll().
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ *nevents = 0;
+ const __wasi_subscription_t *clock_subscription = NULL;
+ for (size_t i = 0; i < nsubscriptions; ++i) {
+ const __wasi_subscription_t *s = &in[i];
+ switch (s->u.type) {
+ case __WASI_EVENTTYPE_FD_READ:
+ case __WASI_EVENTTYPE_FD_WRITE:
+ {
+ __wasi_errno_t error =
+ fd_object_get_locked(&fos[i], ft, s->u.u.fd_readwrite.fd,
+ __WASI_RIGHT_POLL_FD_READWRITE, 0);
+ if (error == 0) {
+ // Proper file descriptor on which we can poll().
+ pfds[i] = (struct pollfd){
+ .fd = fd_number(fos[i]),
+ .events = s->u.type == __WASI_EVENTTYPE_FD_READ
+ ? POLLIN
+ : POLLOUT,
+ };
+ }
+ else {
+ // Invalid file descriptor or rights missing.
+ fos[i] = NULL;
+ pfds[i] = (struct pollfd){ .fd = -1 };
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = s->userdata,
+ .error = error,
+ .type = s->u.type,
+ };
+ }
+ break;
+ }
+ case __WASI_EVENTTYPE_CLOCK:
+ if (clock_subscription == NULL
+ && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME)
+ == 0) {
+ // Relative timeout.
+ fos[i] = NULL;
+ pfds[i] = (struct pollfd){ .fd = -1 };
+ clock_subscription = s;
+ break;
+ }
+ // Fallthrough.
+ default:
+ // Unsupported event.
+ fos[i] = NULL;
+ pfds[i] = (struct pollfd){ .fd = -1 };
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = s->userdata,
+ .error = __WASI_ENOSYS,
+ .type = s->u.type,
+ };
+ break;
+ }
+ }
+ rwlock_unlock(&ft->lock);
+
+ // Use a zero-second timeout in case we've already generated events in
+ // the loop above.
+ int timeout;
+ if (*nevents != 0) {
+ timeout = 0;
+ }
+ else if (clock_subscription != NULL) {
+ __wasi_timestamp_t ts = clock_subscription->u.u.clock.timeout / 1000000;
+ timeout = ts > INT_MAX ? -1 : (int)ts;
+ }
+ else {
+ timeout = -1;
+ }
+ int ret = poll(pfds, nsubscriptions, timeout);
+
+ __wasi_errno_t error = 0;
+ if (ret == -1) {
+ error = convert_errno(errno);
+ }
+ else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) {
+ // No events triggered. Trigger the clock event.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = clock_subscription->userdata,
+ .type = __WASI_EVENTTYPE_CLOCK,
+ };
+ }
+ else {
+ // Events got triggered. Don't trigger the clock event.
+ for (size_t i = 0; i < nsubscriptions; ++i) {
+ if (pfds[i].fd >= 0) {
+ __wasi_filesize_t nbytes = 0;
+ if (in[i].u.type == __WASI_EVENTTYPE_FD_READ) {
+ int l;
+ if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0)
+ nbytes = (__wasi_filesize_t)l;
+ }
+ if ((pfds[i].revents & POLLNVAL) != 0) {
+ // Bad file descriptor. This normally cannot occur, as
+ // referencing the file descriptor object will always ensure
+ // the descriptor is valid. Still, macOS may sometimes
+ // return this on FIFOs when reaching end-of-file.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+#ifdef __APPLE__
+ .u.fd_readwrite.nbytes = nbytes,
+ .u.fd_readwrite.flags =
+ __WASI_EVENT_FD_READWRITE_HANGUP,
+#else
+ .error = __WASI_EBADF,
+#endif
+ .type = in[i].u.type,
+ };
+ }
+ else if ((pfds[i].revents & POLLERR) != 0) {
+ // File descriptor is in an error state.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+ .error = __WASI_EIO,
+ .type = in[i].u.type,
+ };
+ }
+ else if ((pfds[i].revents & POLLHUP) != 0) {
+ // End-of-file.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+ .type = in[i].u.type,
+ .u.fd_readwrite.nbytes = nbytes,
+ .u.fd_readwrite.flags =
+ __WASI_EVENT_FD_READWRITE_HANGUP,
+ };
+ }
+ else if ((pfds[i].revents & (POLLIN | POLLOUT)) != 0) {
+ // Read or write possible.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+ .type = in[i].u.type,
+ .u.fd_readwrite.nbytes = nbytes,
+ };
+ }
+ }
+ }
+ }
+
+ for (size_t i = 0; i < nsubscriptions; ++i)
+ if (fos[i] != NULL)
+ fd_object_release(fos[i]);
+ wasm_runtime_free(fos);
+ wasm_runtime_free(pfds);
+ return error;
+}
+
+#if 0
+/**
+ * We throw exception in libc-wasi wrapper function wasi_proc_exit()
+ * but not call this function.
+ */
+void wasmtime_ssp_proc_exit(
+ __wasi_exitcode_t rval
+) {
+ _Exit((int32)rval);
+}
+#endif
+
+__wasi_errno_t
+wasmtime_ssp_proc_raise(__wasi_signal_t sig)
+{
+ static const int signals[] = {
+#define X(v) [__WASI_##v] = v
+#if defined(SIGABRT)
+ X(SIGABRT),
+#endif
+#if defined(SIGALRM)
+ X(SIGALRM),
+#endif
+#if defined(SIGBUS)
+ X(SIGBUS),
+#endif
+#if defined(SIGCHLD)
+ X(SIGCHLD),
+#endif
+#if defined(SIGCONT)
+ X(SIGCONT),
+#endif
+#if defined(SIGFPE)
+ X(SIGFPE),
+#endif
+#if defined(SIGHUP)
+ X(SIGHUP),
+#endif
+#if defined(SIGILL)
+ X(SIGILL),
+#endif
+#if defined(SIGINT)
+ X(SIGINT),
+#endif
+#if defined(SIGKILL)
+ X(SIGKILL),
+#endif
+#if defined(SIGPIPE)
+ X(SIGPIPE),
+#endif
+#if defined(SIGQUIT)
+ X(SIGQUIT),
+#endif
+#if defined(SIGSYS)
+ X(SIGSEGV),
+#endif
+#if defined(SIGSTOP)
+ X(SIGSTOP),
+#endif
+#if defined(SIGSYS)
+ X(SIGSYS),
+#endif
+#if defined(SIGTERM)
+ X(SIGTERM),
+#endif
+#if defined(SIGTRAP)
+ X(SIGTRAP),
+#endif
+#if defined(SIGTSTP)
+ X(SIGTSTP),
+#endif
+#if defined(SIGTTIN)
+ X(SIGTTIN),
+#endif
+#if defined(SIGTTOU)
+ X(SIGTTOU),
+#endif
+#if defined(SIGURG)
+ X(SIGURG),
+#endif
+#if defined(SIGUSR1)
+ X(SIGUSR1),
+#endif
+#if defined(SIGUSR2)
+ X(SIGUSR2),
+#endif
+#if defined(SIGVTALRM)
+ X(SIGVTALRM),
+#endif
+#if defined(SIGXCPU)
+ X(SIGXCPU),
+#endif
+#if defined(SIGXFSZ)
+ X(SIGXFSZ),
+#endif
+#undef X
+ };
+ if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0)
+ return __WASI_EINVAL;
+
+#if CONFIG_TLS_USE_GSBASE
+ // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV
+ // to the default action before raising.
+ if (sig == __WASI_SIGSEGV) {
+ struct sigaction sa = {
+ .sa_handler = SIG_DFL,
+ };
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGSEGV, &sa, NULL);
+ }
+#endif
+
+ if (raise(signals[sig]) < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_random_get(void *buf, size_t nbyte)
+{
+ random_buf(buf, nbyte);
+ return 0;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_accept(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new)
+{
+ __wasi_filetype_t wasi_type;
+ __wasi_rights_t max_base, max_inheriting;
+ struct fd_object *fo;
+ bh_socket_t new_sock = -1;
+ int ret;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ACCEPT, 0);
+ if (error != __WASI_ESUCCESS) {
+ goto fail;
+ }
+
+ ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ error = convert_errno(errno);
+ goto fail;
+ }
+
+ error = fd_determine_type_rights(new_sock, &wasi_type, &max_base,
+ &max_inheriting);
+ if (error != __WASI_ESUCCESS) {
+ goto fail;
+ }
+
+ error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base,
+ max_inheriting, fd_new);
+ if (error != __WASI_ESUCCESS) {
+ /* released in fd_table_insert_fd() */
+ new_sock = -1;
+ goto fail;
+ }
+
+ return __WASI_ESUCCESS;
+
+fail:
+ if (-1 != new_sock) {
+ os_socket_close(new_sock);
+ }
+ return error;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_addr_local(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ struct fd_object *fo;
+ bh_sockaddr_t bh_addr;
+ int ret;
+
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_addr_local(fd_number(fo), &bh_addr);
+ fd_object_release(fo);
+ if (ret != BHT_OK) {
+ return convert_errno(errno);
+ }
+
+ bh_sockaddr_to_wasi_addr(&bh_addr, addr);
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_addr_remote(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ struct fd_object *fo;
+ bh_sockaddr_t bh_addr;
+ int ret;
+
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_addr_remote(fd_number(fo), &bh_addr);
+ fd_object_release(fo);
+ if (ret != BHT_OK) {
+ return convert_errno(errno);
+ }
+
+ bh_sockaddr_to_wasi_addr(&bh_addr, addr);
+
+ return __WASI_ESUCCESS;
+}
+
+static bool
+wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen)
+{
+ if (addr->kind == IPv4) {
+ const char *format = "%u.%u.%u.%u";
+
+ assert(buflen >= 16);
+
+ snprintf(buf, buflen, format, addr->addr.ip4.addr.n0,
+ addr->addr.ip4.addr.n1, addr->addr.ip4.addr.n2,
+ addr->addr.ip4.addr.n3);
+
+ return true;
+ }
+ else if (addr->kind == IPv6) {
+ const char *format = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
+ __wasi_addr_ip6_t ipv6 = addr->addr.ip6.addr;
+
+ assert(buflen >= 40);
+
+ snprintf(buf, buflen, format, ipv6.n0, ipv6.n1, ipv6.n2, ipv6.n3,
+ ipv6.h0, ipv6.h1, ipv6.h2, ipv6.h3);
+
+ return true;
+ }
+
+ return false;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_bind(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ char buf[48] = { 0 };
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int port = addr->kind == IPv4 ? addr->addr.ip4.port : addr->addr.ip6.port;
+ int ret;
+
+ if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
+ return __WASI_EPROTONOSUPPORT;
+ }
+
+ if (!addr_pool_search(addr_pool, buf)) {
+ return __WASI_EACCES;
+ }
+
+ error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_bind(fd_number(fo), buf, &port);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_addr_resolve(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, char **ns_lookup_list,
+#endif
+ const char *host, const char *service, __wasi_addr_info_hints_t *hints,
+ __wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size,
+ __wasi_size_t *max_info_size)
+{
+ bh_addr_info_t *wamr_addr_info =
+ wasm_runtime_malloc(addr_info_size * sizeof(bh_addr_info_t));
+ uint8_t hints_is_ipv4 = hints->family == INET4;
+ uint8_t hints_is_tcp = hints->type == SOCKET_STREAM;
+ size_t _max_info_size;
+ size_t actual_info_size;
+
+ if (!wamr_addr_info) {
+ return __WASI_ENOMEM;
+ }
+
+ if (!ns_lookup_list_search(ns_lookup_list, host)) {
+ wasm_runtime_free(wamr_addr_info);
+ return __WASI_EACCES;
+ }
+
+ int ret = os_socket_addr_resolve(
+ host, service, hints->hints_enabled ? &hints_is_tcp : NULL,
+ hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info,
+ addr_info_size, &_max_info_size);
+
+ if (ret != BHT_OK) {
+ wasm_runtime_free(wamr_addr_info);
+ return convert_errno(errno);
+ }
+
+ *max_info_size = _max_info_size;
+ actual_info_size =
+ addr_info_size < *max_info_size ? addr_info_size : *max_info_size;
+
+ for (size_t i = 0; i < actual_info_size; i++) {
+ addr_info[i].type =
+ wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM;
+ bh_sockaddr_to_wasi_addr(&wamr_addr_info[i].sockaddr,
+ &addr_info[i].addr);
+ }
+
+ wasm_runtime_free(wamr_addr_info);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ char buf[48] = { 0 };
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+
+ if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
+ return __WASI_EPROTONOSUPPORT;
+ }
+
+ if (!addr_pool_search(addr_pool, buf)) {
+ return __WASI_EACCES;
+ }
+
+ error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_connect(fd_number(fo), buf,
+ addr->kind == IPv4 ? addr->addr.ip4.port
+ : addr->addr.ip6.port);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *size = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse)
+{
+
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, &optlen);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *reuse = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEPORT, &optval, &optlen);
+#else
+ errno = ENOTSUP;
+ ret = BHT_ERROR;
+ optval = 0;
+#endif /* defined(SO_REUSEPORT) */
+
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *reuse = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, &optlen);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *size = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_listen(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t backlog)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_LISTEN, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_listen(fd_number(fo), backlog);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
+ __wasi_fd_t *sockfd)
+{
+ bh_socket_t sock;
+ bool is_tcp = SOCKET_DGRAM == socktype ? false : true;
+ bool is_ipv4 = INET6 == af ? false : true;
+ int ret;
+ __wasi_filetype_t wasi_type;
+ __wasi_rights_t max_base, max_inheriting;
+ __wasi_errno_t error;
+
+ (void)poolfd;
+
+ ret = os_socket_create(&sock, is_ipv4, is_tcp);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ error =
+ fd_determine_type_rights(sock, &wasi_type, &max_base, &max_inheriting);
+ if (error != __WASI_ESUCCESS) {
+ os_socket_close(sock);
+ return error;
+ }
+
+ if (SOCKET_DGRAM == socktype) {
+ assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM);
+ }
+ else {
+ assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM);
+ }
+
+ // TODO: base rights and inheriting rights ?
+ error = fd_table_insert_fd(curfds, sock, wasi_type, max_base,
+ max_inheriting, sockfd);
+ if (error != __WASI_ESUCCESS) {
+ return error;
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = size;
+
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval,
+ sizeof(optval));
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = reuse;
+
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval,
+ sizeof(optval));
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = reuse;
+
+#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEPORT, &optval,
+ sizeof(optval));
+#else
+ errno = ENOTSUP;
+ ret = BHT_ERROR;
+#endif /* defined(SO_REUSEPORT) */
+
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = size;
+
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval,
+ sizeof(optval));
+
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_recv(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len)
+{
+ __wasi_addr_t src_addr;
+
+ return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr,
+ recv_len);
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_recv_from(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags,
+ __wasi_addr_t *src_addr, size_t *recv_len)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ bh_sockaddr_t sockaddr;
+ int ret;
+
+ error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr);
+ fd_object_release(fo);
+ if (-1 == ret) {
+ return convert_errno(errno);
+ }
+
+ bh_sockaddr_to_wasi_addr(&sockaddr, src_addr);
+
+ *recv_len = (size_t)ret;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_send(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+
+ error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ ret = os_socket_send(fd_number(fo), buf, buf_len);
+ fd_object_release(fo);
+ if (-1 == ret) {
+ return convert_errno(errno);
+ }
+
+ *sent_len = (size_t)ret;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_send_to(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t sock, const void *buf, size_t buf_len,
+ __wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len)
+{
+ char addr_buf[48] = { 0 };
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ bh_sockaddr_t sockaddr;
+
+ if (!wasi_addr_to_string(dest_addr, addr_buf, sizeof(addr_buf))) {
+ return __WASI_EPROTONOSUPPORT;
+ }
+
+ if (!addr_pool_search(addr_pool, addr_buf)) {
+ return __WASI_EACCES;
+ }
+
+ error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr);
+
+ ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr);
+ fd_object_release(fo);
+ if (-1 == ret) {
+ return convert_errno(errno);
+ }
+
+ *sent_len = (size_t)ret;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_shutdown(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_shutdown(fd_number(fo));
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sched_yield(void)
+{
+ if (sched_yield() < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_args_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ char **argv, char *argv_buf)
+{
+ for (size_t i = 0; i < argv_environ->argc; ++i) {
+ argv[i] =
+ argv_buf + (argv_environ->argv_list[i] - argv_environ->argv_buf);
+ }
+ argv[argv_environ->argc] = NULL;
+ bh_memcpy_s(argv_buf, (uint32)argv_environ->argv_buf_size,
+ argv_environ->argv_buf, (uint32)argv_environ->argv_buf_size);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_args_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ size_t *argc, size_t *argv_buf_size)
+{
+ *argc = argv_environ->argc;
+ *argv_buf_size = argv_environ->argv_buf_size;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_environ_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ char **environ, char *environ_buf)
+{
+ for (size_t i = 0; i < argv_environ->environ_count; ++i) {
+ environ[i] =
+ environ_buf
+ + (argv_environ->environ_list[i] - argv_environ->environ_buf);
+ }
+ environ[argv_environ->environ_count] = NULL;
+ bh_memcpy_s(environ_buf, (uint32)argv_environ->environ_buf_size,
+ argv_environ->environ_buf,
+ (uint32)argv_environ->environ_buf_size);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_environ_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ size_t *environ_count, size_t *environ_buf_size)
+{
+ *environ_count = argv_environ->environ_count;
+ *environ_buf_size = argv_environ->environ_buf_size;
+ return __WASI_ESUCCESS;
+}
+
+bool
+argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf,
+ size_t argv_buf_size, char **argv_list, size_t argc,
+ char *environ_buf, size_t environ_buf_size,
+ char **environ_list, size_t environ_count)
+{
+ memset(argv_environ, 0, sizeof(struct argv_environ_values));
+
+ argv_environ->argv_buf = argv_buf;
+ argv_environ->argv_buf_size = argv_buf_size;
+ argv_environ->argv_list = argv_list;
+ argv_environ->argc = argc;
+ argv_environ->environ_buf = environ_buf;
+ argv_environ->environ_buf_size = environ_buf_size;
+ argv_environ->environ_list = environ_list;
+ argv_environ->environ_count = environ_count;
+ return true;
+}
+
+void
+argv_environ_destroy(struct argv_environ_values *argv_environ)
+{}
+
+void
+fd_table_destroy(struct fd_table *ft)
+{
+ if (ft->entries) {
+ for (uint32 i = 0; i < ft->size; i++) {
+ if (ft->entries[i].object != NULL) {
+ fd_object_release(ft->entries[i].object);
+ }
+ }
+ rwlock_destroy(&ft->lock);
+ wasm_runtime_free(ft->entries);
+ }
+}
+
+void
+fd_prestats_destroy(struct fd_prestats *pt)
+{
+ if (pt->prestats) {
+ for (uint32 i = 0; i < pt->size; i++) {
+ if (pt->prestats[i].dir != NULL) {
+ wasm_runtime_free((void *)pt->prestats[i].dir);
+ }
+ }
+ rwlock_destroy(&pt->lock);
+ wasm_runtime_free(pt->prestats);
+ }
+}
+
+bool
+addr_pool_init(struct addr_pool *addr_pool)
+{
+ memset(addr_pool, 0, sizeof(*addr_pool));
+
+ return true;
+}
+
+bool
+addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
+{
+ struct addr_pool *cur = addr_pool;
+ struct addr_pool *next;
+ bh_ip_addr_buffer_t target;
+
+ if (!addr_pool) {
+ return false;
+ }
+
+ if (!(next = wasm_runtime_malloc(sizeof(struct addr_pool)))) {
+ return false;
+ }
+
+ next->next = NULL;
+ next->mask = mask;
+
+ if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
+ // If parsing IPv4 fails, try IPv6
+ if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
+ wasm_runtime_free(next);
+ return false;
+ }
+ next->type = IPv6;
+ bh_memcpy_s(next->addr.ip6, sizeof(next->addr.ip6), target.ipv6,
+ sizeof(target.ipv6));
+ }
+ else {
+ next->type = IPv4;
+ next->addr.ip4 = target.ipv4;
+ }
+
+ /* attach with */
+ while (cur->next) {
+ cur = cur->next;
+ }
+ cur->next = next;
+ return true;
+}
+
+static inline size_t
+min(size_t a, size_t b)
+{
+ return a > b ? b : a;
+}
+
+static void
+init_address_mask(uint8_t *buf, size_t buflen, size_t mask)
+{
+ size_t element_size = sizeof(uint8_t) * 8;
+
+ for (size_t i = 0; i < buflen; i++) {
+ if (mask <= i * element_size) {
+ buf[i] = 0;
+ }
+ else {
+ size_t offset = min(mask - i * element_size, element_size);
+ buf[i] = (~0u) << (element_size - offset);
+ }
+ }
+}
+
+/* target must be in network byte order */
+static bool
+compare_address(const struct addr_pool *addr_pool_entry,
+ bh_ip_addr_buffer_t *target)
+{
+ uint8_t maskbuf[16] = { 0 };
+ uint8_t basebuf[16] = { 0 };
+ size_t addr_size;
+ uint8_t max_addr_mask;
+
+ if (addr_pool_entry->type == IPv4) {
+ uint32_t addr_ip4 = htonl(addr_pool_entry->addr.ip4);
+ bh_memcpy_s(basebuf, sizeof(addr_ip4), &addr_ip4, sizeof(addr_ip4));
+ addr_size = 4;
+ }
+ else {
+ uint16_t partial_addr_ip6;
+ for (int i = 0; i < 8; i++) {
+ partial_addr_ip6 = htons(addr_pool_entry->addr.ip6[i]);
+ bh_memcpy_s(&basebuf[i * sizeof(partial_addr_ip6)],
+ sizeof(partial_addr_ip6), &partial_addr_ip6,
+ sizeof(partial_addr_ip6));
+ }
+ addr_size = 16;
+ }
+ max_addr_mask = addr_size * 8;
+
+ /* IPv4 0.0.0.0 or IPv6 :: means any address */
+ if (basebuf[0] == 0 && !memcmp(basebuf, basebuf + 1, addr_size - 1)) {
+ return true;
+ }
+
+ /* No support for invalid mask value */
+ if (addr_pool_entry->mask > max_addr_mask) {
+ return false;
+ }
+
+ init_address_mask(maskbuf, addr_size, addr_pool_entry->mask);
+
+ for (size_t i = 0; i < addr_size; i++) {
+ uint8_t addr_mask = target->data[i] & maskbuf[i];
+ uint8_t range_mask = basebuf[i] & maskbuf[i];
+ if (addr_mask != range_mask) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+addr_pool_search(struct addr_pool *addr_pool, const char *addr)
+{
+ struct addr_pool *cur = addr_pool->next;
+ bh_ip_addr_buffer_t target;
+ __wasi_addr_type_t addr_type;
+
+ if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
+ size_t i;
+
+ if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
+ return false;
+ }
+ addr_type = IPv6;
+ for (i = 0; i < sizeof(target.ipv6) / sizeof(target.ipv6[0]); i++) {
+ target.ipv6[i] = htons(target.ipv6[i]);
+ }
+ }
+ else {
+ addr_type = IPv4;
+ target.ipv4 = htonl(target.ipv4);
+ }
+
+ while (cur) {
+ if (cur->type == addr_type && compare_address(cur, &target)) {
+ return true;
+ }
+
+ cur = cur->next;
+ }
+
+ return false;
+}
+
+void
+addr_pool_destroy(struct addr_pool *addr_pool)
+{
+ struct addr_pool *cur = addr_pool->next;
+
+ while (cur) {
+ struct addr_pool *next = cur->next;
+ wasm_runtime_free(cur);
+ cur = next;
+ }
+}
+
+#ifndef WASMTIME_SSP_STATIC_CURFDS
+#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds,
+#else
+#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE
+#endif
+
+// Defines a function that passes through the socket option to the OS
+// implementation
+#define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \
+ __wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \
+ WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \
+ OPTION_TYPE option) \
+ { \
+ struct fd_object *fo; \
+ __wasi_errno_t error; \
+ int ret; \
+ error = fd_object_get(curfds, &fo, sock, 0, 0); \
+ if (error != 0) \
+ return error; \
+ ret = os_socket_##FUNC_NAME(fd_number(fo), option); \
+ fd_object_release(fo); \
+ if (BHT_OK != ret) \
+ return convert_errno(errno); \
+ return __WASI_ESUCCESS; \
+ }
+
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_timeout, uint64)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_timeout, uint64 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_timeout, uint64)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_timeout, uint64 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_buf_size, size_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_buf_size, size_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_buf_size, size_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_buf_size, size_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_broadcast, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_broadcast, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_keep_alive, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_keep_alive, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_addr, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_addr, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_port, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_port, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_no_delay, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_no_delay, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_quick_ack, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_quick_ack, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_idle, uint32)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_idle, uint32 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_intvl, uint32)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_intvl, uint32 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_fastopen_connect, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_fastopen_connect, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_ttl, uint8_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_ttl, uint8_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_multicast_ttl, uint8_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_multicast_ttl, uint8_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ipv6_only, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *)
+
+#undef WASMTIME_SSP_PASSTHROUGH_FD_TABLE
+#undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool is_enabled, int linger_s)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_get_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool *is_enabled, int *linger_s)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_ip_add_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ bh_ip_addr_buffer_t addr_info;
+ bool is_ipv6;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info);
+ is_ipv6 = imr_multiaddr->kind == IPv6;
+ ret = os_socket_set_ip_add_membership(fd_number(fo), &addr_info,
+ imr_interface, is_ipv6);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_ip_drop_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ bh_ip_addr_buffer_t addr_info;
+ bool is_ipv6;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info);
+ is_ipv6 = imr_multiaddr->kind == IPv6;
+ ret = os_socket_set_ip_drop_membership(fd_number(fo), &addr_info,
+ imr_interface, is_ipv6);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool ipv6, bool is_enabled)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_get_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool ipv6, bool *is_enabled)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+
+ return __WASI_ESUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h
new file mode 100644
index 000000000..7a593390a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h
@@ -0,0 +1,89 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/
+
+#ifndef POSIX_H
+#define POSIX_H
+
+#include "bh_platform.h"
+#include "locking.h"
+
+struct fd_entry;
+struct fd_prestat;
+struct syscalls;
+
+struct fd_table {
+ struct rwlock lock;
+ struct fd_entry *entries;
+ size_t size;
+ size_t used;
+};
+
+struct fd_prestats {
+ struct rwlock lock;
+ struct fd_prestat *prestats;
+ size_t size;
+ size_t used;
+};
+
+struct argv_environ_values {
+ const char *argv_buf;
+ size_t argv_buf_size;
+ char **argv_list;
+ size_t argc;
+ char *environ_buf;
+ size_t environ_buf_size;
+ char **environ_list;
+ size_t environ_count;
+};
+
+struct addr_pool {
+ /* addr and mask in host order */
+ union {
+ uint32 ip4;
+ uint16 ip6[8];
+ } addr;
+ struct addr_pool *next;
+ __wasi_addr_type_t type;
+ uint8 mask;
+};
+
+bool
+fd_table_init(struct fd_table *);
+bool
+fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int);
+bool
+fd_prestats_init(struct fd_prestats *);
+bool
+fd_prestats_insert(struct fd_prestats *, const char *, __wasi_fd_t);
+bool
+argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf,
+ size_t argv_buf_size, char **argv_list, size_t argc,
+ char *environ_buf, size_t environ_buf_size,
+ char **environ_list, size_t environ_count);
+void
+argv_environ_destroy(struct argv_environ_values *argv_environ);
+void
+fd_table_destroy(struct fd_table *ft);
+void
+fd_prestats_destroy(struct fd_prestats *pt);
+
+bool
+addr_pool_init(struct addr_pool *);
+bool
+addr_pool_insert(struct addr_pool *, const char *, uint8 mask);
+bool
+addr_pool_search(struct addr_pool *, const char *);
+void
+addr_pool_destroy(struct addr_pool *);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h
new file mode 100644
index 000000000..2d40bc3aa
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h
@@ -0,0 +1,98 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+// LIST: Double-linked list.
+
+#define LIST_HEAD(name, type) \
+ struct name { \
+ struct type *l_first; \
+ }
+
+/* clang-format off */
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+/* clang-format on */
+
+#define LIST_ENTRY(type) \
+ struct { \
+ struct type *l_next; \
+ struct type **l_prev; \
+ }
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = (head)->l_first; (var) != NULL; (var) = (var)->field.l_next)
+
+#define LIST_INIT(head) \
+ do { \
+ (head)->l_first = NULL; \
+ } while (0)
+
+#define LIST_INSERT_HEAD(head, element, field) \
+ do { \
+ (element)->field.l_next = (head)->l_first; \
+ if ((head)->l_first != NULL) \
+ (head)->l_first->field.l_prev = &(element)->field.l_next; \
+ (head)->l_first = (element); \
+ (element)->field.l_prev = &(head)->l_first; \
+ } while (0)
+
+#define LIST_REMOVE(element, field) \
+ do { \
+ if ((element)->field.l_next != NULL) \
+ (element)->field.l_next->field.l_prev = (element)->field.l_prev; \
+ *(element)->field.l_prev = (element)->field.l_next; \
+ } while (0)
+
+// TAILQ: Double-linked list with tail pointer.
+
+#define TAILQ_HEAD(name, type) \
+ struct name { \
+ struct type *t_first; \
+ struct type **t_last; \
+ }
+
+#define TAILQ_ENTRY(type) \
+ struct { \
+ struct type *t_next; \
+ struct type **t_prev; \
+ }
+
+#define TAILQ_EMPTY(head) ((head)->t_first == NULL)
+#define TAILQ_FIRST(head) ((head)->t_first)
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = (head)->t_first; (var) != NULL; (var) = (var)->field.t_next)
+#define TAILQ_INIT(head) \
+ do { \
+ (head)->t_first = NULL; \
+ (head)->t_last = &(head)->t_first; \
+ } while (0)
+#define TAILQ_INSERT_TAIL(head, elm, field) \
+ do { \
+ (elm)->field.t_next = NULL; \
+ (elm)->field.t_prev = (head)->t_last; \
+ *(head)->t_last = (elm); \
+ (head)->t_last = &(elm)->field.t_next; \
+ } while (0)
+#define TAILQ_REMOVE(head, element, field) \
+ do { \
+ if ((element)->field.t_next != NULL) \
+ (element)->field.t_next->field.t_prev = (element)->field.t_prev; \
+ else \
+ (head)->t_last = (element)->field.t_prev; \
+ *(element)->field.t_prev = (element)->field.t_next; \
+ } while (0)
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c
new file mode 100644
index 000000000..01a1dab3a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c
@@ -0,0 +1,98 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "random.h"
+
+#if CONFIG_HAS_ARC4RANDOM_BUF
+
+void
+random_buf(void *buf, size_t len)
+{
+ arc4random_buf(buf, len);
+}
+
+#elif CONFIG_HAS_GETRANDOM
+
+#ifndef BH_PLATFORM_LINUX_SGX
+#include <sys/random.h>
+#endif
+
+void
+random_buf(void *buf, size_t len)
+{
+ for (;;) {
+ ssize_t x = getrandom(buf, len, 0);
+ if (x < 0) {
+ if (errno == EINTR)
+ continue;
+ os_printf("getrandom failed: %s", strerror(errno));
+ abort();
+ }
+ if ((size_t)x == len)
+ return;
+ buf = (void *)((unsigned char *)buf + x);
+ len -= (size_t)x;
+ }
+}
+
+#else
+
+static int urandom;
+
+static void
+open_urandom(void)
+{
+ urandom = open("/dev/urandom", O_RDONLY);
+ if (urandom < 0) {
+ os_printf("Failed to open /dev/urandom\n");
+ abort();
+ }
+}
+
+void
+random_buf(void *buf, size_t len)
+{
+ static pthread_once_t open_once = PTHREAD_ONCE_INIT;
+ pthread_once(&open_once, open_urandom);
+
+ if ((size_t)read(urandom, buf, len) != len) {
+ os_printf("Short read on /dev/urandom\n");
+ abort();
+ }
+}
+
+#endif
+
+// Calculates a random number within the range [0, upper - 1] without
+// any modulo bias.
+//
+// The function below repeatedly obtains a random number from
+// arc4random() until it lies within the range [2^k % upper, 2^k). As
+// this range has length k * upper, we can safely obtain a number
+// without any modulo bias.
+uintmax_t
+random_uniform(uintmax_t upper)
+{
+ // Compute 2^k % upper
+ // == (2^k - upper) % upper
+ // == -upper % upper.
+ uintmax_t lower = -upper % upper;
+ for (;;) {
+ uintmax_t value;
+ random_buf(&value, sizeof(value));
+ if (value >= lower)
+ return value % upper;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h
new file mode 100644
index 000000000..23c2da4db
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h
@@ -0,0 +1,21 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+void
+random_buf(void *, size_t);
+uintmax_t random_uniform(uintmax_t);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h
new file mode 100644
index 000000000..03b4b87ac
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h
@@ -0,0 +1,139 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef REFCOUNT_H
+#define REFCOUNT_H
+
+#include "bh_platform.h"
+#include "locking.h"
+#include "gnuc.h"
+
+#define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS
+#define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS
+
+#if CONFIG_HAS_STD_ATOMIC != 0
+
+#include <stdatomic.h>
+
+/* Simple reference counter. */
+struct LOCKABLE refcount {
+ atomic_uint count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count) PRODUCES(*r)
+{
+ atomic_init(&r->count, count);
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r) PRODUCES(*r)
+{
+ atomic_fetch_add_explicit(&r->count, 1, memory_order_acquire);
+}
+
+/* Decrement the reference counter, returning whether the reference
+ dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r) CONSUMES(*r)
+{
+ int old =
+ (int)atomic_fetch_sub_explicit(&r->count, 1, memory_order_release);
+ bh_assert(old != 0 && "Reference count becoming negative");
+ return old == 1;
+}
+
+#elif defined(BH_PLATFORM_LINUX_SGX)
+
+#include <sgx_spinlock.h>
+
+/* Simple reference counter. */
+struct refcount {
+ sgx_spinlock_t lock;
+ unsigned int count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count)
+{
+ r->lock = SGX_SPINLOCK_INITIALIZER;
+ r->count = count;
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r)
+{
+ sgx_spin_lock(&r->lock);
+ r->count++;
+ sgx_spin_unlock(&r->lock);
+}
+
+/* Decrement the reference counter, returning whether the reference
+ dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r)
+{
+ int old;
+ sgx_spin_lock(&r->lock);
+ old = (int)r->count;
+ r->count--;
+ sgx_spin_unlock(&r->lock);
+ bh_assert(old != 0 && "Reference count becoming negative");
+ return old == 1;
+}
+
+#elif defined(__GNUC_PREREQ)
+
+#if __GNUC_PREREQ(4, 7)
+
+struct refcount {
+ unsigned int count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count)
+{
+ __atomic_store_n(&r->count, count, __ATOMIC_SEQ_CST);
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r)
+{
+ __atomic_fetch_add(&r->count, 1, __ATOMIC_ACQUIRE);
+}
+
+/* Decrement the reference counter, returning whether the reference
+ dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r)
+{
+ int old = (int)__atomic_fetch_sub(&r->count, 1, __ATOMIC_RELEASE);
+ bh_assert(old != 0 && "Reference count becoming negative");
+ return old == 1;
+}
+
+#else /* else of __GNUC_PREREQ (4.7) */
+#error "Reference counter isn't implemented"
+#endif /* end of __GNUC_PREREQ (4.7) */
+
+#else /* else of CONFIG_HAS_STD_ATOMIC */
+#error "Reference counter isn't implemented"
+#endif /* end of CONFIG_HAS_STD_ATOMIC */
+
+#endif /* end of REFCOUNT_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h
new file mode 100644
index 000000000..4f5838159
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h
@@ -0,0 +1,100 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef RIGHTS_H
+#define RIGHTS_H
+
+/* clang-format off */
+
+#define RIGHTS_ALL \
+ (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \
+ __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \
+ __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \
+ __WASI_RIGHT_PATH_CREATE_DIRECTORY | __WASI_RIGHT_PATH_CREATE_FILE | \
+ __WASI_RIGHT_PATH_LINK_SOURCE | __WASI_RIGHT_PATH_LINK_TARGET | \
+ __WASI_RIGHT_PATH_OPEN | __WASI_RIGHT_FD_READDIR | \
+ __WASI_RIGHT_PATH_READLINK | __WASI_RIGHT_PATH_RENAME_SOURCE | \
+ __WASI_RIGHT_PATH_RENAME_TARGET | __WASI_RIGHT_PATH_FILESTAT_GET | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \
+ __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \
+ __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
+ __WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
+ __WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
+ __WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
+ __WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
+ __WASI_RIGHT_SOCK_SEND_TO)
+
+
+// Block and character device interaction is outside the scope of
+// CloudABI. Simply allow everything.
+#define RIGHTS_BLOCK_DEVICE_BASE RIGHTS_ALL
+#define RIGHTS_BLOCK_DEVICE_INHERITING RIGHTS_ALL
+#define RIGHTS_CHARACTER_DEVICE_BASE RIGHTS_ALL
+#define RIGHTS_CHARACTER_DEVICE_INHERITING RIGHTS_ALL
+
+// Only allow directory operations on directories. Directories can only
+// yield file descriptors to other directories and files.
+#define RIGHTS_DIRECTORY_BASE \
+ (__WASI_RIGHT_FD_FDSTAT_SET_FLAGS | __WASI_RIGHT_FD_SYNC | \
+ __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_PATH_CREATE_DIRECTORY | \
+ __WASI_RIGHT_PATH_CREATE_FILE | __WASI_RIGHT_PATH_LINK_SOURCE | \
+ __WASI_RIGHT_PATH_LINK_TARGET | __WASI_RIGHT_PATH_OPEN | \
+ __WASI_RIGHT_FD_READDIR | __WASI_RIGHT_PATH_READLINK | \
+ __WASI_RIGHT_PATH_RENAME_SOURCE | __WASI_RIGHT_PATH_RENAME_TARGET | \
+ __WASI_RIGHT_PATH_FILESTAT_GET | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \
+ __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \
+ __WASI_RIGHT_POLL_FD_READWRITE)
+#define RIGHTS_DIRECTORY_INHERITING \
+ (RIGHTS_DIRECTORY_BASE | RIGHTS_REGULAR_FILE_BASE)
+
+// Operations that apply to regular files.
+#define RIGHTS_REGULAR_FILE_BASE \
+ (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \
+ __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \
+ __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \
+ __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_FD_FILESTAT_SET_TIMES | __WASI_RIGHT_POLL_FD_READWRITE)
+#define RIGHTS_REGULAR_FILE_INHERITING 0
+
+// Operations that apply to sockets and socket pairs.
+#define RIGHTS_SOCKET_BASE \
+ (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
+ __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
+ __WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
+ __WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
+ __WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
+ __WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
+ __WASI_RIGHT_SOCK_SEND_TO)
+#define RIGHTS_SOCKET_INHERITING RIGHTS_ALL
+
+// Operations that apply to TTYs.
+#define RIGHTS_TTY_BASE \
+ (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
+ __WASI_RIGHT_POLL_FD_READWRITE)
+#define RIGHTS_TTY_INHERITING 0
+
+/* clang-format on */
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
new file mode 100644
index 000000000..7f6e9b941
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
@@ -0,0 +1,143 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef SSP_CONFIG_H
+#define SSP_CONFIG_H
+
+#include "gnuc.h"
+#include <stdlib.h>
+
+#if defined(__FreeBSD__) || defined(__APPLE__) \
+ || (defined(ANDROID) && __ANDROID_API__ < 28)
+#define CONFIG_HAS_ARC4RANDOM_BUF 1
+#else
+#define CONFIG_HAS_ARC4RANDOM_BUF 0
+#endif
+
+// On Linux, prefer to use getrandom, though it isn't available in
+// GLIBC before 2.25.
+#if (defined(__linux__) || defined(ESP_PLATFORM)) \
+ && (!defined(__GLIBC__) || __GLIBC__ > 2 \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
+#define CONFIG_HAS_GETRANDOM 1
+#else
+#define CONFIG_HAS_GETRANDOM 0
+#endif
+
+#if defined(__CloudABI__)
+#define CONFIG_HAS_CAP_ENTER 1
+#else
+#define CONFIG_HAS_CAP_ENTER 0
+#endif
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__) \
+ && !defined(ESP_PLATFORM) && !defined(DISABLE_CLOCK_NANOSLEEP)
+#define CONFIG_HAS_CLOCK_NANOSLEEP 1
+#else
+#define CONFIG_HAS_CLOCK_NANOSLEEP 0
+#endif
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_FDATASYNC 1
+#else
+#define CONFIG_HAS_FDATASYNC 0
+#endif
+
+/*
+ * For NuttX, CONFIG_HAS_ISATTY is provided by its platform header.
+ * (platform_internal.h)
+ */
+#ifndef __NuttX__
+#ifndef __CloudABI__
+#define CONFIG_HAS_ISATTY 1
+#else
+#define CONFIG_HAS_ISATTY 0
+#endif
+#endif
+
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_POSIX_FALLOCATE 1
+#else
+#define CONFIG_HAS_POSIX_FALLOCATE 0
+#endif
+
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_PREADV 1
+#else
+#define CONFIG_HAS_PREADV 0
+#endif
+
+#if defined(__APPLE__) || defined(__CloudABI__)
+#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1
+#else
+#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0
+#endif
+
+#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX)
+#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1
+#else
+#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0
+#endif
+
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_PWRITEV 1
+#else
+#define CONFIG_HAS_PWRITEV 0
+#endif
+
+#ifdef __APPLE__
+#define st_atim st_atimespec
+#define st_ctim st_ctimespec
+#define st_mtim st_mtimespec
+#endif
+
+#ifdef __APPLE__
+#define CONFIG_TLS_USE_GSBASE 1
+#else
+#define CONFIG_TLS_USE_GSBASE 0
+#endif
+
+#if !defined(BH_PLATFORM_LINUX_SGX)
+/* Clang's __GNUC_PREREQ macro has a different meaning than GCC one,
+so we have to handle this case specially */
+#if defined(__clang__)
+/* Clang provides stdatomic.h since 3.6.0
+See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+#define CONFIG_HAS_STD_ATOMIC 1
+#else
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif
+#elif defined(__GNUC_PREREQ)
+/* Even though older versions of GCC support C11, atomics were
+not implemented until 4.9. See
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */
+#if __GNUC_PREREQ(4, 9)
+#define CONFIG_HAS_STD_ATOMIC 1
+#else /* else of __GNUC_PREREQ(4, 9) */
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif /* end of __GNUC_PREREQ(4, 9) */
+#else /* else of defined(__GNUC_PREREQ) */
+#define CONFIG_HAS_STD_ATOMIC 1
+#endif /* end of defined(__GNUC_PREREQ) */
+#else /* else of !defined(BH_PLATFORM_LINUX_SGX) */
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif /* end of !defined(BH_PLATFORM_LINUX_SGX) */
+
+#if !defined(__NuttX__)
+#define CONFIG_HAS_D_INO 1
+#else
+#define CONFIG_HAS_D_INO 0
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c
new file mode 100644
index 000000000..858d8d5e4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c
@@ -0,0 +1,47 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "str.h"
+
+static char *
+bh_strndup(const char *s, size_t n)
+{
+ size_t l = strnlen(s, n);
+ char *s1 = wasm_runtime_malloc((uint32)(l + 1));
+
+ if (!s1)
+ return NULL;
+ bh_memcpy_s(s1, (uint32)(l + 1), s, (uint32)l);
+ s1[l] = 0;
+ return s1;
+}
+
+char *
+str_nullterminate(const char *s, size_t len)
+{
+ /* Copy string */
+ char *ret = bh_strndup(s, len);
+
+ if (ret == NULL)
+ return NULL;
+
+ /* Ensure that it contains no null bytes within */
+ if (strlen(ret) != len) {
+ wasm_runtime_free(ret);
+ errno = EILSEQ;
+ return NULL;
+ }
+ return ret;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h
new file mode 100644
index 000000000..7d633e5c8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h
@@ -0,0 +1,22 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef STR_H
+#define STR_H
+
+#include "ssp_config.h"
+
+char *
+str_nullterminate(const char *, size_t);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript
new file mode 100644
index 000000000..65f561ae2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+thread_manager.c
+''')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_lib_thread_mgr', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c
new file mode 100644
index 000000000..9303eb3f5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c
@@ -0,0 +1,1351 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "thread_manager.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#include "debug_engine.h"
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#endif
+
+typedef struct {
+ bh_list_link l;
+ void (*destroy_cb)(WASMCluster *);
+} DestroyCallBackNode;
+
+static bh_list destroy_callback_list_head;
+static bh_list *const destroy_callback_list = &destroy_callback_list_head;
+
+static bh_list cluster_list_head;
+static bh_list *const cluster_list = &cluster_list_head;
+static korp_mutex cluster_list_lock;
+
+typedef void (*list_visitor)(void *, void *);
+
+static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
+
+/* Set the maximum thread number, if this function is not called,
+ the max thread num is defined by CLUSTER_MAX_THREAD_NUM */
+void
+wasm_cluster_set_max_thread_num(uint32 num)
+{
+ if (num > 0)
+ cluster_max_thread_num = num;
+}
+
+bool
+thread_manager_init()
+{
+ if (bh_list_init(cluster_list) != 0)
+ return false;
+ if (os_mutex_init(&cluster_list_lock) != 0)
+ return false;
+ return true;
+}
+
+void
+thread_manager_destroy()
+{
+ WASMCluster *cluster = bh_list_first_elem(cluster_list);
+ WASMCluster *next;
+ while (cluster) {
+ next = bh_list_elem_next(cluster);
+ wasm_cluster_destroy(cluster);
+ cluster = next;
+ }
+ wasm_cluster_cancel_all_callbacks();
+ os_mutex_destroy(&cluster_list_lock);
+}
+
+static void
+traverse_list(bh_list *l, list_visitor visitor, void *user_data)
+{
+ void *next, *node = bh_list_first_elem(l);
+ while (node) {
+ next = bh_list_elem_next(node);
+ visitor(node, user_data);
+ node = next;
+ }
+}
+
+/* Assumes cluster->lock is locked */
+static bool
+safe_traverse_exec_env_list(WASMCluster *cluster, list_visitor visitor,
+ void *user_data)
+{
+ Vector proc_nodes;
+ void *node;
+ bool ret = true;
+
+ if (!bh_vector_init(&proc_nodes, cluster->exec_env_list.len, sizeof(void *),
+ false)) {
+ ret = false;
+ goto final;
+ }
+
+ node = bh_list_first_elem(&cluster->exec_env_list);
+
+ while (node) {
+ bool already_processed = false;
+ void *proc_node;
+ uint32 i;
+ for (i = 0; i < (uint32)bh_vector_size(&proc_nodes); i++) {
+ if (!bh_vector_get(&proc_nodes, i, &proc_node)) {
+ ret = false;
+ goto final;
+ }
+ if (proc_node == node) {
+ already_processed = true;
+ break;
+ }
+ }
+ if (already_processed) {
+ node = bh_list_elem_next(node);
+ continue;
+ }
+
+ os_mutex_unlock(&cluster->lock);
+ visitor(node, user_data);
+ os_mutex_lock(&cluster->lock);
+ if (!bh_vector_append(&proc_nodes, &node)) {
+ ret = false;
+ goto final;
+ }
+
+ node = bh_list_first_elem(&cluster->exec_env_list);
+ }
+
+final:
+ bh_vector_destroy(&proc_nodes);
+
+ return ret;
+}
+
+/* The caller must lock cluster->lock */
+static bool
+allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+ uint32 stack_end;
+
+ stack_end = wasm_runtime_module_malloc_internal(module_inst, exec_env,
+ cluster->stack_size, NULL);
+ *start = stack_end + cluster->stack_size;
+ *size = cluster->stack_size;
+
+ return stack_end != 0;
+#else
+ uint32 i;
+
+ /* If the module doesn't have aux stack info,
+ it can't create any threads */
+ if (!cluster->stack_segment_occupied)
+ return false;
+
+ for (i = 0; i < cluster_max_thread_num; i++) {
+ if (!cluster->stack_segment_occupied[i]) {
+ if (start)
+ *start = cluster->stack_tops[i];
+ if (size)
+ *size = cluster->stack_size;
+ cluster->stack_segment_occupied[i] = true;
+ return true;
+ }
+ }
+
+ return false;
+#endif
+}
+
+/* The caller must lock cluster->lock */
+static bool
+free_aux_stack(WASMExecEnv *exec_env, uint32 start)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+
+ if (!wasm_exec_env_is_aux_stack_managed_by_runtime(exec_env)) {
+ return true;
+ }
+
+ bh_assert(start >= cluster->stack_size);
+
+ wasm_runtime_module_free_internal(module_inst, exec_env,
+ start - cluster->stack_size);
+
+ return true;
+#else
+ uint32 i;
+
+ for (i = 0; i < cluster_max_thread_num; i++) {
+ if (start == cluster->stack_tops[i]) {
+ cluster->stack_segment_occupied[i] = false;
+ return true;
+ }
+ }
+ return false;
+#endif
+}
+
+WASMCluster *
+wasm_cluster_create(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster;
+ uint32 aux_stack_start, aux_stack_size;
+
+ bh_assert(exec_env->cluster == NULL);
+ if (!(cluster = wasm_runtime_malloc(sizeof(WASMCluster)))) {
+ LOG_ERROR("thread manager error: failed to allocate memory");
+ return NULL;
+ }
+ memset(cluster, 0, sizeof(WASMCluster));
+
+ exec_env->cluster = cluster;
+
+ bh_list_init(&cluster->exec_env_list);
+ bh_list_insert(&cluster->exec_env_list, exec_env);
+ if (os_mutex_init(&cluster->lock) != 0) {
+ wasm_runtime_free(cluster);
+ LOG_ERROR("thread manager error: failed to init mutex");
+ return NULL;
+ }
+
+ /* Prepare the aux stack top and size for every thread */
+ if (!wasm_exec_env_get_aux_stack(exec_env, &aux_stack_start,
+ &aux_stack_size)) {
+#if WASM_ENABLE_LIB_WASI_THREADS == 0
+ LOG_VERBOSE("No aux stack info for this module, can't create thread");
+#endif
+
+ /* If the module don't have aux stack info, don't throw error here,
+ but remain stack_tops and stack_segment_occupied as NULL */
+ os_mutex_lock(&cluster_list_lock);
+ if (bh_list_insert(cluster_list, cluster) != 0) {
+ os_mutex_unlock(&cluster_list_lock);
+ goto fail;
+ }
+ os_mutex_unlock(&cluster_list_lock);
+
+ return cluster;
+ }
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
+ cluster->stack_size = aux_stack_size;
+#else
+ cluster->stack_size = aux_stack_size / (cluster_max_thread_num + 1);
+ if (cluster->stack_size < WASM_THREAD_AUX_STACK_SIZE_MIN) {
+ goto fail;
+ }
+ /* Make stack size 16-byte aligned */
+ cluster->stack_size = cluster->stack_size & (~15);
+#endif
+
+ /* Set initial aux stack top to the instance and
+ aux stack boundary to the main exec_env */
+ if (!wasm_exec_env_set_aux_stack(exec_env, aux_stack_start,
+ cluster->stack_size))
+ goto fail;
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ if (cluster_max_thread_num != 0) {
+ uint64 total_size = cluster_max_thread_num * sizeof(uint32);
+ uint32 i;
+ if (total_size >= UINT32_MAX
+ || !(cluster->stack_tops =
+ wasm_runtime_malloc((uint32)total_size))) {
+ goto fail;
+ }
+ memset(cluster->stack_tops, 0, (uint32)total_size);
+
+ if (!(cluster->stack_segment_occupied =
+ wasm_runtime_malloc(cluster_max_thread_num * sizeof(bool)))) {
+ goto fail;
+ }
+ memset(cluster->stack_segment_occupied, 0,
+ cluster_max_thread_num * sizeof(bool));
+
+ /* Reserve space for main instance */
+ aux_stack_start -= cluster->stack_size;
+
+ for (i = 0; i < cluster_max_thread_num; i++) {
+ cluster->stack_tops[i] = aux_stack_start - cluster->stack_size * i;
+ }
+ }
+#endif
+
+ os_mutex_lock(&cluster_list_lock);
+ if (bh_list_insert(cluster_list, cluster) != 0) {
+ os_mutex_unlock(&cluster_list_lock);
+ goto fail;
+ }
+ os_mutex_unlock(&cluster_list_lock);
+
+ return cluster;
+
+fail:
+ if (cluster)
+ wasm_cluster_destroy(cluster);
+
+ return NULL;
+}
+
+static void
+destroy_cluster_visitor(void *node, void *user_data)
+{
+ DestroyCallBackNode *destroy_node = (DestroyCallBackNode *)node;
+ WASMCluster *cluster = (WASMCluster *)user_data;
+
+ destroy_node->destroy_cb(cluster);
+}
+
+void
+wasm_cluster_destroy(WASMCluster *cluster)
+{
+ traverse_list(destroy_callback_list, destroy_cluster_visitor,
+ (void *)cluster);
+
+ /* Remove the cluster from the cluster list */
+ os_mutex_lock(&cluster_list_lock);
+ bh_list_remove(cluster_list, cluster);
+ os_mutex_unlock(&cluster_list_lock);
+
+ os_mutex_destroy(&cluster->lock);
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ if (cluster->stack_tops)
+ wasm_runtime_free(cluster->stack_tops);
+ if (cluster->stack_segment_occupied)
+ wasm_runtime_free(cluster->stack_segment_occupied);
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_debug_instance_destroy(cluster);
+#endif
+
+ wasm_runtime_free(cluster);
+}
+
+static void
+free_node_visitor(void *node, void *user_data)
+{
+ wasm_runtime_free(node);
+}
+
+void
+wasm_cluster_cancel_all_callbacks()
+{
+ traverse_list(destroy_callback_list, free_node_visitor, NULL);
+ bh_list_init(destroy_callback_list);
+}
+
+WASMCluster *
+wasm_exec_env_get_cluster(WASMExecEnv *exec_env)
+{
+ return exec_env->cluster;
+}
+
+/* The caller must lock cluster->lock */
+static bool
+wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
+{
+ bool ret = true;
+
+ exec_env->cluster = cluster;
+
+ if (cluster->exec_env_list.len == cluster_max_thread_num + 1) {
+ LOG_ERROR("thread manager error: "
+ "maximum number of threads exceeded");
+ ret = false;
+ }
+
+ if (ret && bh_list_insert(&cluster->exec_env_list, exec_env) != 0)
+ ret = false;
+
+ return ret;
+}
+
+static bool
+wasm_cluster_del_exec_env_internal(WASMCluster *cluster, WASMExecEnv *exec_env,
+ bool can_destroy_cluster)
+{
+ bool ret = true;
+ bh_assert(exec_env->cluster == cluster);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ /* Wait for debugger control thread to process the
+ stop event of this thread */
+ if (cluster->debug_inst) {
+ /* lock the debug_inst->wait_lock so
+ other threads can't fire stop events */
+ os_mutex_lock(&cluster->debug_inst->wait_lock);
+ while (cluster->debug_inst->stopped_thread == exec_env) {
+ /* either wakes up by signal or by 1-second timeout */
+ os_cond_reltimedwait(&cluster->debug_inst->wait_cond,
+ &cluster->debug_inst->wait_lock, 1000000);
+ }
+ os_mutex_unlock(&cluster->debug_inst->wait_lock);
+ }
+#endif
+ if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
+ ret = false;
+
+ if (can_destroy_cluster) {
+ if (cluster->exec_env_list.len == 0) {
+ /* exec_env_list empty, destroy the cluster */
+ wasm_cluster_destroy(cluster);
+ }
+ }
+ else {
+ /* Don't destroy cluster as cluster->lock is being used */
+ }
+
+ return ret;
+}
+
+/* The caller should lock cluster->lock for thread safety */
+bool
+wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
+{
+ return wasm_cluster_del_exec_env_internal(cluster, exec_env, true);
+}
+
+static WASMExecEnv *
+wasm_cluster_search_exec_env(WASMCluster *cluster,
+ WASMModuleInstanceCommon *module_inst)
+{
+ WASMExecEnv *node = NULL;
+
+ os_mutex_lock(&cluster->lock);
+ node = bh_list_first_elem(&cluster->exec_env_list);
+ while (node) {
+ if (node->module_inst == module_inst) {
+ os_mutex_unlock(&cluster->lock);
+ return node;
+ }
+ node = bh_list_elem_next(node);
+ }
+
+ os_mutex_unlock(&cluster->lock);
+ return NULL;
+}
+
+/* search the global cluster list to find if the given
+ module instance have a corresponding exec_env */
+WASMExecEnv *
+wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst)
+{
+ WASMCluster *cluster = NULL;
+ WASMExecEnv *exec_env = NULL;
+
+ os_mutex_lock(&cluster_list_lock);
+ cluster = bh_list_first_elem(cluster_list);
+ while (cluster) {
+ exec_env = wasm_cluster_search_exec_env(cluster, module_inst);
+ if (exec_env) {
+ os_mutex_unlock(&cluster_list_lock);
+ return exec_env;
+ }
+ cluster = bh_list_elem_next(cluster);
+ }
+
+ os_mutex_unlock(&cluster_list_lock);
+ return NULL;
+}
+
+WASMExecEnv *
+wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_t module;
+ wasm_module_inst_t new_module_inst;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIContext *wasi_ctx;
+#endif
+ WASMExecEnv *new_exec_env;
+ uint32 aux_stack_start, aux_stack_size;
+ uint32 stack_size = 8192;
+
+ if (!module_inst || !(module = wasm_exec_env_get_module(exec_env))) {
+ return NULL;
+ }
+
+ os_mutex_lock(&cluster->lock);
+
+ if (cluster->has_exception || cluster->processing) {
+ goto fail1;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ stack_size =
+ ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ stack_size =
+ ((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+ if (!(new_module_inst = wasm_runtime_instantiate_internal(
+ module, true, exec_env, stack_size, 0, NULL, 0))) {
+ goto fail1;
+ }
+
+ /* Set custom_data to new module instance */
+ wasm_runtime_set_custom_data_internal(
+ new_module_inst, wasm_runtime_get_custom_data(module_inst));
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
+#endif
+
+ new_exec_env = wasm_exec_env_create_internal(new_module_inst,
+ exec_env->wasm_stack_size);
+ if (!new_exec_env)
+ goto fail2;
+
+ if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
+ LOG_ERROR("thread manager error: "
+ "failed to allocate aux stack space for new thread");
+ goto fail3;
+ }
+
+ /* Set aux stack for current thread */
+ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
+ aux_stack_size)) {
+ goto fail4;
+ }
+
+ /* Inherit suspend_flags of parent thread */
+ new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags;
+
+ if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
+ goto fail4;
+
+ os_mutex_unlock(&cluster->lock);
+
+ return new_exec_env;
+
+fail4:
+ /* free the allocated aux stack space */
+ free_aux_stack(exec_env, aux_stack_start);
+fail3:
+ wasm_exec_env_destroy_internal(new_exec_env);
+fail2:
+ wasm_runtime_deinstantiate_internal(new_module_inst, true);
+fail1:
+ os_mutex_unlock(&cluster->lock);
+
+ return NULL;
+}
+
+void
+wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(cluster != NULL);
+
+ os_mutex_lock(&cluster->lock);
+
+ /* Free aux stack space */
+ free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
+ /* Remove exec_env */
+ wasm_cluster_del_exec_env_internal(cluster, exec_env, false);
+ /* Destroy exec_env */
+ wasm_exec_env_destroy_internal(exec_env);
+ /* Routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ os_mutex_unlock(&cluster->lock);
+}
+
+/* start routine of thread manager */
+static void *
+thread_manager_start_routine(void *arg)
+{
+ void *ret;
+ WASMExecEnv *exec_env = (WASMExecEnv *)arg;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+
+ bh_assert(cluster != NULL);
+ bh_assert(module_inst != NULL);
+
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->handle = os_self_thread();
+ /* Notify the parent thread to continue running */
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ ret = exec_env->thread_start_routine(exec_env);
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_mutex_lock(&exec_env->wait_lock);
+ if (exec_env->suspend_flags.flags & 0x08)
+ ret = exec_env->thread_ret_value;
+ os_mutex_unlock(&exec_env->wait_lock);
+#endif
+
+ /* Routine exit */
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_thread_exited(exec_env);
+#endif
+
+ os_mutex_lock(&cluster_list_lock);
+
+ os_mutex_lock(&cluster->lock);
+
+ /* Detach the native thread here to ensure the resources are freed */
+ if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
+ /* Only detach current thread when there is no other thread
+ joining it, otherwise let the system resources for the
+ thread be released after joining */
+ os_thread_detach(exec_env->handle);
+ /* No need to set exec_env->thread_is_detached to true here
+ since we will exit soon */
+ }
+
+ /* Free aux stack space */
+ free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
+ /* Remove exec_env */
+ wasm_cluster_del_exec_env_internal(cluster, exec_env, false);
+ /* Destroy exec_env */
+ wasm_exec_env_destroy_internal(exec_env);
+ /* Routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ os_mutex_unlock(&cluster->lock);
+
+ os_mutex_unlock(&cluster_list_lock);
+
+ os_thread_exit(ret);
+ return ret;
+}
+
+int32
+wasm_cluster_create_thread(WASMExecEnv *exec_env,
+ wasm_module_inst_t module_inst, bool alloc_aux_stack,
+ void *(*thread_routine)(void *), void *arg)
+{
+ WASMCluster *cluster;
+ WASMExecEnv *new_exec_env;
+ uint32 aux_stack_start = 0, aux_stack_size;
+ korp_tid tid;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ os_mutex_lock(&cluster->lock);
+
+ if (cluster->has_exception || cluster->processing) {
+ goto fail1;
+ }
+
+ new_exec_env =
+ wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size);
+ if (!new_exec_env)
+ goto fail1;
+
+ if (alloc_aux_stack) {
+ if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
+ LOG_ERROR("thread manager error: "
+ "failed to allocate aux stack space for new thread");
+ goto fail2;
+ }
+
+ /* Set aux stack for current thread */
+ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
+ aux_stack_size)) {
+ goto fail3;
+ }
+ }
+ else {
+ /* Disable aux stack */
+ new_exec_env->aux_stack_boundary.boundary = 0;
+ new_exec_env->aux_stack_bottom.bottom = UINT32_MAX;
+ }
+
+ /* Inherit suspend_flags of parent thread */
+ new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags;
+
+ if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
+ goto fail3;
+
+ new_exec_env->thread_start_routine = thread_routine;
+ new_exec_env->thread_arg = arg;
+
+ os_mutex_lock(&new_exec_env->wait_lock);
+
+ if (0
+ != os_thread_create(&tid, thread_manager_start_routine,
+ (void *)new_exec_env,
+ APP_THREAD_STACK_SIZE_DEFAULT)) {
+ os_mutex_unlock(&new_exec_env->wait_lock);
+ goto fail4;
+ }
+
+ /* Wait until the new_exec_env->handle is set to avoid it is
+ illegally accessed after unlocking cluster->lock */
+ os_cond_wait(&new_exec_env->wait_cond, &new_exec_env->wait_lock);
+ os_mutex_unlock(&new_exec_env->wait_lock);
+
+ os_mutex_unlock(&cluster->lock);
+
+ return 0;
+
+fail4:
+ wasm_cluster_del_exec_env_internal(cluster, new_exec_env, false);
+fail3:
+ /* free the allocated aux stack space */
+ if (alloc_aux_stack)
+ free_aux_stack(exec_env, aux_stack_start);
+fail2:
+ wasm_exec_env_destroy_internal(new_exec_env);
+fail1:
+ os_mutex_unlock(&cluster->lock);
+
+ return -1;
+}
+
+bool
+wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
+ const WASMModuleInstanceCommon *module_inst_src)
+{
+ /* workaround about passing instantiate-linking information */
+ CApiFuncImport **new_c_api_func_imports = NULL;
+ CApiFuncImport *c_api_func_imports;
+ uint32 import_func_count = 0;
+ uint32 size_in_bytes = 0;
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_src->module_type == Wasm_Module_Bytecode) {
+ new_c_api_func_imports =
+ &(((WASMModuleInstance *)module_inst_dst)->e->c_api_func_imports);
+ c_api_func_imports = ((const WASMModuleInstance *)module_inst_src)
+ ->e->c_api_func_imports;
+ import_func_count =
+ ((WASMModule *)(((const WASMModuleInstance *)module_inst_src)
+ ->module))
+ ->import_function_count;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_src->module_type == Wasm_Module_AoT) {
+ AOTModuleInstanceExtra *e =
+ (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e;
+ new_c_api_func_imports = &(e->c_api_func_imports);
+
+ e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e;
+ c_api_func_imports = e->c_api_func_imports;
+
+ import_func_count =
+ ((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module))
+ ->import_func_count;
+ }
+#endif
+
+ if (import_func_count != 0 && c_api_func_imports) {
+ size_in_bytes = sizeof(CApiFuncImport) * import_func_count;
+ *new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes);
+ if (!(*new_c_api_func_imports))
+ return false;
+
+ bh_memcpy_s(*new_c_api_func_imports, size_in_bytes, c_api_func_imports,
+ size_in_bytes);
+ }
+ return true;
+}
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+WASMCurrentEnvStatus *
+wasm_cluster_create_exenv_status()
+{
+ WASMCurrentEnvStatus *status;
+
+ if (!(status = wasm_runtime_malloc(sizeof(WASMCurrentEnvStatus)))) {
+ return NULL;
+ }
+
+ status->step_count = 0;
+ status->signal_flag = 0;
+ status->running_status = 0;
+ return status;
+}
+
+void
+wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status)
+{
+ wasm_runtime_free(status);
+}
+
+inline static bool
+wasm_cluster_thread_is_running(WASMExecEnv *exec_env)
+{
+ return exec_env->current_status->running_status == STATUS_RUNNING
+ || exec_env->current_status->running_status == STATUS_STEP;
+}
+
+void
+wasm_cluster_clear_thread_signal(WASMExecEnv *exec_env)
+{
+ exec_env->current_status->signal_flag = 0;
+}
+
+void
+wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo)
+{
+ exec_env->current_status->signal_flag = signo;
+}
+
+static void
+notify_debug_instance(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ if (!cluster->debug_inst) {
+ return;
+ }
+
+ on_thread_stop_event(cluster->debug_inst, exec_env);
+}
+
+static void
+notify_debug_instance_exit(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ if (!cluster->debug_inst) {
+ return;
+ }
+
+ on_thread_exit_event(cluster->debug_inst, exec_env);
+}
+
+void
+wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env)
+{
+ exec_env->current_status->running_status = STATUS_STOP;
+ notify_debug_instance(exec_env);
+
+ while (!wasm_cluster_thread_is_running(exec_env)) {
+ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock);
+ }
+}
+
+void
+wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo)
+{
+ WASMExecEnv *exec_env = bh_list_first_elem(&cluster->exec_env_list);
+ while (exec_env) {
+ wasm_cluster_thread_send_signal(exec_env, signo);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+}
+
+void
+wasm_cluster_thread_exited(WASMExecEnv *exec_env)
+{
+ exec_env->current_status->running_status = STATUS_EXIT;
+ notify_debug_instance_exit(exec_env);
+}
+
+void
+wasm_cluster_thread_continue(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+ wasm_cluster_clear_thread_signal(exec_env);
+ exec_env->current_status->running_status = STATUS_RUNNING;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+}
+
+void
+wasm_cluster_thread_step(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->current_status->running_status = STATUS_STEP;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+}
+
+void
+wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst)
+{
+ cluster->debug_inst = inst;
+}
+
+#endif /* end of WASM_ENABLE_DEBUG_INTERP */
+
+/* Check whether the exec_env is in one of all clusters, the caller
+ should add lock to the cluster list before calling us */
+static bool
+clusters_have_exec_env(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster = bh_list_first_elem(cluster_list);
+ WASMExecEnv *node;
+
+ while (cluster) {
+ os_mutex_lock(&cluster->lock);
+ node = bh_list_first_elem(&cluster->exec_env_list);
+
+ while (node) {
+ if (node == exec_env) {
+ bh_assert(exec_env->cluster == cluster);
+ os_mutex_unlock(&cluster->lock);
+ return true;
+ }
+ node = bh_list_elem_next(node);
+ }
+ os_mutex_unlock(&cluster->lock);
+
+ cluster = bh_list_elem_next(cluster);
+ }
+
+ return false;
+}
+
+int32
+wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val)
+{
+ korp_tid handle;
+
+ os_mutex_lock(&cluster_list_lock);
+
+ if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
+ /* Invalid thread, thread has exited or thread has been detached */
+ if (ret_val)
+ *ret_val = NULL;
+ os_mutex_unlock(&cluster_list_lock);
+ return 0;
+ }
+
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->wait_count++;
+ handle = exec_env->handle;
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ os_mutex_unlock(&cluster_list_lock);
+
+ return os_thread_join(handle, ret_val);
+}
+
+int32
+wasm_cluster_detach_thread(WASMExecEnv *exec_env)
+{
+ int32 ret = 0;
+
+ os_mutex_lock(&cluster_list_lock);
+ if (!clusters_have_exec_env(exec_env)) {
+ /* Invalid thread or the thread has exited */
+ os_mutex_unlock(&cluster_list_lock);
+ return 0;
+ }
+ if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
+ /* Only detach current thread when there is no other thread
+ joining it, otherwise let the system resources for the
+ thread be released after joining */
+ ret = os_thread_detach(exec_env->handle);
+ exec_env->thread_is_detached = true;
+ }
+ os_mutex_unlock(&cluster_list_lock);
+ return ret;
+}
+
+void
+wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
+{
+ WASMCluster *cluster;
+ WASMModuleInstanceCommon *module_inst;
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env->jmpbuf_stack_top) {
+ /* Store the return value in exec_env */
+ exec_env->thread_ret_value = retval;
+ exec_env->suspend_flags.flags |= 0x08;
+
+#ifndef BH_PLATFORM_WINDOWS
+ /* Pop all jmpbuf_node except the last one */
+ while (exec_env->jmpbuf_stack_top->prev) {
+ wasm_exec_env_pop_jmpbuf(exec_env);
+ }
+ os_longjmp(exec_env->jmpbuf_stack_top->jmpbuf, 1);
+ return;
+#endif
+ }
+#endif
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_clear_thread_signal(exec_env);
+ wasm_cluster_thread_exited(exec_env);
+#endif
+
+ /* App exit the thread, free the resources before exit native thread */
+
+ os_mutex_lock(&cluster_list_lock);
+
+ os_mutex_lock(&cluster->lock);
+
+ /* Detach the native thread here to ensure the resources are freed */
+ if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
+ /* Only detach current thread when there is no other thread
+ joining it, otherwise let the system resources for the
+ thread be released after joining */
+ os_thread_detach(exec_env->handle);
+ /* No need to set exec_env->thread_is_detached to true here
+ since we will exit soon */
+ }
+
+ module_inst = exec_env->module_inst;
+
+ /* Free aux stack space */
+ free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
+ /* Remove exec_env */
+ wasm_cluster_del_exec_env_internal(cluster, exec_env, false);
+ /* Destroy exec_env */
+ wasm_exec_env_destroy_internal(exec_env);
+ /* Routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ os_mutex_unlock(&cluster->lock);
+
+ os_mutex_unlock(&cluster_list_lock);
+
+ os_thread_exit(retval);
+}
+
+static void
+set_thread_cancel_flags(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
+#endif
+ exec_env->suspend_flags.flags |= 0x01;
+
+ os_mutex_unlock(&exec_env->wait_lock);
+}
+
+int32
+wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster_list_lock);
+
+ if (!exec_env->cluster) {
+ os_mutex_unlock(&cluster_list_lock);
+ return 0;
+ }
+
+ if (!clusters_have_exec_env(exec_env)) {
+ /* Invalid thread or the thread has exited */
+ goto final;
+ }
+
+ set_thread_cancel_flags(exec_env);
+
+final:
+ os_mutex_unlock(&cluster_list_lock);
+
+ return 0;
+}
+
+static void
+terminate_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+
+ if (curr_exec_env == exec_env)
+ return;
+
+ wasm_cluster_cancel_thread(curr_exec_env);
+ wasm_cluster_join_thread(curr_exec_env, NULL);
+}
+
+void
+wasm_cluster_terminate_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, terminate_thread_visitor, NULL);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, terminate_thread_visitor,
+ (void *)exec_env);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+static void
+wait_for_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+
+ if (curr_exec_env == exec_env)
+ return;
+
+ wasm_cluster_join_thread(curr_exec_env, NULL);
+}
+
+void
+wams_cluster_wait_for_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, wait_for_thread_visitor, NULL);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, wait_for_thread_visitor,
+ (void *)exec_env);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+bool
+wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *))
+{
+ DestroyCallBackNode *node;
+
+ if (!(node = wasm_runtime_malloc(sizeof(DestroyCallBackNode)))) {
+ LOG_ERROR("thread manager error: failed to allocate memory");
+ return false;
+ }
+ node->destroy_cb = callback;
+ bh_list_insert(destroy_callback_list, node);
+ return true;
+}
+
+void
+wasm_cluster_suspend_thread(WASMExecEnv *exec_env)
+{
+ /* Set the suspend flag */
+ exec_env->suspend_flags.flags |= 0x02;
+}
+
+static void
+suspend_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+
+ if (curr_exec_env == exec_env)
+ return;
+
+ wasm_cluster_suspend_thread(curr_exec_env);
+}
+
+void
+wasm_cluster_suspend_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL);
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, suspend_thread_visitor,
+ (void *)exec_env);
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_resume_thread(WASMExecEnv *exec_env)
+{
+ exec_env->suspend_flags.flags &= ~0x02;
+ os_cond_signal(&exec_env->wait_cond);
+}
+
+static void
+resume_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+
+ wasm_cluster_resume_thread(curr_exec_env);
+}
+
+void
+wasm_cluster_resume_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, resume_thread_visitor, NULL);
+ os_mutex_unlock(&cluster->lock);
+}
+
+static void
+set_exception_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+ WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
+ WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
+
+ if (curr_exec_env != exec_env) {
+ WASMModuleInstance *curr_wasm_inst =
+ (WASMModuleInstance *)get_module_inst(curr_exec_env);
+
+ /* Only spread non "wasi proc exit" exception */
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
+ (WASMModuleCommon *)curr_wasm_inst->module);
+ if (shared_mem_node)
+ os_mutex_lock(&shared_mem_node->shared_mem_lock);
+#endif
+ if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
+ bh_memcpy_s(curr_wasm_inst->cur_exception,
+ sizeof(curr_wasm_inst->cur_exception),
+ wasm_inst->cur_exception,
+ sizeof(wasm_inst->cur_exception));
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (shared_mem_node)
+ os_mutex_unlock(&shared_mem_node->shared_mem_lock);
+#endif
+
+ /* Terminate the thread so it can exit from dead loops */
+ set_thread_cancel_flags(curr_exec_env);
+ }
+}
+
+static void
+clear_exception_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+
+ if (curr_exec_env != exec_env) {
+ WASMModuleInstance *curr_wasm_inst =
+ (WASMModuleInstance *)get_module_inst(curr_exec_env);
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
+ (WASMModuleCommon *)curr_wasm_inst->module);
+ if (shared_mem_node)
+ os_mutex_lock(&shared_mem_node->shared_mem_lock);
+#endif
+ curr_wasm_inst->cur_exception[0] = '\0';
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (shared_mem_node)
+ os_mutex_unlock(&shared_mem_node->shared_mem_lock);
+#endif
+ }
+}
+
+void
+wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ os_mutex_lock(&cluster->lock);
+ cluster->has_exception = !clear;
+ traverse_list(&cluster->exec_env_list,
+ clear ? clear_exception_visitor : set_exception_visitor,
+ exec_env);
+ os_mutex_unlock(&cluster->lock);
+}
+
+static void
+set_custom_data_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
+
+ wasm_runtime_set_custom_data_internal(module_inst, user_data);
+}
+
+void
+wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
+ void *custom_data)
+{
+ WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
+
+ if (exec_env == NULL) {
+ /* Maybe threads have not been started yet. */
+ wasm_runtime_set_custom_data_internal(module_inst, custom_data);
+ }
+ else {
+ WASMCluster *cluster;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, set_custom_data_visitor,
+ custom_data);
+ os_mutex_unlock(&cluster->lock);
+ }
+}
+
+bool
+wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+ bool is_thread_terminated =
+ (exec_env->suspend_flags.flags & 0x01) ? true : false;
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ return is_thread_terminated;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h
new file mode 100644
index 000000000..2060869c2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _THREAD_MANAGER_H
+#define _THREAD_MANAGER_H
+
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+#include "../common/wasm_runtime_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+typedef struct WASMDebugInstance WASMDebugInstance;
+#endif
+
+struct WASMCluster {
+ struct WASMCluster *next;
+
+ korp_mutex lock;
+ bh_list exec_env_list;
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ /* The aux stack of a module with shared memory will be
+ divided into several segments. This array store the
+ stack top of different segments */
+ uint32 *stack_tops;
+ /* Record which segments are occupied */
+ bool *stack_segment_occupied;
+#endif
+ /* Size of every stack segment */
+ uint32 stack_size;
+ /* When has_exception == true, this cluster should refuse any spawn thread
+ * requests, this flag can be cleared by calling
+ * wasm_runtime_clear_exception on instances of any threads of this cluster
+ */
+ bool has_exception;
+ /* When processing is true, this cluster should refuse any spawn thread
+ * requests. This is a short-lived state, must be cleared immediately once
+ * the processing finished.
+ * This is used to avoid dead lock when one thread waiting another thread
+ * with lock, see wams_cluster_wait_for_all and wasm_cluster_terminate_all
+ */
+ bool processing;
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ WASMDebugInstance *debug_inst;
+#endif
+};
+
+void
+wasm_cluster_set_max_thread_num(uint32 num);
+
+bool
+thread_manager_init();
+
+void
+thread_manager_destroy();
+
+/* Create cluster */
+WASMCluster *
+wasm_cluster_create(WASMExecEnv *exec_env);
+
+/* Destroy cluster */
+void
+wasm_cluster_destroy(WASMCluster *cluster);
+
+/* Get the cluster of the current exec_env */
+WASMCluster *
+wasm_exec_env_get_cluster(WASMExecEnv *exec_env);
+
+/* Forward registered functions to a new thread */
+bool
+wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
+ const WASMModuleInstanceCommon *module_inst_src);
+
+int32
+wasm_cluster_create_thread(WASMExecEnv *exec_env,
+ wasm_module_inst_t module_inst, bool alloc_aux_stack,
+ void *(*thread_routine)(void *), void *arg);
+
+int32
+wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val);
+
+int32
+wasm_cluster_detach_thread(WASMExecEnv *exec_env);
+
+int32
+wasm_cluster_cancel_thread(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval);
+
+bool
+wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *));
+
+void
+wasm_cluster_cancel_all_callbacks();
+
+void
+wasm_cluster_suspend_all(WASMCluster *cluster);
+
+void
+wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env);
+
+void
+wasm_cluster_suspend_thread(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_resume_thread(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_resume_all(WASMCluster *cluster);
+
+void
+wasm_cluster_terminate_all(WASMCluster *cluster);
+
+void
+wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env);
+
+void
+wams_cluster_wait_for_all(WASMCluster *cluster);
+
+void
+wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env);
+
+bool
+wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env);
+
+WASMExecEnv *
+wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
+
+void
+wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear);
+
+WASMExecEnv *
+wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
+ void *custom_data);
+
+bool
+wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#define WAMR_SIG_TRAP (5)
+#define WAMR_SIG_STOP (19)
+#define WAMR_SIG_TERM (15)
+#define WAMR_SIG_SINGSTEP (0x1ff)
+
+#define STATUS_RUNNING (0)
+#define STATUS_STOP (1)
+#define STATUS_EXIT (2)
+#define STATUS_STEP (3)
+
+#define IS_WAMR_TERM_SIG(signo) ((signo) == WAMR_SIG_TERM)
+
+#define IS_WAMR_STOP_SIG(signo) \
+ ((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP)
+
+struct WASMCurrentEnvStatus {
+ uint64 signal_flag : 32;
+ uint64 step_count : 16;
+ uint64 running_status : 16;
+};
+
+WASMCurrentEnvStatus *
+wasm_cluster_create_exenv_status();
+
+void
+wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status);
+
+void
+wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo);
+
+/* This function must be called with exec_env->wait_lock locked, otherwise we
+ * may miss the signal from debugger thread, see
+ * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1860 */
+void
+wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status);
+
+void
+wasm_cluster_thread_exited(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_thread_continue(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo);
+
+void
+wasm_cluster_thread_step(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst);
+
+#endif /* end of WASM_ENABLE_DEBUG_INTERP != 0 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _THREAD_MANAGER_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake
new file mode 100644
index 000000000..c37a336b4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (THREAD_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_THREAD_MGR=1)
+
+include_directories(${THREAD_MGR_DIR})
+
+file (GLOB source_all ${THREAD_MGR_DIR}/*.c)
+
+set (THREAD_MGR_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md
new file mode 100644
index 000000000..ac737c281
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md
@@ -0,0 +1,96 @@
+# WASI-NN
+
+## How to use
+
+Enable WASI-NN in the WAMR by spefiying it in the cmake building configuration as follows,
+
+```
+set (WAMR_BUILD_WASI_NN 1)
+```
+
+The definition of the functions provided by WASI-NN is in the header file `core/iwasm/libraries/wasi-nn/wasi_nn.h`.
+
+By only including this file in your WASM application you will bind WASI-NN into your module.
+
+## Tests
+
+To run the tests we assume that the current directory is the root of the repository.
+
+
+### Build the runtime
+
+Build the runtime image for your execution target type.
+
+`EXECUTION_TYPE` can be:
+* `cpu`
+* `nvidia-gpu`
+* `vx-delegate`
+
+```
+EXECUTION_TYPE=cpu
+docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} .
+```
+
+
+### Build wasm app
+
+```
+docker build -t wasi-nn-compile -f core/iwasm/libraries/wasi-nn/test/Dockerfile.compile .
+```
+
+```
+docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile
+```
+
+
+### Run wasm app
+
+If all the tests have run properly you will the the following message in the terminal,
+
+```
+Tests: passed!
+```
+
+* CPU
+
+```
+docker run \
+ -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-cpu \
+ --dir=/assets \
+ --env="TARGET=cpu" \
+ /assets/test_tensorflow.wasm
+```
+
+* (NVIDIA) GPU
+
+```
+docker run \
+ --runtime=nvidia \
+ -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-nvidia-gpu \
+ --dir=/assets \
+ --env="TARGET=gpu" \
+ /assets/test_tensorflow.wasm
+```
+
+* vx-delegate for NPU (x86 simulater)
+
+```
+docker run \
+ -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-vx-delegate \
+ --dir=/assets \
+ --env="TARGET=gpu" \
+ /assets/test_tensorflow.wasm
+```
+
+
+
+Requirements:
+* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
+
+## What is missing
+
+Supported:
+
+* Graph encoding: `tensorflowlite`.
+* Execution target: `cpu` and `gpu`.
+* Tensor type: `fp32`.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake
new file mode 100644
index 000000000..bbeac3b14
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake
@@ -0,0 +1,41 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+find_library(TENSORFLOW_LITE
+ NAMES tensorflow-lite
+)
+
+if(NOT EXISTS ${TENSORFLOW_LITE})
+ if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
+ execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh
+ RESULT_VARIABLE TENSORFLOW_RESULT
+ )
+ else ()
+ message("Tensorflow is already downloaded.")
+ endif()
+ set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
+
+ if (WASI_NN_ENABLE_GPU EQUAL 1)
+ # Tensorflow specific:
+ # * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite
+ set (TFLITE_ENABLE_GPU ON)
+ endif ()
+
+ include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
+ include_directories (${TENSORFLOW_SOURCE_DIR})
+ add_subdirectory(
+ "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite"
+ "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL)
+
+else()
+ find_path(TENSORFLOW_LITE_INCLUDE_DIR
+ NAMES tensorflow/lite/interpreter.h
+ )
+ find_path(FLATBUFFER_INCLUDE_DIR
+ NAMES flatbuffers/flatbuffers.h
+ )
+ include_directories (${TENSORFLOW_LITE_INCLUDE_DIR})
+ include_directories (${FLATBUFFER_INCLUDE_DIR})
+endif()
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h
new file mode 100644
index 000000000..a196429a0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_LOGGER_H
+#define WASI_NN_LOGGER_H
+
+#include <stdio.h>
+#include <string.h>
+
+#define __FILENAME__ \
+ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+/* Disable a level by removing the define */
+#ifndef NN_LOG_LEVEL
+/*
+ 0 -> debug, info, warn, err
+ 1 -> info, warn, err
+ 2 -> warn, err
+ 3 -> err
+ 4 -> NO LOGS
+*/
+#define NN_LOG_LEVEL 0
+#endif
+
+// Definition of the levels
+#if NN_LOG_LEVEL <= 3
+#define NN_ERR_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d ERROR] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_ERR_PRINTF(fmt, ...)
+#endif
+#if NN_LOG_LEVEL <= 2
+#define NN_WARN_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d WARNING] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_WARN_PRINTF(fmt, ...)
+#endif
+#if NN_LOG_LEVEL <= 1
+#define NN_INFO_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d INFO] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_INFO_PRINTF(fmt, ...)
+#endif
+#if NN_LOG_LEVEL <= 0
+#define NN_DBG_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d DEBUG] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_DBG_PRINTF(fmt, ...)
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
new file mode 100644
index 000000000..fe04b657b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasi_nn_app_native.h"
+
+static error
+graph_builder_app_native(wasm_module_inst_t instance,
+ graph_builder_wasm *builder_wasm,
+ graph_builder *builder)
+{
+ if (!wasm_runtime_validate_app_addr(instance, builder_wasm->buf_offset,
+ builder_wasm->size * sizeof(uint8_t))) {
+ NN_ERR_PRINTF("builder_wasm->buf_offset is invalid");
+ return invalid_argument;
+ }
+
+ builder->buf = (uint8_t *)wasm_runtime_addr_app_to_native(
+ instance, builder_wasm->buf_offset);
+ builder->size = builder_wasm->size;
+ return success;
+}
+
+error
+graph_builder_array_app_native(wasm_module_inst_t instance,
+ graph_builder_array_wasm *builder_array_wasm,
+ graph_builder_array *builder_array)
+{
+ if (!wasm_runtime_validate_native_addr(instance, builder_array_wasm,
+ sizeof(graph_builder_array_wasm))) {
+ NN_ERR_PRINTF("builder_array_wasm is invalid");
+ return invalid_argument;
+ }
+
+ NN_DBG_PRINTF("Graph builder array contains %d elements",
+ builder_array_wasm->size);
+
+ if (!wasm_runtime_validate_app_addr(
+ instance, builder_array_wasm->buf_offset,
+ builder_array_wasm->size * sizeof(graph_builder_wasm))) {
+ NN_ERR_PRINTF("builder_array_wasm->buf_offset is invalid");
+ return invalid_argument;
+ }
+
+ graph_builder_wasm *builder_wasm =
+ (graph_builder_wasm *)wasm_runtime_addr_app_to_native(
+ instance, builder_array_wasm->buf_offset);
+
+ graph_builder *builder = (graph_builder *)wasm_runtime_malloc(
+ builder_array_wasm->size * sizeof(graph_builder));
+ if (builder == NULL)
+ return missing_memory;
+
+ for (uint32_t i = 0; i < builder_array_wasm->size; ++i) {
+ error res;
+ if (success
+ != (res = graph_builder_app_native(instance, &builder_wasm[i],
+ &builder[i]))) {
+ wasm_runtime_free(builder);
+ return res;
+ }
+
+ NN_DBG_PRINTF("Graph builder %d contains %d elements", i,
+ builder->size);
+ }
+
+ builder_array->buf = builder;
+ builder_array->size = builder_array_wasm->size;
+ return success;
+}
+
+static error
+tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
+ tensor_wasm *input_tensor_wasm, tensor_data *data)
+{
+ if (!wasm_runtime_validate_app_addr(
+ instance, input_tensor_wasm->data_offset, total_elements)) {
+ NN_ERR_PRINTF("input_tensor_wasm->data_offset is invalid");
+ return invalid_argument;
+ }
+ *data = (tensor_data)wasm_runtime_addr_app_to_native(
+ instance, input_tensor_wasm->data_offset);
+ return success;
+}
+
+static error
+tensor_dimensions_app_native(wasm_module_inst_t instance,
+ tensor_wasm *input_tensor_wasm,
+ tensor_dimensions **dimensions)
+{
+ if (!wasm_runtime_validate_app_addr(instance,
+ input_tensor_wasm->dimensions_offset,
+ sizeof(tensor_dimensions_wasm))) {
+ NN_ERR_PRINTF("input_tensor_wasm->dimensions_offset is invalid");
+ return invalid_argument;
+ }
+
+ tensor_dimensions_wasm *dimensions_wasm =
+ (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native(
+ instance, input_tensor_wasm->dimensions_offset);
+
+ if (!wasm_runtime_validate_app_addr(instance, dimensions_wasm->buf_offset,
+ sizeof(tensor_dimensions))) {
+ NN_ERR_PRINTF("dimensions_wasm->buf_offset is invalid");
+ return invalid_argument;
+ }
+
+ *dimensions =
+ (tensor_dimensions *)wasm_runtime_malloc(sizeof(tensor_dimensions));
+ if (dimensions == NULL)
+ return missing_memory;
+
+ (*dimensions)->size = dimensions_wasm->size;
+ (*dimensions)->buf = (uint32_t *)wasm_runtime_addr_app_to_native(
+ instance, dimensions_wasm->buf_offset);
+
+ NN_DBG_PRINTF("Number of dimensions: %d", (*dimensions)->size);
+ return success;
+}
+
+error
+tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
+ tensor *input_tensor)
+{
+ NN_DBG_PRINTF("Converting tensor_wasm to tensor");
+ if (!wasm_runtime_validate_native_addr(instance, input_tensor_wasm,
+ sizeof(tensor_wasm))) {
+ NN_ERR_PRINTF("input_tensor_wasm is invalid");
+ return invalid_argument;
+ }
+
+ error res;
+
+ tensor_dimensions *dimensions = NULL;
+ if (success
+ != (res = tensor_dimensions_app_native(instance, input_tensor_wasm,
+ &dimensions))) {
+ NN_ERR_PRINTF("error when parsing dimensions");
+ return res;
+ }
+
+ uint32_t total_elements = 1;
+ for (uint32_t i = 0; i < dimensions->size; ++i) {
+ total_elements *= dimensions->buf[i];
+ NN_DBG_PRINTF("Dimension %d: %d", i, dimensions->buf[i]);
+ }
+ NN_DBG_PRINTF("Tensor type: %d", input_tensor_wasm->type);
+ NN_DBG_PRINTF("Total number of elements: %d", total_elements);
+
+ tensor_data data = NULL;
+ if (success
+ != (res = tensor_data_app_native(instance, total_elements,
+ input_tensor_wasm, &data))) {
+ wasm_runtime_free(dimensions);
+ return res;
+ }
+
+ input_tensor->type = input_tensor_wasm->type;
+ input_tensor->dimensions = dimensions;
+ input_tensor->data = data;
+ return success;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
new file mode 100644
index 000000000..15154bd31
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_APP_NATIVE
+#define WASI_NN_APP_NATIVE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "wasi_nn.h"
+#include "logger.h"
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+typedef struct {
+ uint32_t buf_offset;
+ uint32_t size;
+} graph_builder_wasm;
+
+typedef struct {
+ uint32_t buf_offset;
+ uint32_t size;
+} graph_builder_array_wasm;
+
+typedef struct {
+ uint32_t buf_offset;
+ uint32_t size;
+} tensor_dimensions_wasm;
+
+typedef struct {
+ uint32_t dimensions_offset;
+ tensor_type type;
+ uint32_t data_offset;
+} tensor_wasm;
+
+error
+graph_builder_array_app_native(wasm_module_inst_t instance,
+ graph_builder_array_wasm *builder,
+ graph_builder_array *builder_native);
+
+error
+tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor,
+ tensor *input_tensor_native);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c
new file mode 100644
index 000000000..466630f99
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "wasi_nn.h"
+#include "wasi_nn_app_native.h"
+#include "logger.h"
+#include "wasi_nn_tensorflowlite.hpp"
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+#include "wasm_runtime.h"
+#include "aot_runtime.h"
+
+/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
+
+typedef error (*LOAD)(void *, graph_builder_array *, graph_encoding,
+ execution_target, graph *);
+typedef error (*INIT_EXECUTION_CONTEXT)(void *, graph,
+ graph_execution_context *);
+typedef error (*SET_INPUT)(void *, graph_execution_context, uint32_t, tensor *);
+typedef error (*COMPUTE)(void *, graph_execution_context);
+typedef error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t,
+ tensor_data, uint32_t *);
+
+typedef struct {
+ LOAD load;
+ INIT_EXECUTION_CONTEXT init_execution_context;
+ SET_INPUT set_input;
+ COMPUTE compute;
+ GET_OUTPUT get_output;
+} api_function;
+
+/* Global variables */
+
+static api_function lookup[] = {
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { tensorflowlite_load, tensorflowlite_init_execution_context,
+ tensorflowlite_set_input, tensorflowlite_compute,
+ tensorflowlite_get_output }
+};
+
+/* Utils */
+
+static bool
+is_encoding_implemented(graph_encoding encoding)
+{
+ return lookup[encoding].load && lookup[encoding].init_execution_context
+ && lookup[encoding].set_input && lookup[encoding].compute
+ && lookup[encoding].get_output;
+}
+
+static error
+is_model_initialized(WASINNContext *wasi_nn_ctx)
+{
+ if (!wasi_nn_ctx->is_initialized) {
+ NN_ERR_PRINTF("Model not initialized.");
+ return runtime_error;
+ }
+ return success;
+}
+
+WASINNContext *
+wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance)
+{
+ WASINNContext *wasi_nn_ctx = NULL;
+#if WASM_ENABLE_INTERP != 0
+ if (instance->module_type == Wasm_Module_Bytecode) {
+ NN_DBG_PRINTF("Getting ctx from WASM");
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)instance;
+ wasi_nn_ctx = ((WASMModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (instance->module_type == Wasm_Module_AoT) {
+ NN_DBG_PRINTF("Getting ctx from AOT");
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)instance;
+ wasi_nn_ctx = ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+ }
+#endif
+ bh_assert(wasi_nn_ctx != NULL);
+ NN_DBG_PRINTF("Returning ctx");
+ return wasi_nn_ctx;
+}
+
+/* WASI-NN implementation */
+
+error
+wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
+ graph_encoding encoding, execution_target target, graph *g)
+{
+ NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding,
+ target);
+
+ if (!is_encoding_implemented(encoding)) {
+ NN_ERR_PRINTF("Encoding not supported.");
+ return invalid_encoding;
+ }
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+
+ error res;
+ graph_builder_array builder_native = { 0 };
+ if (success
+ != (res = graph_builder_array_app_native(instance, builder,
+ &builder_native)))
+ return res;
+
+ if (!wasm_runtime_validate_native_addr(instance, g, sizeof(graph))) {
+ NN_ERR_PRINTF("graph is invalid");
+ res = invalid_argument;
+ goto fail;
+ }
+
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+ res = lookup[encoding].load(wasi_nn_ctx->tflite_ctx, &builder_native,
+ encoding, target, g);
+
+ NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res, *g);
+
+ wasi_nn_ctx->current_encoding = encoding;
+ wasi_nn_ctx->is_initialized = true;
+
+fail:
+ // XXX: Free intermediate structure pointers
+ if (builder_native.buf)
+ wasm_runtime_free(builder_native.buf);
+
+ return res;
+}
+
+error
+wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
+ graph_execution_context *ctx)
+{
+ NN_DBG_PRINTF("Running wasi_nn_init_execution_context [graph=%d]...", g);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ if (!wasm_runtime_validate_native_addr(instance, ctx,
+ sizeof(graph_execution_context))) {
+ NN_ERR_PRINTF("ctx is invalid");
+ return invalid_argument;
+ }
+
+ res = lookup[wasi_nn_ctx->current_encoding].init_execution_context(
+ wasi_nn_ctx->tflite_ctx, g, ctx);
+
+ NN_DBG_PRINTF(
+ "wasi_nn_init_execution_context finished with status %d [ctx=%d]", res,
+ *ctx);
+ return res;
+}
+
+error
+wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
+ uint32_t index, tensor_wasm *input_tensor)
+{
+ NN_DBG_PRINTF("Running wasi_nn_set_input [ctx=%d, index=%d]...", ctx,
+ index);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ tensor input_tensor_native = { 0 };
+ if (success
+ != (res = tensor_app_native(instance, input_tensor,
+ &input_tensor_native)))
+ return res;
+
+ res = lookup[wasi_nn_ctx->current_encoding].set_input(
+ wasi_nn_ctx->tflite_ctx, ctx, index, &input_tensor_native);
+
+ // XXX: Free intermediate structure pointers
+ if (input_tensor_native.dimensions)
+ wasm_runtime_free(input_tensor_native.dimensions);
+
+ NN_DBG_PRINTF("wasi_nn_set_input finished with status %d", res);
+ return res;
+}
+
+error
+wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
+{
+ NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ res = lookup[wasi_nn_ctx->current_encoding].compute(wasi_nn_ctx->tflite_ctx,
+ ctx);
+ NN_DBG_PRINTF("wasi_nn_compute finished with status %d", res);
+ return res;
+}
+
+error
+wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
+ uint32_t index, tensor_data output_tensor,
+ uint32_t *output_tensor_size)
+{
+ NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx,
+ index);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ if (!wasm_runtime_validate_native_addr(instance, output_tensor_size,
+ sizeof(uint32_t))) {
+ NN_ERR_PRINTF("output_tensor_size is invalid");
+ return invalid_argument;
+ }
+
+ res = lookup[wasi_nn_ctx->current_encoding].get_output(
+ wasi_nn_ctx->tflite_ctx, ctx, index, output_tensor, output_tensor_size);
+ NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]",
+ res, *output_tensor_size);
+ return res;
+}
+
+/* Non-exposed public functions */
+
+WASINNContext *
+wasi_nn_initialize()
+{
+ NN_DBG_PRINTF("Initializing wasi-nn");
+ WASINNContext *wasi_nn_ctx =
+ (WASINNContext *)wasm_runtime_malloc(sizeof(WASINNContext));
+ if (wasi_nn_ctx == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for WASI-NN context");
+ return NULL;
+ }
+ wasi_nn_ctx->is_initialized = true;
+ wasi_nn_ctx->current_encoding = 3;
+ tensorflowlite_initialize(&wasi_nn_ctx->tflite_ctx);
+ return wasi_nn_ctx;
+}
+
+void
+wasi_nn_destroy(WASINNContext *wasi_nn_ctx)
+{
+ if (wasi_nn_ctx == NULL) {
+ NN_ERR_PRINTF(
+ "Error when deallocating memory. WASI-NN context is NULL");
+ return;
+ }
+ NN_DBG_PRINTF("Freeing wasi-nn");
+ NN_DBG_PRINTF("-> is_initialized: %d", wasi_nn_ctx->is_initialized);
+ NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->current_encoding);
+ tensorflowlite_destroy(wasi_nn_ctx->tflite_ctx);
+ wasm_runtime_free(wasi_nn_ctx);
+}
+
+/* Register WASI-NN in WAMR */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, wasi_nn_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_wasi_nn[] = {
+ REG_NATIVE_FUNC(load, "(*ii*)i"),
+ REG_NATIVE_FUNC(init_execution_context, "(i*)i"),
+ REG_NATIVE_FUNC(set_input, "(ii*)i"),
+ REG_NATIVE_FUNC(compute, "(i)i"),
+ REG_NATIVE_FUNC(get_output, "(ii**)i"),
+};
+
+uint32_t
+get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+ *p_libc_wasi_apis = native_symbols_wasi_nn;
+ return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
new file mode 100644
index 000000000..52d16bd1d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_PRIVATE_H
+#define WASI_NN_PRIVATE_H
+
+#include "wasi_nn_types.h"
+
+typedef struct {
+ bool is_initialized;
+ graph_encoding current_encoding;
+ void *tflite_ctx;
+} WASINNContext;
+
+/**
+ * @brief Initialize wasi-nn
+ *
+ */
+WASINNContext *
+wasi_nn_initialize();
+/**
+ * @brief Destroy wasi-nn on app exists
+ *
+ */
+
+void
+wasi_nn_destroy(WASINNContext *wasi_nn_ctx);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp
new file mode 100644
index 000000000..dfd21787c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasi_nn.h"
+#include "wasi_nn_tensorflowlite.hpp"
+#include "logger.h"
+
+#include "bh_common.h"
+#include "bh_platform.h"
+#include "platform_common.h"
+
+#include <tensorflow/lite/interpreter.h>
+#include <tensorflow/lite/kernels/register.h>
+#include <tensorflow/lite/model.h>
+#include <tensorflow/lite/optional_debug_tools.h>
+#include <tensorflow/lite/error_reporter.h>
+
+#if defined(WASI_NN_ENABLE_GPU)
+#include <tensorflow/lite/delegates/gpu/delegate.h>
+#endif
+
+#if defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
+#include <tensorflow/lite/delegates/external/external_delegate.h>
+#endif
+
+/* Maximum number of graphs per WASM instance */
+#define MAX_GRAPHS_PER_INST 10
+/* Maximum number of graph execution context per WASM instance*/
+#define MAX_GRAPH_EXEC_CONTEXTS_PER_INST 10
+
+typedef struct {
+ std::unique_ptr<tflite::Interpreter> interpreter;
+} Interpreter;
+
+typedef struct {
+ char *model_pointer;
+ std::unique_ptr<tflite::FlatBufferModel> model;
+ execution_target target;
+} Model;
+
+typedef struct {
+ uint32_t current_models;
+ Model models[MAX_GRAPHS_PER_INST];
+ uint32_t current_interpreters;
+ Interpreter interpreters[MAX_GRAPH_EXEC_CONTEXTS_PER_INST];
+ korp_mutex g_lock;
+ TfLiteDelegate *delegate;
+} TFLiteContext;
+
+/* Utils */
+
+static error
+initialize_g(TFLiteContext *tfl_ctx, graph *g)
+{
+ os_mutex_lock(&tfl_ctx->g_lock);
+ if (tfl_ctx->current_models == MAX_GRAPHS_PER_INST) {
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ NN_ERR_PRINTF("Excedded max graphs per WASM instance");
+ return runtime_error;
+ }
+ *g = tfl_ctx->current_models++;
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ return success;
+}
+static error
+initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
+ graph_execution_context *ctx)
+{
+ os_mutex_lock(&tfl_ctx->g_lock);
+ if (tfl_ctx->current_interpreters == MAX_GRAPH_EXEC_CONTEXTS_PER_INST) {
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ NN_ERR_PRINTF("Excedded max graph execution context per WASM instance");
+ return runtime_error;
+ }
+ *ctx = tfl_ctx->current_interpreters++;
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ return success;
+}
+
+static error
+is_valid_graph(TFLiteContext *tfl_ctx, graph g)
+{
+ if (g >= MAX_GRAPHS_PER_INST) {
+ NN_ERR_PRINTF("Invalid graph: %d >= %d.", g, MAX_GRAPHS_PER_INST);
+ return runtime_error;
+ }
+ if (tfl_ctx->models[g].model_pointer == NULL) {
+ NN_ERR_PRINTF("Context (model) non-initialized.");
+ return runtime_error;
+ }
+ if (tfl_ctx->models[g].model == NULL) {
+ NN_ERR_PRINTF("Context (tflite model) non-initialized.");
+ return runtime_error;
+ }
+ return success;
+}
+
+static error
+is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
+ graph_execution_context ctx)
+{
+ if (ctx >= MAX_GRAPH_EXEC_CONTEXTS_PER_INST) {
+ NN_ERR_PRINTF("Invalid graph execution context: %d >= %d", ctx,
+ MAX_GRAPH_EXEC_CONTEXTS_PER_INST);
+ return runtime_error;
+ }
+ if (tfl_ctx->interpreters[ctx].interpreter == NULL) {
+ NN_ERR_PRINTF("Context (interpreter) non-initialized.");
+ return runtime_error;
+ }
+ return success;
+}
+
+/* WASI-NN (tensorflow) implementation */
+
+error
+tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
+ graph_encoding encoding, execution_target target, graph *g)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ if (builder->size != 1) {
+ NN_ERR_PRINTF("Unexpected builder format.");
+ return invalid_argument;
+ }
+
+ if (encoding != tensorflowlite) {
+ NN_ERR_PRINTF("Encoding is not tensorflowlite.");
+ return invalid_argument;
+ }
+
+ if (target != cpu && target != gpu) {
+ NN_ERR_PRINTF("Only CPU and GPU target is supported.");
+ return invalid_argument;
+ }
+
+ error res;
+ if (success != (res = initialize_g(tfl_ctx, g)))
+ return res;
+
+ uint32_t size = builder->buf[0].size;
+
+ // Save model
+ tfl_ctx->models[*g].model_pointer = (char *)wasm_runtime_malloc(size);
+ if (tfl_ctx->models[*g].model_pointer == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for model.");
+ return missing_memory;
+ }
+
+ bh_memcpy_s(tfl_ctx->models[*g].model_pointer, size, builder->buf[0].buf,
+ size);
+
+ // Save model flatbuffer
+ tfl_ctx->models[*g].model =
+ std::move(tflite::FlatBufferModel::BuildFromBuffer(
+ tfl_ctx->models[*g].model_pointer, size, NULL));
+
+ if (tfl_ctx->models[*g].model == NULL) {
+ NN_ERR_PRINTF("Loading model error.");
+ wasm_runtime_free(tfl_ctx->models[*g].model_pointer);
+ tfl_ctx->models[*g].model_pointer = NULL;
+ return missing_memory;
+ }
+
+ // Save target
+ tfl_ctx->models[*g].target = target;
+ return success;
+}
+
+error
+tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
+ graph_execution_context *ctx)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph(tfl_ctx, g)))
+ return res;
+
+ if (success != (res = initialize_graph_ctx(tfl_ctx, g, ctx)))
+ return res;
+
+ // Build the interpreter with the InterpreterBuilder.
+ tflite::ops::builtin::BuiltinOpResolver resolver;
+ tflite::InterpreterBuilder tflite_builder(*tfl_ctx->models[g].model,
+ resolver);
+ tflite_builder(&tfl_ctx->interpreters[*ctx].interpreter);
+ if (tfl_ctx->interpreters[*ctx].interpreter == NULL) {
+ NN_ERR_PRINTF("Error when generating the interpreter.");
+ return missing_memory;
+ }
+
+ bool use_default = false;
+ switch (tfl_ctx->models[g].target) {
+ case gpu:
+ {
+#if defined(WASI_NN_ENABLE_GPU)
+ NN_WARN_PRINTF("GPU enabled.");
+ // https://www.tensorflow.org/lite/performance/gpu
+ TfLiteGpuDelegateOptionsV2 options =
+ TfLiteGpuDelegateOptionsV2Default();
+ options.inference_preference =
+ TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;
+ options.inference_priority1 =
+ TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY;
+ tfl_ctx->delegate = TfLiteGpuDelegateV2Create(&options);
+ if (tfl_ctx->delegate == NULL) {
+ NN_ERR_PRINTF("Error when generating GPU delegate.");
+ use_default = true;
+ return missing_memory;
+ }
+ if (tfl_ctx->interpreters[*ctx]
+ .interpreter->ModifyGraphWithDelegate(tfl_ctx->delegate)
+ != kTfLiteOk) {
+ NN_ERR_PRINTF("Error when enabling GPU delegate.");
+ use_default = true;
+ }
+#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
+ NN_WARN_PRINTF("external delegation enabled.");
+ TfLiteExternalDelegateOptions options =
+ TfLiteExternalDelegateOptionsDefault(WASI_NN_EXT_DELEGATE_PATH);
+ tfl_ctx->delegate = TfLiteExternalDelegateCreate(&options);
+ if (tfl_ctx->delegate == NULL) {
+ NN_ERR_PRINTF("Error when generating External delegate.");
+ use_default = true;
+ return missing_memory;
+ }
+ if (tfl_ctx->interpreters[*ctx]
+ .interpreter->ModifyGraphWithDelegate(tfl_ctx->delegate)
+ != kTfLiteOk) {
+ NN_ERR_PRINTF("Error when enabling External delegate.");
+ use_default = true;
+ }
+#else
+ NN_WARN_PRINTF("GPU not enabled.");
+ use_default = true;
+#endif
+ break;
+ }
+ default:
+ use_default = true;
+ }
+ if (use_default)
+ NN_WARN_PRINTF("Default encoding is CPU.");
+
+ tfl_ctx->interpreters[*ctx].interpreter->AllocateTensors();
+ return success;
+}
+
+error
+tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor *input_tensor)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
+ return res;
+
+ uint32_t num_tensors =
+ tfl_ctx->interpreters[ctx].interpreter->inputs().size();
+ NN_DBG_PRINTF("Number of tensors (%d)", num_tensors);
+ if (index + 1 > num_tensors) {
+ return runtime_error;
+ }
+
+ auto tensor = tfl_ctx->interpreters[ctx].interpreter->input_tensor(index);
+ if (tensor == NULL) {
+ NN_ERR_PRINTF("Missing memory");
+ return missing_memory;
+ }
+
+ uint32_t model_tensor_size = 1;
+ for (int i = 0; i < tensor->dims->size; ++i)
+ model_tensor_size *= (uint32_t)tensor->dims->data[i];
+
+ uint32_t input_tensor_size = 1;
+ for (uint32_t i = 0; i < input_tensor->dimensions->size; i++)
+ input_tensor_size *= (uint32_t)input_tensor->dimensions->buf[i];
+
+ if (model_tensor_size != input_tensor_size) {
+ NN_ERR_PRINTF("Input tensor shape from the model is different than the "
+ "one provided");
+ return invalid_argument;
+ }
+
+ auto *input =
+ tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor<float>(
+ index);
+ if (input == NULL)
+ return missing_memory;
+
+ bh_memcpy_s(input, model_tensor_size * sizeof(float), input_tensor->data,
+ model_tensor_size * sizeof(float));
+ return success;
+}
+
+error
+tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
+ return res;
+
+ tfl_ctx->interpreters[ctx].interpreter->Invoke();
+ return success;
+}
+
+error
+tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor_data output_tensor,
+ uint32_t *output_tensor_size)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
+ return res;
+
+ uint32_t num_output_tensors =
+ tfl_ctx->interpreters[ctx].interpreter->outputs().size();
+ NN_DBG_PRINTF("Number of tensors (%d)", num_output_tensors);
+
+ if (index + 1 > num_output_tensors) {
+ return runtime_error;
+ }
+
+ auto tensor = tfl_ctx->interpreters[ctx].interpreter->output_tensor(index);
+ if (tensor == NULL) {
+ NN_ERR_PRINTF("Missing memory");
+ return missing_memory;
+ }
+
+ uint32_t model_tensor_size = 1;
+ for (int i = 0; i < (int)tensor->dims->size; ++i)
+ model_tensor_size *= (uint32_t)tensor->dims->data[i];
+
+ if (*output_tensor_size < model_tensor_size) {
+ NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
+ return missing_memory;
+ }
+
+ float *tensor_f =
+ tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor<float>(
+ index);
+ for (uint32_t i = 0; i < model_tensor_size; ++i)
+ NN_DBG_PRINTF("output: %f", tensor_f[i]);
+
+ *output_tensor_size = model_tensor_size;
+ bh_memcpy_s(output_tensor, model_tensor_size * sizeof(float), tensor_f,
+ model_tensor_size * sizeof(float));
+ return success;
+}
+
+void
+tensorflowlite_initialize(void **tflite_ctx)
+{
+ TFLiteContext *tfl_ctx = new TFLiteContext();
+ if (tfl_ctx == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for tensorflowlite.");
+ return;
+ }
+
+ NN_DBG_PRINTF("Initializing models.");
+ tfl_ctx->current_models = 0;
+ for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) {
+ tfl_ctx->models[i].model_pointer = NULL;
+ }
+ NN_DBG_PRINTF("Initializing interpreters.");
+ tfl_ctx->current_interpreters = 0;
+
+ if (os_mutex_init(&tfl_ctx->g_lock) != 0) {
+ NN_ERR_PRINTF("Error while initializing the lock");
+ }
+
+ tfl_ctx->delegate = NULL;
+
+ *tflite_ctx = (void *)tfl_ctx;
+}
+
+void
+tensorflowlite_destroy(void *tflite_ctx)
+{
+ /*
+ TensorFlow Lite memory is internally managed by tensorflow
+
+ Related issues:
+ * https://github.com/tensorflow/tensorflow/issues/15880
+ */
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ if (tfl_ctx->delegate != NULL) {
+#if defined(WASI_NN_ENABLE_GPU)
+ TfLiteGpuDelegateV2Delete(tfl_ctx->delegate);
+#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
+ TfLiteExternalDelegateDelete(tfl_ctx->delegate);
+#endif
+ }
+
+ NN_DBG_PRINTF("Freeing memory.");
+ for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) {
+ tfl_ctx->models[i].model.reset();
+ if (tfl_ctx->models[i].model_pointer)
+ wasm_runtime_free(tfl_ctx->models[i].model_pointer);
+ tfl_ctx->models[i].model_pointer = NULL;
+ }
+ for (int i = 0; i < MAX_GRAPH_EXEC_CONTEXTS_PER_INST; ++i) {
+ tfl_ctx->interpreters[i].interpreter.reset();
+ }
+ os_mutex_destroy(&tfl_ctx->g_lock);
+ delete tfl_ctx;
+ NN_DBG_PRINTF("Memory free'd.");
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
new file mode 100644
index 000000000..9605420dd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_TENSORFLOWLITE_HPP
+#define WASI_NN_TENSORFLOWLITE_HPP
+
+#include "wasi_nn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+error
+tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
+ graph_encoding encoding, execution_target target, graph *g);
+
+error
+tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
+ graph_execution_context *ctx);
+
+error
+tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor *input_tensor);
+
+error
+tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx);
+
+error
+tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor_data output_tensor,
+ uint32_t *output_tensor_size);
+
+void
+tensorflowlite_initialize(void **tflite_ctx);
+
+void
+tensorflowlite_destroy(void *tflite_ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt
new file mode 100644
index 000000000..33fad71eb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt
@@ -0,0 +1,173 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.9)
+
+project (iwasm)
+
+set (CMAKE_VERBOSE_MAKEFILE OFF)
+# Reset default linker flags
+set (CMAKE_C_STANDARD 99)
+set (CMAKE_CXX_STANDARD 14)
+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+if (NOT DEFINED WAMR_BUILD_PLATFORM)
+ set (WAMR_BUILD_PLATFORM "linux")
+endif ()
+
+# Set WAMR_BUILD_TARGET, currently values supported:
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
+# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
+if (NOT DEFINED WAMR_BUILD_TARGET)
+ if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
+ set (WAMR_BUILD_TARGET "AARCH64")
+ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
+ set (WAMR_BUILD_TARGET "RISCV64")
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ # Build as X86_64 by default in 64-bit platform
+ set (WAMR_BUILD_TARGET "X86_64")
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
+ # Build as X86_32 by default in 32-bit platform
+ set (WAMR_BUILD_TARGET "X86_32")
+ else ()
+ message(SEND_ERROR "Unsupported build target platform!")
+ 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_FAST_JIT)
+ # Disable Fast JIT by default
+ set (WAMR_BUILD_FAST_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 ()
+
+if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
+ # Enable fast interpreter
+ set (WAMR_BUILD_FAST_INTERP 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_MULTI_MODULE)
+ # Disable multiple modules by default
+ set (WAMR_BUILD_MULTI_MODULE 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
+ # Disable pthread library by default
+ set (WAMR_BUILD_LIB_PTHREAD 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
+ # Disable wasm mini loader by default
+ set (WAMR_BUILD_MINI_LOADER 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_SIMD)
+ # Enable SIMD by default
+ set (WAMR_BUILD_SIMD 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_REF_TYPES)
+ # Disable reference types by default
+ set (WAMR_BUILD_REF_TYPES 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP)
+ # Disable Debug feature by default
+ set (WAMR_BUILD_DEBUG_INTERP 0)
+endif ()
+
+if (WAMR_BUILD_DEBUG_INTERP EQUAL 1)
+ set (WAMR_BUILD_FAST_INTERP 0)
+ set (WAMR_BUILD_MINI_LOADER 0)
+ set (WAMR_BUILD_SIMD 0)
+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 -pie -fPIE")
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow")
+# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion")
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wno-unused")
+
+if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+ if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register")
+ # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,bounds-strict,alignment \
+ -fno-sanitize-recover")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,bounds-strict,alignment \
+ -fno-sanitize-recover")
+ endif()
+ else ()
+ # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,alignment \
+ -fno-sanitize-recover")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,alignment \
+ -fno-sanitize-recover")
+ endif()
+ endif ()
+endif ()
+
+# The following flags are to enhance security, but it may impact performance,
+# we disable them by default.
+#if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftrapv -D_FORTIFY_SOURCE=2")
+#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")
+
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+
+add_executable (iwasm ${WAMR_ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM}/main.c ${UNCOMMON_SHARED_SOURCE})
+
+install (TARGETS iwasm DESTINATION bin)
+
+target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} ${TENSORFLOW_LIB} -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} ${UV_A_LIBS} -lm -ldl -lpthread)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh
new file mode 100755
index 000000000..33879eaf7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh
@@ -0,0 +1,21 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+# WASM application that uses WASI-NN
+
+/opt/wasi-sdk/bin/clang \
+ -Wl,--allow-undefined \
+ -Wl,--strip-all,--no-entry \
+ --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
+ -I.. -I../src/utils \
+ -o test_tensorflow.wasm \
+ test_tensorflow.c utils.c
+
+# TFLite models to use in the tests
+
+cd models
+python3 average.py
+python3 max.py
+python3 mult_dimension.py
+python3 mult_outputs.py
+python3 sum.py
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py
new file mode 100755
index 000000000..a21fe7520
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[5, 5, 1]),
+ tf.keras.layers.AveragePooling2D(
+ pool_size=(5, 5), strides=None, padding="valid", data_format=None)
+
+])
+
+# Export model to tflite
+
+save_model(model, "average.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py
new file mode 100755
index 000000000..a3ec45677
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[5, 5, 1]),
+ tf.keras.layers.MaxPooling2D(
+ pool_size=(5, 5), strides=None, padding="valid", data_format=None)
+
+])
+
+# Export model to tflite
+
+save_model(model, "max.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py
new file mode 100644
index 000000000..f521a93af
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[3, 3, 1]),
+ tf.keras.layers.Conv2D(1, (1, 1), kernel_initializer=tf.keras.initializers.Constant(
+ value=1), bias_initializer='zeros'
+ )
+])
+# Export model to tflite
+
+save_model(model, "mult_dim.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py
new file mode 100755
index 000000000..98a50129c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+import numpy as np
+from keras.layers import AveragePooling2D, Conv2D
+
+from tensorflow.keras import Input, Model
+
+from utils import save_model
+
+
+inputs = Input(shape=(4, 4, 1))
+
+output1 = Conv2D(1, (4, 1), kernel_initializer=tf.keras.initializers.Constant(
+ value=1), bias_initializer='zeros'
+)(inputs)
+output2 = AveragePooling2D(pool_size=(
+ 4, 1), strides=None, padding="valid", data_format=None)(inputs)
+
+model = Model(inputs=inputs, outputs=[output1, output2])
+
+inp = np.arange(16).reshape((1, 4, 4, 1))
+
+print(inp)
+
+res = model.predict(inp)
+
+print(res)
+print(res[0].shape)
+print(res[1].shape)
+
+save_model(model, "mult_out.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py
new file mode 100755
index 000000000..503125b34
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[5, 5, 1]),
+ tf.keras.layers.Conv2D(1, (5, 5), kernel_initializer=tf.keras.initializers.Constant(
+ value=1), bias_initializer='zeros'
+ )
+])
+
+# Export model to tflite
+
+save_model(model, "sum.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py
new file mode 100644
index 000000000..8335f05da
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+import pathlib
+
+
+def save_model(model, filename):
+ converter = tf.lite.TFLiteConverter.from_keras_model(model)
+ tflite_model = converter.convert()
+ tflite_models_dir = pathlib.Path("./")
+ tflite_model_file = tflite_models_dir/filename
+ tflite_model_file.write_bytes(tflite_model)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt
new file mode 100644
index 000000000..4cf2910db
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt
@@ -0,0 +1 @@
+tensorflow==2.11.1 \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
new file mode 100644
index 000000000..2fa516538
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+#include "utils.h"
+#include "logger.h"
+
+void
+test_sum(execution_target target)
+{
+ int dims[] = { 1, 5, 5, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output = run_inference(target, input.input_tensor, input.dim,
+ &output_size, "/assets/models/sum.tflite", 1);
+
+ assert(output_size == 1);
+ assert(fabs(output[0] - 300.0) < EPSILON);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_max(execution_target target)
+{
+ int dims[] = { 1, 5, 5, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output = run_inference(target, input.input_tensor, input.dim,
+ &output_size, "/assets/models/max.tflite", 1);
+
+ assert(output_size == 1);
+ assert(fabs(output[0] - 24.0) < EPSILON);
+ NN_INFO_PRINTF("Result: max is %f", output[0]);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_average(execution_target target)
+{
+ int dims[] = { 1, 5, 5, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output =
+ run_inference(target, input.input_tensor, input.dim, &output_size,
+ "/assets/models/average.tflite", 1);
+
+ assert(output_size == 1);
+ assert(fabs(output[0] - 12.0) < EPSILON);
+ NN_INFO_PRINTF("Result: average is %f", output[0]);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_mult_dimensions(execution_target target)
+{
+ int dims[] = { 1, 3, 3, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output =
+ run_inference(target, input.input_tensor, input.dim, &output_size,
+ "/assets/models/mult_dim.tflite", 1);
+
+ assert(output_size == 9);
+ for (int i = 0; i < 9; i++)
+ assert(fabs(output[i] - i) < EPSILON);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_mult_outputs(execution_target target)
+{
+ int dims[] = { 1, 4, 4, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output =
+ run_inference(target, input.input_tensor, input.dim, &output_size,
+ "/assets/models/mult_out.tflite", 2);
+
+ assert(output_size == 8);
+ // first tensor check
+ for (int i = 0; i < 4; i++)
+ assert(fabs(output[i] - (i * 4 + 24)) < EPSILON);
+ // second tensor check
+ for (int i = 0; i < 4; i++)
+ assert(fabs(output[i + 4] - (i + 6)) < EPSILON);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+int
+main()
+{
+ char *env = getenv("TARGET");
+ if (env == NULL) {
+ NN_INFO_PRINTF("Usage:\n--env=\"TARGET=[cpu|gpu]\"");
+ return 1;
+ }
+ execution_target target;
+ if (strcmp(env, "cpu") == 0)
+ target = cpu;
+ else if (strcmp(env, "gpu") == 0)
+ target = gpu;
+ else {
+ NN_ERR_PRINTF("Wrong target!");
+ return 1;
+ }
+ NN_INFO_PRINTF("################### Testing sum...");
+ test_sum(target);
+ NN_INFO_PRINTF("################### Testing max...");
+ test_max(target);
+ NN_INFO_PRINTF("################### Testing average...");
+ test_average(target);
+ NN_INFO_PRINTF("################### Testing multiple dimensions...");
+ test_mult_dimensions(target);
+ NN_INFO_PRINTF("################### Testing multiple outputs...");
+ test_mult_outputs(target);
+
+ NN_INFO_PRINTF("Tests: passed!");
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c
new file mode 100644
index 000000000..e0704cab4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "utils.h"
+#include "logger.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+error
+wasm_load(char *model_name, graph *g, execution_target target)
+{
+ FILE *pFile = fopen(model_name, "r");
+ if (pFile == NULL)
+ return invalid_argument;
+
+ uint8_t *buffer;
+ size_t result;
+
+ // allocate memory to contain the whole file:
+ buffer = (uint8_t *)malloc(sizeof(uint8_t) * MAX_MODEL_SIZE);
+ if (buffer == NULL) {
+ fclose(pFile);
+ return missing_memory;
+ }
+
+ result = fread(buffer, 1, MAX_MODEL_SIZE, pFile);
+ if (result <= 0) {
+ fclose(pFile);
+ free(buffer);
+ return missing_memory;
+ }
+
+ graph_builder_array arr;
+
+ arr.size = 1;
+ arr.buf = (graph_builder *)malloc(sizeof(graph_builder));
+ if (arr.buf == NULL) {
+ fclose(pFile);
+ free(buffer);
+ return missing_memory;
+ }
+
+ arr.buf[0].size = result;
+ arr.buf[0].buf = buffer;
+
+ error res = load(&arr, tensorflowlite, target, g);
+
+ fclose(pFile);
+ free(buffer);
+ free(arr.buf);
+ return res;
+}
+
+error
+wasm_init_execution_context(graph g, graph_execution_context *ctx)
+{
+ return init_execution_context(g, ctx);
+}
+
+error
+wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
+{
+ tensor_dimensions dims;
+ dims.size = INPUT_TENSOR_DIMS;
+ dims.buf = (uint32_t *)malloc(dims.size * sizeof(uint32_t));
+ if (dims.buf == NULL)
+ return missing_memory;
+
+ tensor tensor;
+ tensor.dimensions = &dims;
+ for (int i = 0; i < tensor.dimensions->size; ++i)
+ tensor.dimensions->buf[i] = dim[i];
+ tensor.type = fp32;
+ tensor.data = (uint8_t *)input_tensor;
+ error err = set_input(ctx, 0, &tensor);
+
+ free(dims.buf);
+ return err;
+}
+
+error
+wasm_compute(graph_execution_context ctx)
+{
+ return compute(ctx);
+}
+
+error
+wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
+ uint32_t *out_size)
+{
+ return get_output(ctx, index, (uint8_t *)out_tensor, out_size);
+}
+
+float *
+run_inference(execution_target target, float *input, uint32_t *input_size,
+ uint32_t *output_size, char *model_name,
+ uint32_t num_output_tensors)
+{
+ graph graph;
+ if (wasm_load(model_name, &graph, target) != success) {
+ NN_ERR_PRINTF("Error when loading model.");
+ exit(1);
+ }
+
+ graph_execution_context ctx;
+ if (wasm_init_execution_context(graph, &ctx) != success) {
+ NN_ERR_PRINTF("Error when initialixing execution context.");
+ exit(1);
+ }
+
+ if (wasm_set_input(ctx, input, input_size) != success) {
+ NN_ERR_PRINTF("Error when setting input tensor.");
+ exit(1);
+ }
+
+ if (wasm_compute(ctx) != success) {
+ NN_ERR_PRINTF("Error when running inference.");
+ exit(1);
+ }
+
+ float *out_tensor = (float *)malloc(sizeof(float) * MAX_OUTPUT_TENSOR_SIZE);
+ if (out_tensor == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for output tensor.");
+ exit(1);
+ }
+
+ uint32_t offset = 0;
+ for (int i = 0; i < num_output_tensors; ++i) {
+ *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size;
+ if (wasm_get_output(ctx, i, &out_tensor[offset], output_size)
+ != success) {
+ NN_ERR_PRINTF("Error when getting output.");
+ exit(1);
+ }
+
+ offset += *output_size;
+ }
+ *output_size = offset;
+ return out_tensor;
+}
+
+input_info
+create_input(int *dims)
+{
+ input_info input = { .dim = NULL, .input_tensor = NULL, .elements = 1 };
+
+ input.dim = malloc(INPUT_TENSOR_DIMS * sizeof(uint32_t));
+ if (input.dim)
+ for (int i = 0; i < INPUT_TENSOR_DIMS; ++i) {
+ input.dim[i] = dims[i];
+ input.elements *= dims[i];
+ }
+
+ input.input_tensor = malloc(input.elements * sizeof(float));
+ for (int i = 0; i < input.elements; ++i)
+ input.input_tensor[i] = i;
+
+ return input;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h
new file mode 100644
index 000000000..6373be542
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_UTILS
+#define WASI_NN_UTILS
+
+#include <stdint.h>
+
+#include "wasi_nn.h"
+
+#define MAX_MODEL_SIZE 85000000
+#define MAX_OUTPUT_TENSOR_SIZE 200
+#define INPUT_TENSOR_DIMS 4
+#define EPSILON 1e-8
+
+typedef struct {
+ float *input_tensor;
+ uint32_t *dim;
+ uint32_t elements;
+} input_info;
+
+/* wasi-nn wrappers */
+
+error
+wasm_load(char *model_name, graph *g, execution_target target);
+
+error
+wasm_init_execution_context(graph g, graph_execution_context *ctx);
+
+error
+wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim);
+
+error
+wasm_compute(graph_execution_context ctx);
+
+error
+wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
+ uint32_t *out_size);
+
+/* Utils */
+
+float *
+run_inference(execution_target target, float *input, uint32_t *input_size,
+ uint32_t *output_size, char *model_name,
+ uint32_t num_output_tensors);
+
+input_info
+create_input(int *dims);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake
new file mode 100644
index 000000000..019782c2e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake
@@ -0,0 +1,22 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
+
+# Find tensorflow-lite
+find_package(tensorflow_lite REQUIRED)
+
+set (WASI_NN_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories (${WASI_NN_DIR})
+include_directories (${WASI_NN_DIR}/src)
+include_directories (${WASI_NN_DIR}/src/utils)
+
+set (
+ LIBC_WASI_NN_SOURCE
+ ${WASI_NN_DIR}/src/wasi_nn.c
+ ${WASI_NN_DIR}/src/wasi_nn_tensorflowlite.cpp
+ ${WASI_NN_DIR}/src/utils/wasi_nn_app_native.c
+)
+
+set (TENSORFLOW_LIB tensorflow-lite)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h
new file mode 100644
index 000000000..2bf0a192c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/**
+ * Following definition from:
+ * [Oct 25th, 2022]
+ * https://github.com/WebAssembly/wasi-nn/blob/0f77c48ec195748990ff67928a4b3eef5f16c2de/wasi-nn.wit.md
+ */
+
+#ifndef WASI_NN_H
+#define WASI_NN_H
+
+#include <stdint.h>
+#include "wasi_nn_types.h"
+
+/**
+ * @brief Load an opaque sequence of bytes to use for inference.
+ *
+ * @param builder Model builder.
+ * @param encoding Model encoding.
+ * @param target Execution target.
+ * @param g Graph.
+ * @return error Execution status.
+ */
+error
+load(graph_builder_array *builder, graph_encoding encoding,
+ execution_target target, graph *g)
+ __attribute__((import_module("wasi_nn")));
+
+/**
+ * INFERENCE
+ *
+ */
+
+// Bind a `graph` to the input and output tensors for an inference.
+typedef uint32_t graph_execution_context;
+
+/**
+ * @brief Create an execution instance of a loaded graph.
+ *
+ * @param g Graph.
+ * @param ctx Execution context.
+ * @return error Execution status.
+ */
+error
+init_execution_context(graph g, graph_execution_context *ctx)
+ __attribute__((import_module("wasi_nn")));
+
+/**
+ * @brief Define the inputs to use for inference.
+ *
+ * @param ctx Execution context.
+ * @param index Input tensor index.
+ * @param tensor Input tensor.
+ * @return error Execution status.
+ */
+error
+set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
+ __attribute__((import_module("wasi_nn")));
+
+/**
+ * @brief Compute the inference on the given inputs.
+ *
+ * @param ctx Execution context.
+ * @return error Execution status.
+ */
+error
+compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
+
+/**
+ * @brief Extract the outputs after inference.
+ *
+ * @param ctx Execution context.
+ * @param index Output tensor index.
+ * @param output_tensor Buffer where output tensor with index `index` is
+ * copied.
+ * @param output_tensor_size Pointer to `output_tensor` maximum size.
+ * After the function call it is updated with the
+ * copied number of bytes.
+ * @return error Execution status.
+ */
+error
+get_output(graph_execution_context ctx, uint32_t index,
+ tensor_data output_tensor, uint32_t *output_tensor_size)
+ __attribute__((import_module("wasi_nn")));
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h
new file mode 100644
index 000000000..a2cebe49e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_TYPES_H
+#define WASI_NN_TYPES_H
+
+/**
+ * ERRORS
+ *
+ */
+
+// Error codes returned by functions in this API.
+typedef enum {
+ // No error occurred.
+ success = 0,
+ // Caller module passed an invalid argument.
+ invalid_argument,
+ // Invalid encoding.
+ invalid_encoding,
+ // Caller module is missing a memory export.
+ missing_memory,
+ // Device or resource busy.
+ busy,
+ // Runtime Error.
+ runtime_error,
+} error;
+
+/**
+ * TENSOR
+ *
+ */
+
+// The dimensions of a tensor.
+//
+// The array length matches the tensor rank and each element in the array
+// describes the size of each dimension.
+typedef struct {
+ uint32_t *buf;
+ uint32_t size;
+} tensor_dimensions;
+
+// The type of the elements in a tensor.
+typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
+
+// The tensor data.
+//
+// Initially conceived as a sparse representation, each empty cell would be
+// filled with zeros and the array length must match the product of all of the
+// dimensions and the number of bytes in the type (e.g., a 2x2 tensor with
+// 4-byte f32 elements would have a data array of length 16). Naturally, this
+// representation requires some knowledge of how to lay out data in
+// memory--e.g., using row-major ordering--and could perhaps be improved.
+typedef uint8_t *tensor_data;
+
+// A tensor.
+typedef struct {
+ // Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To
+ // represent a tensor containing a single value, use `[1]` for the tensor
+ // dimensions.
+ tensor_dimensions *dimensions;
+ // Describe the type of element in the tensor (e.g., f32).
+ tensor_type type;
+ // Contains the tensor data.
+ tensor_data data;
+} tensor;
+
+/**
+ * GRAPH
+ *
+ */
+
+// The graph initialization data.
+//
+// This consists of an array of buffers because implementing backends may encode
+// their graph IR in parts (e.g., OpenVINO stores its IR and weights
+// separately).
+typedef struct {
+ uint8_t *buf;
+ uint32_t size;
+} graph_builder;
+
+typedef struct {
+ graph_builder *buf;
+ uint32_t size;
+} graph_builder_array;
+
+// An execution graph for performing inference (i.e., a model).
+typedef uint32_t graph;
+
+// Describes the encoding of the graph. This allows the API to be implemented by
+// various backends that encode (i.e., serialize) their graph IR with different
+// formats.
+typedef enum {
+ openvino = 0,
+ onnx,
+ tensorflow,
+ pytorch,
+ tensorflowlite
+} graph_encoding;
+
+// Define where the graph should be executed.
+typedef enum execution_target { cpu = 0, gpu, tpu } execution_target;
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/LICENSE.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/LICENSE.md
new file mode 100644
index 000000000..f4b1a054c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/LICENSE.md
@@ -0,0 +1,30 @@
+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:
+
+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 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.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/coap-constants.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/coap-constants.h
new file mode 100644
index 000000000..1de2ed9d8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/er-coap/coap-constants.h
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file
+ * Collection of constants specified in the CoAP standard.
+ * \author
+ * Matthias Kovatsch <kovatsch@inf.ethz.ch>
+ */
+
+/**
+ * \addtogroup coap
+ * @{
+ */
+
+#ifndef COAP_CONSTANTS_H_
+#define COAP_CONSTANTS_H_
+
+/* clang-format off */
+#define COAP_DEFAULT_PORT 5683
+#define COAP_DEFAULT_SECURE_PORT 5684
+
+#define COAP_DEFAULT_MAX_AGE 60
+#define COAP_RESPONSE_TIMEOUT 3
+#define COAP_RESPONSE_RANDOM_FACTOR 1.5
+#define COAP_MAX_RETRANSMIT 4
+
+#define COAP_HEADER_LEN 4 /* | version:0x03 type:0x0C tkl:0xF0 | code | mid:0x00FF | mid:0xFF00 | */
+#define COAP_TOKEN_LEN 8 /* The maximum number of bytes for the Token */
+#define COAP_ETAG_LEN 8 /* The maximum number of bytes for the ETag */
+
+#define COAP_HEADER_VERSION_MASK 0xC0
+#define COAP_HEADER_VERSION_POSITION 6
+#define COAP_HEADER_TYPE_MASK 0x30
+#define COAP_HEADER_TYPE_POSITION 4
+#define COAP_HEADER_TOKEN_LEN_MASK 0x0F
+#define COAP_HEADER_TOKEN_LEN_POSITION 0
+
+#define COAP_HEADER_OPTION_DELTA_MASK 0xF0
+#define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F
+/* clang-format on */
+
+/* CoAP message types */
+typedef enum {
+ COAP_TYPE_CON, /* confirmables */
+ COAP_TYPE_NON, /* non-confirmables */
+ COAP_TYPE_ACK, /* acknowledgements */
+ COAP_TYPE_RST /* reset */
+} coap_message_type_t;
+
+/* clang-format off */
+/* CoAP request method codes */
+typedef enum {
+ COAP_GET = 1,
+ COAP_POST, COAP_PUT,
+ COAP_DELETE
+} coap_method_t;
+/* clang-format on */
+
+/* CoAP response codes */
+typedef enum {
+ COAP_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;
+
+/* CoAP header option numbers */
+typedef enum {
+ COAP_OPTION_IF_MATCH = 1, /* 0-8 B */
+ COAP_OPTION_URI_HOST = 3, /* 1-255 B */
+ COAP_OPTION_ETAG = 4, /* 1-8 B */
+ COAP_OPTION_IF_NONE_MATCH = 5, /* 0 B */
+ COAP_OPTION_OBSERVE = 6, /* 0-3 B */
+ COAP_OPTION_URI_PORT = 7, /* 0-2 B */
+ COAP_OPTION_LOCATION_PATH = 8, /* 0-255 B */
+ COAP_OPTION_URI_PATH = 11, /* 0-255 B */
+ COAP_OPTION_CONTENT_FORMAT = 12, /* 0-2 B */
+ COAP_OPTION_MAX_AGE = 14, /* 0-4 B */
+ COAP_OPTION_URI_QUERY = 15, /* 0-255 B */
+ COAP_OPTION_ACCEPT = 17, /* 0-2 B */
+ COAP_OPTION_LOCATION_QUERY = 20, /* 0-255 B */
+ COAP_OPTION_BLOCK2 = 23, /* 1-3 B */
+ COAP_OPTION_BLOCK1 = 27, /* 1-3 B */
+ COAP_OPTION_SIZE2 = 28, /* 0-4 B */
+ COAP_OPTION_PROXY_URI = 35, /* 1-1034 B */
+ COAP_OPTION_PROXY_SCHEME = 39, /* 1-255 B */
+ COAP_OPTION_SIZE1 = 60, /* 0-4 B */
+} coap_option_t;
+
+/* CoAP Content-Formats */
+typedef enum {
+ TEXT_PLAIN = 0,
+ TEXT_XML = 1,
+ TEXT_CSV = 2,
+ TEXT_HTML = 3,
+ IMAGE_GIF = 21,
+ IMAGE_JPEG = 22,
+ IMAGE_PNG = 23,
+ IMAGE_TIFF = 24,
+ AUDIO_RAW = 25,
+ VIDEO_RAW = 26,
+ APPLICATION_LINK_FORMAT = 40,
+ APPLICATION_XML = 41,
+ APPLICATION_OCTET_STREAM = 42,
+ APPLICATION_RDF_XML = 43,
+ APPLICATION_SOAP_XML = 44,
+ APPLICATION_ATOM_XML = 45,
+ APPLICATION_XMPP_XML = 46,
+ APPLICATION_EXI = 47,
+ APPLICATION_FASTINFOSET = 48,
+ APPLICATION_SOAP_FASTINFOSET = 49,
+ APPLICATION_JSON = 50,
+ APPLICATION_X_OBIX_BINARY = 51
+} coap_content_format_t;
+
+/**
+ * Resource flags for allowed methods and special functionalities.
+ */
+typedef enum {
+ NO_FLAGS = 0,
+
+ /* methods to handle */
+ METHOD_GET = (1 << 0),
+ METHOD_POST = (1 << 1),
+ METHOD_PUT = (1 << 2),
+ METHOD_DELETE = (1 << 3),
+
+ /* special flags */
+ HAS_SUB_RESOURCES = (1 << 4),
+ IS_SEPARATE = (1 << 5),
+ IS_OBSERVABLE = (1 << 6),
+ IS_PERIODIC = (1 << 7)
+} coap_resource_flags_t;
+
+#endif /* COAP_CONSTANTS_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/extension/coap_ext.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/extension/coap_ext.h
new file mode 100644
index 000000000..f61deac27
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/extension/coap_ext.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef COAP_EXTENSION_COAP_EXT_H_
+#define COAP_EXTENSION_COAP_EXT_H_
+
+#include "coap-constants.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COAP_EVENT (COAP_DELETE + 2)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* COAP_EXTENSION_COAP_EXT_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/lib_coap.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/lib_coap.cmake
new file mode 100644
index 000000000..8970e5d6c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/coap/lib_coap.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_COAP_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${LIB_COAP_DIR}/er-coap)
+include_directories(${LIB_COAP_DIR}/extension)
+
+file (GLOB_RECURSE source_all ${LIB_COAP_DIR}/*.c)
+
+set (LIB_COAP_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/SConscript
new file mode 100644
index 000000000..602d87158
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/SConscript
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import os
+
+cwd = GetCurrentDir()
+
+src = Split('''
+''')
+
+
+def addSrcFiles(arr, path):
+ for f in os.listdir(path):
+ fpath = os.path.join(path, f);
+ if os.path.isfile(fpath):
+ ext = os.path.splitext(fpath)[-1]
+ if ext == '.c' or ext == '.cpp':
+ arr += [fpath]
+ elif os.path.isdir(fpath):
+ addSrcFiles(arr, fpath)
+
+
+
+addSrcFiles(src, cwd);
+CPPPATH = [cwd, cwd+'/../include']
+
+group = DefineGroup('iwasm_platform_core', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_alloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_alloc.c
new file mode 100644
index 000000000..5c2a628a2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_alloc.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "ems_gc_internal.h"
+
+static inline bool
+hmu_is_in_heap(void *hmu, gc_uint8 *heap_base_addr, gc_uint8 *heap_end_addr)
+{
+ gc_uint8 *addr = (gc_uint8 *)hmu;
+ return (addr >= heap_base_addr && addr < heap_end_addr) ? true : false;
+}
+
+/**
+ * Remove a node from the tree it belongs to
+ *
+ * @param p the node to remove, can not be NULL, can not be the ROOT node
+ * the node will be removed from the tree, and the left, right and
+ * parent pointers of the node @p will be set to be NULL. Other fields
+ * won't be touched. The tree will be re-organized so that the order
+ * conditions are still satisified.
+ */
+static bool
+remove_tree_node(gc_heap_t *heap, hmu_tree_node_t *p)
+{
+ hmu_tree_node_t *q = NULL, **slot = NULL, *parent;
+ hmu_tree_node_t *root = heap->kfc_tree_root;
+ gc_uint8 *base_addr = heap->base_addr;
+ gc_uint8 *end_addr = base_addr + heap->current_size;
+
+ bh_assert(p);
+
+ parent = p->parent;
+ if (!parent || p == root /* p can not be the ROOT node */
+ || !hmu_is_in_heap(p, base_addr, end_addr)
+ || (parent != root && !hmu_is_in_heap(parent, base_addr, end_addr))) {
+ goto fail;
+ }
+
+ /* get the slot which holds pointer to node p */
+ if (p == p->parent->right) {
+ /* Don't use `slot = &p->parent->right` to avoid compiler warning */
+ slot = (hmu_tree_node_t **)((uint8 *)p->parent
+ + offsetof(hmu_tree_node_t, right));
+ }
+ else if (p == p->parent->left) {
+ /* p should be a child of its parent */
+ /* Don't use `slot = &p->parent->left` to avoid compiler warning */
+ slot = (hmu_tree_node_t **)((uint8 *)p->parent
+ + offsetof(hmu_tree_node_t, left));
+ }
+ else {
+ goto fail;
+ }
+
+ /**
+ * algorithms used to remove node p
+ * case 1: if p has no left child, replace p with its right child
+ * case 2: if p has no right child, replace p with its left child
+ * case 3: otherwise, find p's predecessor, remove it from the tree
+ * and replace p with it.
+ * use predecessor can keep the left <= root < right condition.
+ */
+
+ if (!p->left) {
+ /* move right child up*/
+ *slot = p->right;
+ if (p->right) {
+ if (!hmu_is_in_heap(p->right, base_addr, end_addr)) {
+ goto fail;
+ }
+ p->right->parent = p->parent;
+ }
+
+ p->left = p->right = p->parent = NULL;
+ return true;
+ }
+
+ if (!p->right) {
+ /* move left child up*/
+ *slot = p->left;
+ if (!hmu_is_in_heap(p->left, base_addr, end_addr)) {
+ goto fail;
+ }
+ /* p->left can never be NULL unless it is corrupted. */
+ p->left->parent = p->parent;
+
+ p->left = p->right = p->parent = NULL;
+ return true;
+ }
+
+ /* both left & right exist, find p's predecessor at first*/
+ q = p->left;
+ if (!hmu_is_in_heap(q, base_addr, end_addr)) {
+ goto fail;
+ }
+ while (q->right) {
+ q = q->right;
+ if (!hmu_is_in_heap(q, base_addr, end_addr)) {
+ goto fail;
+ }
+ }
+
+ /* remove from the tree*/
+ if (!remove_tree_node(heap, q))
+ return false;
+
+ *slot = q;
+ q->parent = p->parent;
+ q->left = p->left;
+ q->right = p->right;
+ if (q->left) {
+ if (!hmu_is_in_heap(q->left, base_addr, end_addr)) {
+ goto fail;
+ }
+ q->left->parent = q;
+ }
+ if (q->right) {
+ if (!hmu_is_in_heap(q->right, base_addr, end_addr)) {
+ goto fail;
+ }
+ q->right->parent = q;
+ }
+
+ p->left = p->right = p->parent = NULL;
+
+ return true;
+fail:
+ heap->is_heap_corrupted = true;
+ return false;
+}
+
+static bool
+unlink_hmu(gc_heap_t *heap, hmu_t *hmu)
+{
+ gc_uint8 *base_addr, *end_addr;
+ gc_size_t size;
+
+ bh_assert(gci_is_heap_valid(heap));
+ bh_assert(hmu && (gc_uint8 *)hmu >= heap->base_addr
+ && (gc_uint8 *)hmu < heap->base_addr + heap->current_size);
+
+ if (hmu_get_ut(hmu) != HMU_FC) {
+ heap->is_heap_corrupted = true;
+ return false;
+ }
+
+ base_addr = heap->base_addr;
+ end_addr = base_addr + heap->current_size;
+ size = hmu_get_size(hmu);
+
+ if (HMU_IS_FC_NORMAL(size)) {
+ uint32 node_idx = size >> 3;
+ hmu_normal_node_t *node_prev = NULL, *node_next;
+ hmu_normal_node_t *node = heap->kfc_normal_list[node_idx].next;
+
+ while (node) {
+ if (!hmu_is_in_heap(node, base_addr, end_addr)) {
+ heap->is_heap_corrupted = true;
+ return false;
+ }
+ node_next = get_hmu_normal_node_next(node);
+ if ((hmu_t *)node == hmu) {
+ if (!node_prev) /* list head */
+ heap->kfc_normal_list[node_idx].next = node_next;
+ else
+ set_hmu_normal_node_next(node_prev, node_next);
+ break;
+ }
+ node_prev = node;
+ node = node_next;
+ }
+
+ if (!node) {
+ os_printf("[GC_ERROR]couldn't find the node in the normal list\n");
+ }
+ }
+ else {
+ if (!remove_tree_node(heap, (hmu_tree_node_t *)hmu))
+ return false;
+ }
+ return true;
+}
+
+static void
+hmu_set_free_size(hmu_t *hmu)
+{
+ gc_size_t size;
+ bh_assert(hmu && hmu_get_ut(hmu) == HMU_FC);
+
+ size = hmu_get_size(hmu);
+ *((uint32 *)((char *)hmu + size) - 1) = size;
+}
+
+/**
+ * Add free chunk back to KFC
+ *
+ * @param heap should not be NULL and it should be a valid heap
+ * @param hmu should not be NULL and it should be a HMU of length @size inside
+ * @heap hmu should be 8-bytes aligned
+ * @param size should be positive and multiple of 8
+ * hmu with size @size will be added into KFC as a new FC.
+ */
+bool
+gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
+{
+ gc_uint8 *base_addr, *end_addr;
+ hmu_normal_node_t *np = NULL;
+ hmu_tree_node_t *root = NULL, *tp = NULL, *node = NULL;
+ uint32 node_idx;
+
+ bh_assert(gci_is_heap_valid(heap));
+ bh_assert(hmu && (gc_uint8 *)hmu >= heap->base_addr
+ && (gc_uint8 *)hmu < heap->base_addr + heap->current_size);
+ bh_assert(((gc_uint32)(uintptr_t)hmu_to_obj(hmu) & 7) == 0);
+ bh_assert(size > 0
+ && ((gc_uint8 *)hmu) + size
+ <= heap->base_addr + heap->current_size);
+ bh_assert(!(size & 7));
+
+ base_addr = heap->base_addr;
+ end_addr = base_addr + heap->current_size;
+
+ hmu_set_ut(hmu, HMU_FC);
+ hmu_set_size(hmu, size);
+ hmu_set_free_size(hmu);
+
+ if (HMU_IS_FC_NORMAL(size)) {
+ np = (hmu_normal_node_t *)hmu;
+ if (!hmu_is_in_heap(np, base_addr, end_addr)) {
+ heap->is_heap_corrupted = true;
+ return false;
+ }
+
+ node_idx = size >> 3;
+ set_hmu_normal_node_next(np, heap->kfc_normal_list[node_idx].next);
+ heap->kfc_normal_list[node_idx].next = np;
+ return true;
+ }
+
+ /* big block */
+ node = (hmu_tree_node_t *)hmu;
+ node->size = size;
+ node->left = node->right = node->parent = NULL;
+
+ /* find proper node to link this new node to */
+ root = heap->kfc_tree_root;
+ tp = root;
+ bh_assert(tp->size < size);
+ while (1) {
+ if (tp->size < size) {
+ if (!tp->right) {
+ tp->right = node;
+ node->parent = tp;
+ break;
+ }
+ tp = tp->right;
+ }
+ else { /* tp->size >= size */
+ if (!tp->left) {
+ tp->left = node;
+ node->parent = tp;
+ break;
+ }
+ tp = tp->left;
+ }
+ if (!hmu_is_in_heap(tp, base_addr, end_addr)) {
+ heap->is_heap_corrupted = true;
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Find a proper hmu for required memory size
+ *
+ * @param heap should not be NULL and should be a valid heap
+ * @param size should cover the header and should be 8 bytes aligned
+ * GC will not be performed here.
+ * Heap extension will not be performed here.
+ *
+ * @return hmu allocated if success, which will be aligned to 8 bytes,
+ * NULL otherwise
+ */
+static hmu_t *
+alloc_hmu(gc_heap_t *heap, gc_size_t size)
+{
+ gc_uint8 *base_addr, *end_addr;
+ hmu_normal_list_t *normal_head = NULL;
+ hmu_normal_node_t *p = NULL;
+ uint32 node_idx = 0, init_node_idx = 0;
+ hmu_tree_node_t *root = NULL, *tp = NULL, *last_tp = NULL;
+ hmu_t *next, *rest;
+ uintptr_t tp_ret;
+
+ bh_assert(gci_is_heap_valid(heap));
+ bh_assert(size > 0 && !(size & 7));
+
+ base_addr = heap->base_addr;
+ end_addr = base_addr + heap->current_size;
+
+ if (size < GC_SMALLEST_SIZE)
+ size = GC_SMALLEST_SIZE;
+
+ /* check normal list at first*/
+ if (HMU_IS_FC_NORMAL(size)) {
+ /* find a non-empty slot in normal_node_list with good size*/
+ init_node_idx = (size >> 3);
+ for (node_idx = init_node_idx; node_idx < HMU_NORMAL_NODE_CNT;
+ node_idx++) {
+ normal_head = heap->kfc_normal_list + node_idx;
+ if (normal_head->next)
+ break;
+ normal_head = NULL;
+ }
+
+ /* found in normal list*/
+ if (normal_head) {
+ bh_assert(node_idx >= init_node_idx);
+
+ p = normal_head->next;
+ if (!hmu_is_in_heap(p, base_addr, end_addr)) {
+ heap->is_heap_corrupted = true;
+ return NULL;
+ }
+ normal_head->next = get_hmu_normal_node_next(p);
+ if (((gc_int32)(uintptr_t)hmu_to_obj(p) & 7) != 0) {
+ heap->is_heap_corrupted = true;
+ return NULL;
+ }
+
+ if ((gc_size_t)node_idx != (uint32)init_node_idx
+ /* with bigger size*/
+ && ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) {
+ rest = (hmu_t *)(((char *)p) + size);
+ if (!gci_add_fc(heap, rest, (node_idx << 3) - size)) {
+ return NULL;
+ }
+ hmu_mark_pinuse(rest);
+ }
+ else {
+ size = node_idx << 3;
+ next = (hmu_t *)((char *)p + size);
+ if (hmu_is_in_heap(next, base_addr, end_addr))
+ hmu_mark_pinuse(next);
+ }
+
+ heap->total_free_size -= size;
+ if ((heap->current_size - heap->total_free_size)
+ > heap->highmark_size)
+ heap->highmark_size =
+ heap->current_size - heap->total_free_size;
+
+ hmu_set_size((hmu_t *)p, size);
+ return (hmu_t *)p;
+ }
+ }
+
+ /* need to find a node in tree*/
+ root = heap->kfc_tree_root;
+
+ /* find the best node*/
+ bh_assert(root);
+ tp = root->right;
+ while (tp) {
+ if (!hmu_is_in_heap(tp, base_addr, end_addr)) {
+ heap->is_heap_corrupted = true;
+ return NULL;
+ }
+
+ if (tp->size < size) {
+ tp = tp->right;
+ continue;
+ }
+
+ /* record the last node with size equal to or bigger than given size*/
+ last_tp = tp;
+ tp = tp->left;
+ }
+
+ if (last_tp) {
+ bh_assert(last_tp->size >= size);
+
+ /* alloc in last_p*/
+
+ /* remove node last_p from tree*/
+ if (!remove_tree_node(heap, last_tp))
+ return NULL;
+
+ if (last_tp->size >= size + GC_SMALLEST_SIZE) {
+ rest = (hmu_t *)((char *)last_tp + size);
+ if (!gci_add_fc(heap, rest, last_tp->size - size))
+ return NULL;
+ hmu_mark_pinuse(rest);
+ }
+ else {
+ size = last_tp->size;
+ next = (hmu_t *)((char *)last_tp + size);
+ if (hmu_is_in_heap(next, base_addr, end_addr))
+ hmu_mark_pinuse(next);
+ }
+
+ heap->total_free_size -= size;
+ if ((heap->current_size - heap->total_free_size) > heap->highmark_size)
+ heap->highmark_size = heap->current_size - heap->total_free_size;
+
+ hmu_set_size((hmu_t *)last_tp, size);
+ tp_ret = (uintptr_t)last_tp;
+ return (hmu_t *)tp_ret;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find a proper HMU with given size
+ *
+ * @param heap should not be NULL and should be a valid heap
+ * @param size should cover the header and should be 8 bytes aligned
+ *
+ * Note: This function will try several ways to satisfy the allocation request:
+ * 1. Find a proper on available HMUs.
+ * 2. GC will be triggered if 1 failed.
+ * 3. Find a proper on available HMUS.
+ * 4. Return NULL if 3 failed
+ *
+ * @return hmu allocated if success, which will be aligned to 8 bytes,
+ * NULL otherwise
+ */
+static hmu_t *
+alloc_hmu_ex(gc_heap_t *heap, gc_size_t size)
+{
+ bh_assert(gci_is_heap_valid(heap));
+ bh_assert(size > 0 && !(size & 7));
+
+ return alloc_hmu(heap, size);
+}
+
+static unsigned long g_total_malloc = 0;
+static unsigned long g_total_free = 0;
+
+#if BH_ENABLE_GC_VERIFY == 0
+gc_object_t
+gc_alloc_vo(void *vheap, gc_size_t size)
+#else
+gc_object_t
+gc_alloc_vo_internal(void *vheap, gc_size_t size, const char *file, int line)
+#endif
+{
+ gc_heap_t *heap = (gc_heap_t *)vheap;
+ hmu_t *hmu = NULL;
+ gc_object_t ret = (gc_object_t)NULL;
+ gc_size_t tot_size = 0, tot_size_unaligned;
+
+ /* hmu header + prefix + obj + suffix */
+ tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
+ /* aligned size*/
+ tot_size = GC_ALIGN_8(tot_size_unaligned);
+ if (tot_size < size)
+ /* integer overflow */
+ return NULL;
+
+ if (heap->is_heap_corrupted) {
+ os_printf("[GC_ERROR]Heap is corrupted, allocate memory failed.\n");
+ return NULL;
+ }
+
+ os_mutex_lock(&heap->lock);
+
+ hmu = alloc_hmu_ex(heap, tot_size);
+ if (!hmu)
+ goto finish;
+
+ bh_assert(hmu_get_size(hmu) >= tot_size);
+ /* the total size allocated may be larger than
+ the required size, reset it here */
+ tot_size = hmu_get_size(hmu);
+
+ g_total_malloc += tot_size;
+
+ hmu_set_ut(hmu, HMU_VO);
+ hmu_unfree_vo(hmu);
+
+#if BH_ENABLE_GC_VERIFY != 0
+ hmu_init_prefix_and_suffix(hmu, tot_size, file, line);
+#endif
+
+ ret = hmu_to_obj(hmu);
+ if (tot_size > tot_size_unaligned)
+ /* clear buffer appended by GC_ALIGN_8() */
+ memset((uint8 *)ret + size, 0, tot_size - tot_size_unaligned);
+
+finish:
+ os_mutex_unlock(&heap->lock);
+ return ret;
+}
+
+#if BH_ENABLE_GC_VERIFY == 0
+gc_object_t
+gc_realloc_vo(void *vheap, void *ptr, gc_size_t size)
+#else
+gc_object_t
+gc_realloc_vo_internal(void *vheap, void *ptr, gc_size_t size, const char *file,
+ int line)
+#endif
+{
+ gc_heap_t *heap = (gc_heap_t *)vheap;
+ hmu_t *hmu = NULL, *hmu_old = NULL, *hmu_next;
+ gc_object_t ret = (gc_object_t)NULL, obj_old = (gc_object_t)ptr;
+ gc_size_t tot_size, tot_size_unaligned, tot_size_old = 0, tot_size_next;
+ gc_size_t obj_size, obj_size_old;
+ gc_uint8 *base_addr, *end_addr;
+ hmu_type_t ut;
+
+ /* hmu header + prefix + obj + suffix */
+ tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
+ /* aligned size*/
+ tot_size = GC_ALIGN_8(tot_size_unaligned);
+ if (tot_size < size)
+ /* integer overflow */
+ return NULL;
+
+ if (heap->is_heap_corrupted) {
+ os_printf("[GC_ERROR]Heap is corrupted, allocate memory failed.\n");
+ return NULL;
+ }
+
+ if (obj_old) {
+ hmu_old = obj_to_hmu(obj_old);
+ tot_size_old = hmu_get_size(hmu_old);
+ if (tot_size <= tot_size_old)
+ /* current node alreay meets requirement */
+ return obj_old;
+ }
+
+ base_addr = heap->base_addr;
+ end_addr = base_addr + heap->current_size;
+
+ os_mutex_lock(&heap->lock);
+
+ if (hmu_old) {
+ hmu_next = (hmu_t *)((char *)hmu_old + tot_size_old);
+ if (hmu_is_in_heap(hmu_next, base_addr, end_addr)) {
+ ut = hmu_get_ut(hmu_next);
+ tot_size_next = hmu_get_size(hmu_next);
+ if (ut == HMU_FC && tot_size <= tot_size_old + tot_size_next) {
+ /* current node and next node meets requirement */
+ if (!unlink_hmu(heap, hmu_next)) {
+ os_mutex_unlock(&heap->lock);
+ return NULL;
+ }
+ hmu_set_size(hmu_old, tot_size);
+ memset((char *)hmu_old + tot_size_old, 0,
+ tot_size - tot_size_old);
+#if BH_ENABLE_GC_VERIFY != 0
+ hmu_init_prefix_and_suffix(hmu_old, tot_size, file, line);
+#endif
+ if (tot_size < tot_size_old + tot_size_next) {
+ hmu_next = (hmu_t *)((char *)hmu_old + tot_size);
+ tot_size_next = tot_size_old + tot_size_next - tot_size;
+ if (!gci_add_fc(heap, hmu_next, tot_size_next)) {
+ os_mutex_unlock(&heap->lock);
+ return NULL;
+ }
+ }
+ os_mutex_unlock(&heap->lock);
+ return obj_old;
+ }
+ }
+ }
+
+ hmu = alloc_hmu_ex(heap, tot_size);
+ if (!hmu)
+ goto finish;
+
+ bh_assert(hmu_get_size(hmu) >= tot_size);
+ /* the total size allocated may be larger than
+ the required size, reset it here */
+ tot_size = hmu_get_size(hmu);
+ g_total_malloc += tot_size;
+
+ hmu_set_ut(hmu, HMU_VO);
+ hmu_unfree_vo(hmu);
+
+#if BH_ENABLE_GC_VERIFY != 0
+ hmu_init_prefix_and_suffix(hmu, tot_size, file, line);
+#endif
+
+ ret = hmu_to_obj(hmu);
+
+finish:
+
+ if (ret) {
+ obj_size = tot_size - HMU_SIZE - OBJ_PREFIX_SIZE - OBJ_SUFFIX_SIZE;
+ memset(ret, 0, obj_size);
+ if (obj_old) {
+ obj_size_old =
+ tot_size_old - HMU_SIZE - OBJ_PREFIX_SIZE - OBJ_SUFFIX_SIZE;
+ bh_memcpy_s(ret, obj_size, obj_old, obj_size_old);
+ }
+ }
+
+ os_mutex_unlock(&heap->lock);
+
+ if (ret && obj_old)
+ gc_free_vo(vheap, obj_old);
+
+ return ret;
+}
+
+/**
+ * Do some checking to see if given pointer is a possible valid heap
+ * @return GC_TRUE if all checking passed, GC_FALSE otherwise
+ */
+int
+gci_is_heap_valid(gc_heap_t *heap)
+{
+ if (!heap)
+ return GC_FALSE;
+ if (heap->heap_id != (gc_handle_t)heap)
+ return GC_FALSE;
+
+ return GC_TRUE;
+}
+
+#if BH_ENABLE_GC_VERIFY == 0
+int
+gc_free_vo(void *vheap, gc_object_t obj)
+#else
+int
+gc_free_vo_internal(void *vheap, gc_object_t obj, const char *file, int line)
+#endif
+{
+ gc_heap_t *heap = (gc_heap_t *)vheap;
+ gc_uint8 *base_addr, *end_addr;
+ hmu_t *hmu = NULL;
+ hmu_t *prev = NULL;
+ hmu_t *next = NULL;
+ gc_size_t size = 0;
+ hmu_type_t ut;
+ int ret = GC_SUCCESS;
+
+ if (!obj) {
+ return GC_SUCCESS;
+ }
+
+ if (heap->is_heap_corrupted) {
+ os_printf("[GC_ERROR]Heap is corrupted, free memory failed.\n");
+ return GC_ERROR;
+ }
+
+ hmu = obj_to_hmu(obj);
+
+ base_addr = heap->base_addr;
+ end_addr = base_addr + heap->current_size;
+
+ os_mutex_lock(&heap->lock);
+
+ if (hmu_is_in_heap(hmu, base_addr, end_addr)) {
+#if BH_ENABLE_GC_VERIFY != 0
+ hmu_verify(heap, hmu);
+#endif
+ ut = hmu_get_ut(hmu);
+ if (ut == HMU_VO) {
+ if (hmu_is_vo_freed(hmu)) {
+ bh_assert(0);
+ ret = GC_ERROR;
+ goto out;
+ }
+
+ size = hmu_get_size(hmu);
+
+ g_total_free += size;
+
+ heap->total_free_size += size;
+
+ if (!hmu_get_pinuse(hmu)) {
+ prev = (hmu_t *)((char *)hmu - *((int *)hmu - 1));
+
+ if (hmu_is_in_heap(prev, base_addr, end_addr)
+ && hmu_get_ut(prev) == HMU_FC) {
+ size += hmu_get_size(prev);
+ hmu = prev;
+ if (!unlink_hmu(heap, prev)) {
+ ret = GC_ERROR;
+ goto out;
+ }
+ }
+ }
+
+ next = (hmu_t *)((char *)hmu + size);
+ if (hmu_is_in_heap(next, base_addr, end_addr)) {
+ if (hmu_get_ut(next) == HMU_FC) {
+ size += hmu_get_size(next);
+ if (!unlink_hmu(heap, next)) {
+ ret = GC_ERROR;
+ goto out;
+ }
+ next = (hmu_t *)((char *)hmu + size);
+ }
+ }
+
+ if (!gci_add_fc(heap, hmu, size)) {
+ ret = GC_ERROR;
+ goto out;
+ }
+
+ if (hmu_is_in_heap(next, base_addr, end_addr)) {
+ hmu_unmark_pinuse(next);
+ }
+ }
+ else {
+ ret = GC_ERROR;
+ goto out;
+ }
+ ret = GC_SUCCESS;
+ goto out;
+ }
+
+out:
+ os_mutex_unlock(&heap->lock);
+ return ret;
+}
+
+void
+gc_dump_heap_stats(gc_heap_t *heap)
+{
+ os_printf("heap: %p, heap start: %p\n", heap, heap->base_addr);
+ os_printf("total free: %" PRIu32 ", current: %" PRIu32
+ ", highmark: %" PRIu32 "\n",
+ heap->total_free_size, heap->current_size, heap->highmark_size);
+ os_printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n",
+ g_total_malloc, g_total_free, g_total_malloc - g_total_free);
+}
+
+uint32
+gc_get_heap_highmark_size(gc_heap_t *heap)
+{
+ return heap->highmark_size;
+}
+
+void
+gci_dump(gc_heap_t *heap)
+{
+ hmu_t *cur = NULL, *end = NULL;
+ hmu_type_t ut;
+ gc_size_t size;
+ int i = 0, p, mark;
+ char inuse = 'U';
+
+ cur = (hmu_t *)heap->base_addr;
+ end = (hmu_t *)((char *)heap->base_addr + heap->current_size);
+
+ while (cur < end) {
+ ut = hmu_get_ut(cur);
+ size = hmu_get_size(cur);
+ p = hmu_get_pinuse(cur);
+ mark = hmu_is_jo_marked(cur);
+
+ if (ut == HMU_VO)
+ inuse = 'V';
+ else if (ut == HMU_JO)
+ inuse = hmu_is_jo_marked(cur) ? 'J' : 'j';
+ else if (ut == HMU_FC)
+ inuse = 'F';
+
+ if (size == 0 || size > (uint32)((uint8 *)end - (uint8 *)cur)) {
+ os_printf("[GC_ERROR]Heap is corrupted, heap dump failed.\n");
+ heap->is_heap_corrupted = true;
+ return;
+ }
+
+ os_printf("#%d %08" PRIx32 " %" PRIx32 " %d %d"
+ " %c %" PRId32 "\n",
+ i, (int32)((char *)cur - (char *)heap->base_addr), (int32)ut,
+ p, mark, inuse, (int32)hmu_obj_size(size));
+#if BH_ENABLE_GC_VERIFY != 0
+ if (inuse == 'V') {
+ gc_object_prefix_t *prefix = (gc_object_prefix_t *)(cur + 1);
+ os_printf("#%s:%d\n", prefix->file_name, prefix->line_no);
+ }
+#endif
+
+ cur = (hmu_t *)((char *)cur + size);
+ i++;
+ }
+
+ if (cur != end) {
+ os_printf("[GC_ERROR]Heap is corrupted, heap dump failed.\n");
+ heap->is_heap_corrupted = true;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc.h
new file mode 100644
index 000000000..9a74d0046
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/**
+ * @file ems_gc.h
+ * @date Wed Aug 3 10:46:38 2011
+ *
+ * @brief This file defines GC modules types and interfaces.
+ */
+
+#ifndef _EMS_GC_H
+#define _EMS_GC_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GC_HEAD_PADDING 4
+
+#define NULL_REF ((gc_object_t)NULL)
+
+#define GC_SUCCESS (0)
+#define GC_ERROR (-1)
+
+#define GC_TRUE (1)
+#define GC_FALSE (0)
+
+#define GC_MAX_HEAP_SIZE (256 * BH_KB)
+
+typedef void *gc_handle_t;
+typedef void *gc_object_t;
+typedef int64 gc_int64;
+typedef uint32 gc_uint32;
+typedef int32 gc_int32;
+typedef uint16 gc_uint16;
+typedef int16 gc_int16;
+typedef uint8 gc_uint8;
+typedef int8 gc_int8;
+typedef uint32 gc_size_t;
+
+typedef enum {
+ GC_STAT_TOTAL = 0,
+ GC_STAT_FREE,
+ GC_STAT_HIGHMARK,
+} GC_STAT_INDEX;
+
+/**
+ * GC initialization from a buffer, which is separated into
+ * two parts: the beginning of the buffer is used to create
+ * the heap structure, and the left is used to create the
+ * actual pool data
+ *
+ * @param buf the buffer to be initialized to a heap
+ * @param buf_size the size of buffer
+ *
+ * @return gc handle if success, NULL otherwise
+ */
+gc_handle_t
+gc_init_with_pool(char *buf, gc_size_t buf_size);
+
+/**
+ * GC initialization from heap struct buffer and pool buffer
+ *
+ * @param struct_buf the struct buffer to create the heap structure
+ * @param struct_buf_size the size of struct buffer
+ * @param pool_buf the pool buffer to create pool data
+ * @param pool_buf_size the size of poll buffer
+ *
+ * @return gc handle if success, NULL otherwise
+ */
+gc_handle_t
+gc_init_with_struct_and_pool(char *struct_buf, gc_size_t struct_buf_size,
+ char *pool_buf, gc_size_t pool_buf_size);
+
+/**
+ * Destroy heap which is initilized from a buffer
+ *
+ * @param handle handle to heap needed destroy
+ *
+ * @return GC_SUCCESS if success
+ * GC_ERROR for bad parameters or failed system resource freeing.
+ */
+int
+gc_destroy_with_pool(gc_handle_t handle);
+
+/**
+ * Return heap struct size
+ */
+uint32
+gc_get_heap_struct_size(void);
+
+/**
+ * Migrate heap from one pool buf to another pool buf
+ *
+ * @param handle handle of the new heap
+ * @param pool_buf_new the new pool buffer
+ * @param pool_buf_size the size of new pool buffer
+ *
+ * @return GC_SUCCESS if success, GC_ERROR otherwise
+ */
+int
+gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size);
+
+/**
+ * Check whether the heap is corrupted
+ *
+ * @param handle handle of the heap
+ *
+ * @return true if success, false otherwise
+ */
+bool
+gc_is_heap_corrupted(gc_handle_t handle);
+
+/**
+ * Get Heap Stats
+ *
+ * @param stats [out] integer array to save heap stats
+ * @param size [in] the size of stats
+ * @param mmt [in] type of heap, MMT_SHARED or MMT_INSTANCE
+ */
+void *
+gc_heap_stats(void *heap, uint32 *stats, int size);
+
+#if BH_ENABLE_GC_VERIFY == 0
+
+gc_object_t
+gc_alloc_vo(void *heap, gc_size_t size);
+
+gc_object_t
+gc_realloc_vo(void *heap, void *ptr, gc_size_t size);
+
+int
+gc_free_vo(void *heap, gc_object_t obj);
+
+#else /* else of BH_ENABLE_GC_VERIFY */
+
+gc_object_t
+gc_alloc_vo_internal(void *heap, gc_size_t size, const char *file, int line);
+
+gc_object_t
+gc_realloc_vo_internal(void *heap, void *ptr, gc_size_t size, const char *file,
+ int line);
+
+int
+gc_free_vo_internal(void *heap, gc_object_t obj, const char *file, int line);
+
+/* clang-format off */
+#define gc_alloc_vo(heap, size) \
+ gc_alloc_vo_internal(heap, size, __FILE__, __LINE__)
+
+#define gc_realloc_vo(heap, ptr, size) \
+ gc_realloc_vo_internal(heap, ptr, size, __FILE__, __LINE__)
+
+#define gc_free_vo(heap, obj) \
+ gc_free_vo_internal(heap, obj, __FILE__, __LINE__)
+/* clang-format on */
+
+#endif /* end of BH_ENABLE_GC_VERIFY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc_internal.h
new file mode 100644
index 000000000..e1ff9d61d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_gc_internal.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _EMS_GC_INTERNAL_H
+#define _EMS_GC_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bh_platform.h"
+#include "ems_gc.h"
+
+/* HMU (heap memory unit) basic block type */
+typedef enum hmu_type_enum {
+ HMU_TYPE_MIN = 0,
+ HMU_TYPE_MAX = 3,
+ HMU_JO = 3,
+ HMU_VO = 2,
+ HMU_FC = 1,
+ HMU_FM = 0
+} hmu_type_t;
+
+typedef struct hmu_struct {
+ gc_uint32 header;
+} hmu_t;
+
+#if BH_ENABLE_GC_VERIFY != 0
+
+#if UINTPTR_MAX > UINT32_MAX
+/* 2 prefix paddings for 64-bit pointer */
+#define GC_OBJECT_PREFIX_PADDING_CNT 2
+#else
+/* 3 prefix paddings for 32-bit pointer */
+#define GC_OBJECT_PREFIX_PADDING_CNT 3
+#endif
+#define GC_OBJECT_SUFFIX_PADDING_CNT 4
+#define GC_OBJECT_PADDING_VALUE (0x12345678)
+
+typedef struct gc_object_prefix {
+ const char *file_name;
+ gc_int32 line_no;
+ gc_int32 size;
+ gc_uint32 padding[GC_OBJECT_PREFIX_PADDING_CNT];
+} gc_object_prefix_t;
+
+typedef struct gc_object_suffix {
+ gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT];
+} gc_object_suffix_t;
+
+#define OBJ_PREFIX_SIZE (sizeof(gc_object_prefix_t))
+#define OBJ_SUFFIX_SIZE (sizeof(gc_object_suffix_t))
+
+void
+hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size,
+ const char *file_name, int line_no);
+
+void
+hmu_verify(void *vheap, hmu_t *hmu);
+
+#define SKIP_OBJ_PREFIX(p) ((void *)((gc_uint8 *)(p) + OBJ_PREFIX_SIZE))
+#define SKIP_OBJ_SUFFIX(p) ((void *)((gc_uint8 *)(p) + OBJ_SUFFIX_SIZE))
+
+#define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
+
+#else /* else of BH_ENABLE_GC_VERIFY */
+
+#define OBJ_PREFIX_SIZE 0
+#define OBJ_SUFFIX_SIZE 0
+
+#define SKIP_OBJ_PREFIX(p) ((void *)((gc_uint8 *)(p) + OBJ_PREFIX_SIZE))
+#define SKIP_OBJ_SUFFIX(p) ((void *)((gc_uint8 *)(p) + OBJ_SUFFIX_SIZE))
+
+#define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
+
+#endif /* end of BH_ENABLE_GC_VERIFY */
+
+#define hmu_obj_size(s) ((s)-OBJ_EXTRA_SIZE)
+
+#define GC_ALIGN_8(s) (((uint32)(s) + 7) & (uint32)~7)
+
+#define GC_SMALLEST_SIZE \
+ GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8)
+#define GC_GET_REAL_SIZE(x) \
+ GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE \
+ + (((x) > 8) ? (x) : 8))
+
+/**
+ * hmu bit operation
+ */
+
+#define SETBIT(v, offset) (v) |= ((uint32)1 << (offset))
+#define GETBIT(v, offset) ((v) & ((uint32)1 << (offset)) ? 1 : 0)
+#define CLRBIT(v, offset) (v) &= (~((uint32)1 << (offset)))
+
+/* clang-format off */
+#define SETBITS(v, offset, size, value) \
+ do { \
+ (v) &= ~((((uint32)1 << size) - 1) << offset); \
+ (v) |= ((uint32)value << offset); \
+ } while (0)
+#define CLRBITS(v, offset, size) \
+ (v) &= ~((((uint32)1 << size) - 1) << offset)
+#define GETBITS(v, offset, size) \
+ (((v) & (((((uint32)1 << size) - 1) << offset))) >> offset)
+/* clang-format on */
+
+/**
+ * gc object layout definition
+ */
+
+#define HMU_SIZE (sizeof(hmu_t))
+
+#define hmu_to_obj(hmu) (gc_object_t)(SKIP_OBJ_PREFIX((hmu_t *)(hmu) + 1))
+#define obj_to_hmu(obj) ((hmu_t *)((gc_uint8 *)(obj)-OBJ_PREFIX_SIZE) - 1)
+
+#define HMU_UT_SIZE 2
+#define HMU_UT_OFFSET 30
+
+/* clang-format off */
+#define hmu_get_ut(hmu) \
+ GETBITS((hmu)->header, HMU_UT_OFFSET, HMU_UT_SIZE)
+#define hmu_set_ut(hmu, type) \
+ SETBITS((hmu)->header, HMU_UT_OFFSET, HMU_UT_SIZE, type)
+#define hmu_is_ut_valid(tp) \
+ (tp >= HMU_TYPE_MIN && tp <= HMU_TYPE_MAX)
+/* clang-format on */
+
+/* P in use bit means the previous chunk is in use */
+#define HMU_P_OFFSET 29
+
+#define hmu_mark_pinuse(hmu) SETBIT((hmu)->header, HMU_P_OFFSET)
+#define hmu_unmark_pinuse(hmu) CLRBIT((hmu)->header, HMU_P_OFFSET)
+#define hmu_get_pinuse(hmu) GETBIT((hmu)->header, HMU_P_OFFSET)
+
+#define HMU_JO_VT_SIZE 27
+#define HMU_JO_VT_OFFSET 0
+#define HMU_JO_MB_OFFSET 28
+
+#define hmu_mark_jo(hmu) SETBIT((hmu)->header, HMU_JO_MB_OFFSET)
+#define hmu_unmark_jo(hmu) CLRBIT((hmu)->header, HMU_JO_MB_OFFSET)
+#define hmu_is_jo_marked(hmu) GETBIT((hmu)->header, HMU_JO_MB_OFFSET)
+
+/**
+ * The hmu size is divisible by 8, its lowest 3 bits are 0, so we only
+ * store its higher bits of bit [29..3], and bit [2..0] are not stored.
+ * After that, the maximal heap size can be enlarged from (1<<27) = 128MB
+ * to (1<<27) * 8 = 1GB.
+ */
+#define HMU_SIZE_SIZE 27
+#define HMU_SIZE_OFFSET 0
+
+#define HMU_VO_FB_OFFSET 28
+
+#define hmu_is_vo_freed(hmu) GETBIT((hmu)->header, HMU_VO_FB_OFFSET)
+#define hmu_unfree_vo(hmu) CLRBIT((hmu)->header, HMU_VO_FB_OFFSET)
+
+#define hmu_get_size(hmu) \
+ (GETBITS((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE) << 3)
+#define hmu_set_size(hmu, size) \
+ SETBITS((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, ((size) >> 3))
+
+/**
+ * HMU free chunk management
+ */
+
+#ifndef HMU_NORMAL_NODE_CNT
+#define HMU_NORMAL_NODE_CNT 32
+#endif
+#define HMU_FC_NORMAL_MAX_SIZE ((HMU_NORMAL_NODE_CNT - 1) << 3)
+#define HMU_IS_FC_NORMAL(size) ((size) < HMU_FC_NORMAL_MAX_SIZE)
+#if HMU_FC_NORMAL_MAX_SIZE >= GC_MAX_HEAP_SIZE
+#error "Too small GC_MAX_HEAP_SIZE"
+#endif
+
+typedef struct hmu_normal_node {
+ hmu_t hmu_header;
+ gc_int32 next_offset;
+} hmu_normal_node_t;
+
+typedef struct hmu_normal_list {
+ hmu_normal_node_t *next;
+} hmu_normal_list_t;
+
+static inline hmu_normal_node_t *
+get_hmu_normal_node_next(hmu_normal_node_t *node)
+{
+ return node->next_offset
+ ? (hmu_normal_node_t *)((uint8 *)node + node->next_offset)
+ : NULL;
+}
+
+static inline void
+set_hmu_normal_node_next(hmu_normal_node_t *node, hmu_normal_node_t *next)
+{
+ if (next) {
+ bh_assert((uint8 *)next - (uint8 *)node < INT32_MAX);
+ node->next_offset = (gc_int32)(intptr_t)((uint8 *)next - (uint8 *)node);
+ }
+ else {
+ node->next_offset = 0;
+ }
+}
+
+/**
+ * Define hmu_tree_node as a packed struct, since it is at the 4-byte
+ * aligned address and the size of hmu_head is 4, so in 64-bit target,
+ * the left/right/parent fields will be at 8-byte aligned address,
+ * we can access them directly.
+ */
+#if UINTPTR_MAX == UINT64_MAX
+#if defined(_MSC_VER)
+__pragma(pack(push, 1));
+#define __attr_packed
+#elif defined(__GNUC__) || defined(__clang__)
+#define __attr_packed __attribute__((packed))
+#else
+#error "packed attribute isn't used to define struct hmu_tree_node"
+#endif
+#else /* else of UINTPTR_MAX == UINT64_MAX */
+#define __attr_packed
+#endif
+
+typedef struct hmu_tree_node {
+ hmu_t hmu_header;
+ struct hmu_tree_node *left;
+ struct hmu_tree_node *right;
+ struct hmu_tree_node *parent;
+ gc_size_t size;
+} __attr_packed hmu_tree_node_t;
+
+#if UINTPTR_MAX == UINT64_MAX
+#if defined(_MSC_VER)
+__pragma(pack(pop));
+#endif
+#endif
+
+bh_static_assert(sizeof(hmu_tree_node_t) == 8 + 3 * sizeof(void *));
+bh_static_assert(offsetof(hmu_tree_node_t, left) == 4);
+
+#define ASSERT_TREE_NODE_ALIGNED_ACCESS(tree_node) \
+ do { \
+ bh_assert((((uintptr_t)&tree_node->left) & (sizeof(uintptr_t) - 1)) \
+ == 0); \
+ } while (0)
+
+typedef struct gc_heap_struct {
+ /* for double checking*/
+ gc_handle_t heap_id;
+
+ gc_uint8 *base_addr;
+ gc_size_t current_size;
+
+ korp_mutex lock;
+
+ hmu_normal_list_t kfc_normal_list[HMU_NORMAL_NODE_CNT];
+
+#if UINTPTR_MAX == UINT64_MAX
+ /* make kfc_tree_root_buf 4-byte aligned and not 8-byte aligned,
+ so kfc_tree_root's left/right/parent fields are 8-byte aligned
+ and we can access them directly */
+ uint32 __padding;
+#endif
+ uint8 kfc_tree_root_buf[sizeof(hmu_tree_node_t)];
+ /* point to kfc_tree_root_buf, the order in kfc_tree is:
+ size[left] <= size[cur] < size[right] */
+ hmu_tree_node_t *kfc_tree_root;
+
+ /* whether heap is corrupted, e.g. the hmu nodes are modified
+ by user */
+ bool is_heap_corrupted;
+
+ gc_size_t init_size;
+ gc_size_t highmark_size;
+ gc_size_t total_free_size;
+} gc_heap_t;
+
+/**
+ * MISC internal used APIs
+ */
+
+bool
+gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size);
+
+int
+gci_is_heap_valid(gc_heap_t *heap);
+
+/**
+ * Verify heap integrity
+ */
+void
+gci_verify_heap(gc_heap_t *heap);
+
+/**
+ * Dump heap nodes
+ */
+void
+gci_dump(gc_heap_t *heap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _EMS_GC_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_hmu.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_hmu.c
new file mode 100644
index 000000000..41745e161
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_hmu.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "ems_gc_internal.h"
+
+#if BH_ENABLE_GC_VERIFY != 0
+
+/**
+ * Set default value to prefix and suffix
+ * @param hmu should not be NULL and should have been correctly initilized
+ * (except prefix and suffix part)
+ * @param tot_size is offered here because hmu_get_size can not be used
+ * till now. tot_size should not be smaller than OBJ_EXTRA_SIZE.
+ * For VO, tot_size should be equal to object total size.
+ */
+void
+hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size,
+ const char *file_name, int line_no)
+{
+ gc_object_prefix_t *prefix = NULL;
+ gc_object_suffix_t *suffix = NULL;
+ gc_uint32 i = 0;
+
+ bh_assert(hmu);
+ bh_assert(hmu_get_ut(hmu) == HMU_JO || hmu_get_ut(hmu) == HMU_VO);
+ bh_assert(tot_size >= OBJ_EXTRA_SIZE);
+ bh_assert(!(tot_size & 7));
+ bh_assert(hmu_get_ut(hmu) != HMU_VO || hmu_get_size(hmu) >= tot_size);
+
+ prefix = (gc_object_prefix_t *)(hmu + 1);
+ suffix =
+ (gc_object_suffix_t *)((gc_uint8 *)hmu + tot_size - OBJ_SUFFIX_SIZE);
+ prefix->file_name = file_name;
+ prefix->line_no = line_no;
+ prefix->size = tot_size;
+
+ for (i = 0; i < GC_OBJECT_PREFIX_PADDING_CNT; i++) {
+ prefix->padding[i] = GC_OBJECT_PADDING_VALUE;
+ }
+
+ for (i = 0; i < GC_OBJECT_SUFFIX_PADDING_CNT; i++) {
+ suffix->padding[i] = GC_OBJECT_PADDING_VALUE;
+ }
+}
+
+void
+hmu_verify(void *vheap, hmu_t *hmu)
+{
+ gc_heap_t *heap = (gc_heap_t *)vheap;
+ gc_object_prefix_t *prefix = NULL;
+ gc_object_suffix_t *suffix = NULL;
+ gc_uint32 i = 0;
+ hmu_type_t ut;
+ gc_size_t size = 0;
+ int is_padding_ok = 1;
+
+ bh_assert(hmu);
+ ut = hmu_get_ut(hmu);
+ bh_assert(hmu_is_ut_valid(ut));
+
+ prefix = (gc_object_prefix_t *)(hmu + 1);
+ size = prefix->size;
+ suffix = (gc_object_suffix_t *)((gc_uint8 *)hmu + size - OBJ_SUFFIX_SIZE);
+
+ if (ut == HMU_VO || ut == HMU_JO) {
+ /* check padding*/
+ for (i = 0; i < GC_OBJECT_PREFIX_PADDING_CNT; i++) {
+ if (prefix->padding[i] != GC_OBJECT_PADDING_VALUE) {
+ is_padding_ok = 0;
+ break;
+ }
+ }
+ for (i = 0; i < GC_OBJECT_SUFFIX_PADDING_CNT; i++) {
+ if (suffix->padding[i] != GC_OBJECT_PADDING_VALUE) {
+ is_padding_ok = 0;
+ break;
+ }
+ }
+
+ if (!is_padding_ok) {
+ os_printf("Invalid padding for object created at %s:%d\n",
+ (prefix->file_name ? prefix->file_name : ""),
+ prefix->line_no);
+ heap->is_heap_corrupted = true;
+ }
+ }
+}
+
+#endif /* end of BH_ENABLE_GC_VERIFY */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_kfc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_kfc.c
new file mode 100644
index 000000000..80d202679
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/ems/ems_kfc.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "ems_gc_internal.h"
+
+static gc_handle_t
+gc_init_internal(gc_heap_t *heap, char *base_addr, gc_size_t heap_max_size)
+{
+ hmu_tree_node_t *root = NULL, *q = NULL;
+ int ret;
+
+ memset(heap, 0, sizeof *heap);
+
+ ret = os_mutex_init(&heap->lock);
+ if (ret != BHT_OK) {
+ os_printf("[GC_ERROR]failed to init lock\n");
+ return NULL;
+ }
+
+ /* init all data structures*/
+ heap->current_size = heap_max_size;
+ heap->base_addr = (gc_uint8 *)base_addr;
+ heap->heap_id = (gc_handle_t)heap;
+
+ heap->total_free_size = heap->current_size;
+ heap->highmark_size = 0;
+
+ root = heap->kfc_tree_root = (hmu_tree_node_t *)heap->kfc_tree_root_buf;
+ memset(root, 0, sizeof *root);
+ root->size = sizeof *root;
+ hmu_set_ut(&root->hmu_header, HMU_FC);
+ hmu_set_size(&root->hmu_header, sizeof *root);
+
+ q = (hmu_tree_node_t *)heap->base_addr;
+ memset(q, 0, sizeof *q);
+ hmu_set_ut(&q->hmu_header, HMU_FC);
+ hmu_set_size(&q->hmu_header, heap->current_size);
+
+ ASSERT_TREE_NODE_ALIGNED_ACCESS(q);
+ ASSERT_TREE_NODE_ALIGNED_ACCESS(root);
+
+ hmu_mark_pinuse(&q->hmu_header);
+ root->right = q;
+ q->parent = root;
+ q->size = heap->current_size;
+
+ bh_assert(root->size <= HMU_FC_NORMAL_MAX_SIZE);
+
+ return heap;
+}
+
+gc_handle_t
+gc_init_with_pool(char *buf, gc_size_t buf_size)
+{
+ char *buf_end = buf + buf_size;
+ char *buf_aligned = (char *)(((uintptr_t)buf + 7) & (uintptr_t)~7);
+ char *base_addr = buf_aligned + sizeof(gc_heap_t);
+ gc_heap_t *heap = (gc_heap_t *)buf_aligned;
+ gc_size_t heap_max_size;
+
+ if (buf_size < APP_HEAP_SIZE_MIN) {
+ os_printf("[GC_ERROR]heap init buf size (%" PRIu32 ") < %" PRIu32 "\n",
+ buf_size, (uint32)APP_HEAP_SIZE_MIN);
+ return NULL;
+ }
+
+ base_addr =
+ (char *)(((uintptr_t)base_addr + 7) & (uintptr_t)~7) + GC_HEAD_PADDING;
+ heap_max_size = (uint32)(buf_end - base_addr) & (uint32)~7;
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ os_printf("Heap created, total size: %u\n", buf_size);
+ os_printf(" heap struct size: %u\n", sizeof(gc_heap_t));
+ os_printf(" actual heap size: %u\n", heap_max_size);
+ os_printf(" padding bytes: %u\n",
+ buf_size - sizeof(gc_heap_t) - heap_max_size);
+#endif
+ return gc_init_internal(heap, base_addr, heap_max_size);
+}
+
+gc_handle_t
+gc_init_with_struct_and_pool(char *struct_buf, gc_size_t struct_buf_size,
+ char *pool_buf, gc_size_t pool_buf_size)
+{
+ gc_heap_t *heap = (gc_heap_t *)struct_buf;
+ char *base_addr = pool_buf + GC_HEAD_PADDING;
+ char *pool_buf_end = pool_buf + pool_buf_size;
+ gc_size_t heap_max_size;
+
+ if ((((uintptr_t)struct_buf) & 7) != 0) {
+ os_printf("[GC_ERROR]heap init struct buf not 8-byte aligned\n");
+ return NULL;
+ }
+
+ if (struct_buf_size < sizeof(gc_handle_t)) {
+ os_printf("[GC_ERROR]heap init struct buf size (%" PRIu32 ") < %zu\n",
+ struct_buf_size, sizeof(gc_handle_t));
+ return NULL;
+ }
+
+ if ((((uintptr_t)pool_buf) & 7) != 0) {
+ os_printf("[GC_ERROR]heap init pool buf not 8-byte aligned\n");
+ return NULL;
+ }
+
+ if (pool_buf_size < APP_HEAP_SIZE_MIN) {
+ os_printf("[GC_ERROR]heap init buf size (%" PRIu32 ") < %u\n",
+ pool_buf_size, APP_HEAP_SIZE_MIN);
+ return NULL;
+ }
+
+ heap_max_size = (uint32)(pool_buf_end - base_addr) & (uint32)~7;
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ os_printf("Heap created, total size: %u\n",
+ struct_buf_size + pool_buf_size);
+ os_printf(" heap struct size: %u\n", sizeof(gc_heap_t));
+ os_printf(" actual heap size: %u\n", heap_max_size);
+ os_printf(" padding bytes: %u\n", pool_buf_size - heap_max_size);
+#endif
+ return gc_init_internal(heap, base_addr, heap_max_size);
+}
+
+int
+gc_destroy_with_pool(gc_handle_t handle)
+{
+ gc_heap_t *heap = (gc_heap_t *)handle;
+ int ret = GC_SUCCESS;
+
+#if BH_ENABLE_GC_VERIFY != 0
+ hmu_t *cur = (hmu_t *)heap->base_addr;
+ hmu_t *end = (hmu_t *)((char *)heap->base_addr + heap->current_size);
+
+ if (!heap->is_heap_corrupted
+ && (hmu_t *)((char *)cur + hmu_get_size(cur)) != end) {
+ os_printf("Memory leak detected:\n");
+ gci_dump(heap);
+ ret = GC_ERROR;
+ }
+#endif
+
+ os_mutex_destroy(&heap->lock);
+ memset(heap, 0, sizeof(gc_heap_t));
+ return ret;
+}
+
+uint32
+gc_get_heap_struct_size()
+{
+ return sizeof(gc_heap_t);
+}
+
+static void
+adjust_ptr(uint8 **p_ptr, intptr_t offset)
+{
+ if (*p_ptr)
+ *p_ptr = (uint8 *)((intptr_t)(*p_ptr) + offset);
+}
+
+int
+gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size)
+{
+ gc_heap_t *heap = (gc_heap_t *)handle;
+ char *base_addr_new = pool_buf_new + GC_HEAD_PADDING;
+ char *pool_buf_end = pool_buf_new + pool_buf_size;
+ intptr_t offset = (uint8 *)base_addr_new - (uint8 *)heap->base_addr;
+ hmu_t *cur = NULL, *end = NULL;
+ hmu_tree_node_t *tree_node;
+ uint8 **p_left, **p_right, **p_parent;
+ gc_size_t heap_max_size, size;
+
+ if ((((uintptr_t)pool_buf_new) & 7) != 0) {
+ os_printf("[GC_ERROR]heap migrate pool buf not 8-byte aligned\n");
+ return GC_ERROR;
+ }
+
+ heap_max_size = (uint32)(pool_buf_end - base_addr_new) & (uint32)~7;
+
+ if (pool_buf_end < base_addr_new || heap_max_size < heap->current_size) {
+ os_printf("[GC_ERROR]heap migrate invlaid pool buf size\n");
+ return GC_ERROR;
+ }
+
+ if (offset == 0)
+ return 0;
+
+ if (heap->is_heap_corrupted) {
+ os_printf("[GC_ERROR]Heap is corrupted, heap migrate failed.\n");
+ return GC_ERROR;
+ }
+
+ heap->base_addr = (uint8 *)base_addr_new;
+
+ ASSERT_TREE_NODE_ALIGNED_ACCESS(heap->kfc_tree_root);
+
+ p_left = (uint8 **)((uint8 *)heap->kfc_tree_root
+ + offsetof(hmu_tree_node_t, left));
+ p_right = (uint8 **)((uint8 *)heap->kfc_tree_root
+ + offsetof(hmu_tree_node_t, right));
+ p_parent = (uint8 **)((uint8 *)heap->kfc_tree_root
+ + offsetof(hmu_tree_node_t, parent));
+ adjust_ptr(p_left, offset);
+ adjust_ptr(p_right, offset);
+ adjust_ptr(p_parent, offset);
+
+ cur = (hmu_t *)heap->base_addr;
+ end = (hmu_t *)((char *)heap->base_addr + heap->current_size);
+
+ while (cur < end) {
+ size = hmu_get_size(cur);
+
+ if (size <= 0 || size > (uint32)((uint8 *)end - (uint8 *)cur)) {
+ os_printf("[GC_ERROR]Heap is corrupted, heap migrate failed.\n");
+ heap->is_heap_corrupted = true;
+ return GC_ERROR;
+ }
+
+ if (hmu_get_ut(cur) == HMU_FC && !HMU_IS_FC_NORMAL(size)) {
+ tree_node = (hmu_tree_node_t *)cur;
+
+ ASSERT_TREE_NODE_ALIGNED_ACCESS(tree_node);
+
+ p_left = (uint8 **)((uint8 *)tree_node
+ + offsetof(hmu_tree_node_t, left));
+ p_right = (uint8 **)((uint8 *)tree_node
+ + offsetof(hmu_tree_node_t, right));
+ p_parent = (uint8 **)((uint8 *)tree_node
+ + offsetof(hmu_tree_node_t, parent));
+ adjust_ptr(p_left, offset);
+ adjust_ptr(p_right, offset);
+ if (tree_node->parent != heap->kfc_tree_root)
+ /* The root node belongs to heap structure,
+ it is fixed part and isn't changed. */
+ adjust_ptr(p_parent, offset);
+ }
+ cur = (hmu_t *)((char *)cur + size);
+ }
+
+ if (cur != end) {
+ os_printf("[GC_ERROR]Heap is corrupted, heap migrate failed.\n");
+ heap->is_heap_corrupted = true;
+ return GC_ERROR;
+ }
+
+ return 0;
+}
+
+bool
+gc_is_heap_corrupted(gc_handle_t handle)
+{
+ gc_heap_t *heap = (gc_heap_t *)handle;
+
+ return heap->is_heap_corrupted ? true : false;
+}
+
+#if BH_ENABLE_GC_VERIFY != 0
+void
+gci_verify_heap(gc_heap_t *heap)
+{
+ hmu_t *cur = NULL, *end = NULL;
+
+ bh_assert(heap && gci_is_heap_valid(heap));
+ cur = (hmu_t *)heap->base_addr;
+ end = (hmu_t *)(heap->base_addr + heap->current_size);
+ while (cur < end) {
+ hmu_verify(heap, cur);
+ cur = (hmu_t *)((gc_uint8 *)cur + hmu_get_size(cur));
+ }
+ bh_assert(cur == end);
+}
+#endif
+
+void *
+gc_heap_stats(void *heap_arg, uint32 *stats, int size)
+{
+ int i;
+ gc_heap_t *heap = (gc_heap_t *)heap_arg;
+
+ for (i = 0; i < size; i++) {
+ switch (i) {
+ case GC_STAT_TOTAL:
+ stats[i] = heap->current_size;
+ break;
+ case GC_STAT_FREE:
+ stats[i] = heap->total_free_size;
+ break;
+ case GC_STAT_HIGHMARK:
+ stats[i] = heap->highmark_size;
+ break;
+ default:
+ break;
+ }
+ }
+ return heap;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.c
new file mode 100644
index 000000000..f952c1858
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "mem_alloc.h"
+
+#if DEFAULT_MEM_ALLOCATOR == MEM_ALLOCATOR_EMS
+
+#include "ems/ems_gc.h"
+
+mem_allocator_t
+mem_allocator_create(void *mem, uint32_t size)
+{
+ return gc_init_with_pool((char *)mem, size);
+}
+
+mem_allocator_t
+mem_allocator_create_with_struct_and_pool(void *struct_buf,
+ uint32_t struct_buf_size,
+ void *pool_buf,
+ uint32_t pool_buf_size)
+{
+ return gc_init_with_struct_and_pool((char *)struct_buf, struct_buf_size,
+ pool_buf, pool_buf_size);
+}
+
+int
+mem_allocator_destroy(mem_allocator_t allocator)
+{
+ return gc_destroy_with_pool((gc_handle_t)allocator);
+}
+
+uint32
+mem_allocator_get_heap_struct_size()
+{
+ return gc_get_heap_struct_size();
+}
+
+void *
+mem_allocator_malloc(mem_allocator_t allocator, uint32_t size)
+{
+ return gc_alloc_vo((gc_handle_t)allocator, size);
+}
+
+void *
+mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size)
+{
+ return gc_realloc_vo((gc_handle_t)allocator, ptr, size);
+}
+
+void
+mem_allocator_free(mem_allocator_t allocator, void *ptr)
+{
+ if (ptr)
+ gc_free_vo((gc_handle_t)allocator, ptr);
+}
+
+int
+mem_allocator_migrate(mem_allocator_t allocator, char *pool_buf_new,
+ uint32 pool_buf_size)
+{
+ return gc_migrate((gc_handle_t)allocator, pool_buf_new, pool_buf_size);
+}
+
+bool
+mem_allocator_is_heap_corrupted(mem_allocator_t allocator)
+{
+ return gc_is_heap_corrupted((gc_handle_t)allocator);
+}
+
+bool
+mem_allocator_get_alloc_info(mem_allocator_t allocator, void *mem_alloc_info)
+{
+ gc_heap_stats((gc_handle_t)allocator, mem_alloc_info, 3);
+ return true;
+}
+
+#else /* else of DEFAULT_MEM_ALLOCATOR */
+
+#include "tlsf/tlsf.h"
+
+typedef struct mem_allocator_tlsf {
+ tlsf_t tlsf;
+ korp_mutex lock;
+} mem_allocator_tlsf;
+
+mem_allocator_t
+mem_allocator_create(void *mem, uint32_t size)
+{
+ mem_allocator_tlsf *allocator_tlsf;
+ tlsf_t tlsf;
+ char *mem_aligned = (char *)(((uintptr_t)mem + 3) & ~3);
+
+ if (size < 1024) {
+ printf("Create mem allocator failed: pool size must be "
+ "at least 1024 bytes.\n");
+ return NULL;
+ }
+
+ size -= mem_aligned - (char *)mem;
+ mem = (void *)mem_aligned;
+
+ tlsf = tlsf_create_with_pool(mem, size);
+ if (!tlsf) {
+ printf("Create mem allocator failed: tlsf_create_with_pool failed.\n");
+ return NULL;
+ }
+
+ allocator_tlsf = tlsf_malloc(tlsf, sizeof(mem_allocator_tlsf));
+ if (!allocator_tlsf) {
+ printf("Create mem allocator failed: tlsf_malloc failed.\n");
+ tlsf_destroy(tlsf);
+ return NULL;
+ }
+
+ allocator_tlsf->tlsf = tlsf;
+
+ if (os_mutex_init(&allocator_tlsf->lock)) {
+ printf("Create mem allocator failed: tlsf_malloc failed.\n");
+ tlsf_free(tlsf, allocator_tlsf);
+ tlsf_destroy(tlsf);
+ return NULL;
+ }
+
+ return allocator_tlsf;
+}
+
+void
+mem_allocator_destroy(mem_allocator_t allocator)
+{
+ mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
+ tlsf_t tlsf = allocator_tlsf->tlsf;
+
+ os_mutex_destroy(&allocator_tlsf->lock);
+ tlsf_free(tlsf, allocator_tlsf);
+ tlsf_destroy(tlsf);
+}
+
+void *
+mem_allocator_malloc(mem_allocator_t allocator, uint32_t size)
+{
+ void *ret;
+ mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
+
+ if (size == 0)
+ /* tlsf doesn't allow to allocate 0 byte */
+ size = 1;
+
+ os_mutex_lock(&allocator_tlsf->lock);
+ ret = tlsf_malloc(allocator_tlsf->tlsf, size);
+ os_mutex_unlock(&allocator_tlsf->lock);
+ return ret;
+}
+
+void *
+mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size)
+{
+ void *ret;
+ mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
+
+ if (size == 0)
+ /* tlsf doesn't allow to allocate 0 byte */
+ size = 1;
+
+ os_mutex_lock(&allocator_tlsf->lock);
+ ret = tlsf_realloc(allocator_tlsf->tlsf, ptr, size);
+ os_mutex_unlock(&allocator_tlsf->lock);
+ return ret;
+}
+
+void
+mem_allocator_free(mem_allocator_t allocator, void *ptr)
+{
+ if (ptr) {
+ mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
+ os_mutex_lock(&allocator_tlsf->lock);
+ tlsf_free(allocator_tlsf->tlsf, ptr);
+ os_mutex_unlock(&allocator_tlsf->lock);
+ }
+}
+
+int
+mem_allocator_migrate(mem_allocator_t allocator, mem_allocator_t allocator_old)
+{
+ return tlsf_migrate((mem_allocator_tlsf *)allocator,
+ (mem_allocator_tlsf *)allocator_old);
+}
+
+#endif /* end of DEFAULT_MEM_ALLOCATOR */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.cmake
new file mode 100644
index 000000000..c0b4157f4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.cmake
@@ -0,0 +1,19 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+set (MEM_ALLOC_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${MEM_ALLOC_DIR})
+
+if (WAMR_BUILD_GC_VERIFY EQUAL 1)
+ add_definitions (-DBH_ENABLE_GC_VERIFY=1)
+endif ()
+
+file (GLOB_RECURSE source_all
+ ${MEM_ALLOC_DIR}/ems/*.c
+ ${MEM_ALLOC_DIR}/tlsf/*.c
+ ${MEM_ALLOC_DIR}/mem_alloc.c)
+
+set (MEM_ALLOC_SHARED_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.h
new file mode 100644
index 000000000..1f35b2792
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/mem-alloc/mem_alloc.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __MEM_ALLOC_H
+#define __MEM_ALLOC_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *mem_allocator_t;
+
+mem_allocator_t
+mem_allocator_create(void *mem, uint32_t size);
+
+mem_allocator_t
+mem_allocator_create_with_struct_and_pool(void *struct_buf,
+ uint32_t struct_buf_size,
+ void *pool_buf,
+ uint32_t pool_buf_size);
+
+int
+mem_allocator_destroy(mem_allocator_t allocator);
+
+uint32
+mem_allocator_get_heap_struct_size(void);
+
+void *
+mem_allocator_malloc(mem_allocator_t allocator, uint32_t size);
+
+void *
+mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size);
+
+void
+mem_allocator_free(mem_allocator_t allocator, void *ptr);
+
+int
+mem_allocator_migrate(mem_allocator_t allocator, char *pool_buf_new,
+ uint32 pool_buf_size);
+
+bool
+mem_allocator_is_heap_corrupted(mem_allocator_t allocator);
+
+bool
+mem_allocator_get_alloc_info(mem_allocator_t allocator, void *mem_alloc_info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef __MEM_ALLOC_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/README.md
new file mode 100644
index 000000000..de6f1cc68
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/README.md
@@ -0,0 +1,10 @@
+This folder contains the platform abstract layer for multiple platforms. To support a new platform, you can simply create a new folder here and implement all the APIs defined in [`include`](./include) folder.
+
+
+
+Refer to [port_wamr.md](../../../doc/port_wamr.md) for how to port WAMR to a target platform.
+
+
+
+
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_platform.c
new file mode 100644
index 000000000..c9f5f17e6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_platform.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+int
+os_thread_sys_init();
+
+void
+os_thread_sys_destroy();
+
+int
+bh_platform_init()
+{
+ return os_thread_sys_init();
+}
+
+void
+bh_platform_destroy()
+{
+ os_thread_sys_destroy();
+}
+
+void *
+os_malloc(unsigned size)
+{
+ return NULL;
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return NULL;
+}
+
+void
+os_free(void *ptr)
+{}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ if ((uint64)size >= UINT32_MAX)
+ return NULL;
+ return BH_MALLOC((uint32)size);
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ return BH_FREE(addr);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ return 0;
+}
+
+void
+os_dcache_flush()
+{}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_thread.c
new file mode 100644
index 000000000..0efd2f394
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_thread.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+/* clang-format off */
+#define bh_assert(v) do { \
+ if (!(v)) { \
+ printf("\nASSERTION FAILED: %s, at %s, line %d\n", \
+ #v, __FILE__, __LINE__); \
+ aos_reboot(); \
+ while (1); \
+ } \
+} while (0)
+/* clang-format on */
+
+struct os_thread_data;
+typedef struct os_thread_wait_node {
+ aos_sem_t sem;
+ os_thread_wait_list next;
+} os_thread_wait_node;
+
+typedef struct os_thread_data {
+ /* Thread body */
+ aos_task_t thread;
+ /* Thread start routine */
+ thread_start_routine_t start_routine;
+ /* Thread start routine argument */
+ void *arg;
+ /* Thread local root */
+ void *tlr;
+ /* Wait node of current thread */
+ os_thread_wait_node wait_node;
+ /* Lock for waiting list */
+ aos_mutex_t wait_list_lock;
+ /* Waiting list of other threads who are joining this thread */
+ os_thread_wait_list thread_wait_list;
+} os_thread_data;
+
+static bool is_thread_sys_inited = false;
+
+/* Thread data of supervisor thread */
+static os_thread_data supervisor_thread_data;
+
+/* Thread data key */
+static aos_task_key_t thread_data_key;
+
+/* Thread name index */
+static int thread_name_index;
+
+int
+os_thread_sys_init()
+{
+ if (is_thread_sys_inited)
+ return BHT_OK;
+
+ if (aos_task_key_create(&thread_data_key) != 0)
+ return BHT_ERROR;
+
+ /* Initialize supervisor thread data */
+ memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
+
+ if (aos_sem_new(&supervisor_thread_data.wait_node.sem, 1) != 0) {
+ aos_task_key_delete(thread_data_key);
+ return BHT_ERROR;
+ }
+
+ if (aos_task_setspecific(thread_data_key, &supervisor_thread_data)) {
+ aos_sem_free(&supervisor_thread_data.wait_node.sem);
+ aos_task_key_delete(thread_data_key);
+ return BHT_ERROR;
+ }
+
+ is_thread_sys_inited = true;
+ return BHT_OK;
+}
+
+void
+os_thread_sys_destroy()
+{
+ if (is_thread_sys_inited) {
+ aos_task_key_delete(thread_data_key);
+ aos_sem_free(&supervisor_thread_data.wait_node.sem);
+ is_thread_sys_inited = false;
+ }
+}
+
+static os_thread_data *
+thread_data_current()
+{
+ return aos_task_getspecific(thread_data_key);
+}
+
+static void
+os_thread_cleanup(void)
+{
+ os_thread_data *thread_data = thread_data_current();
+ os_thread_wait_list thread_wait_list;
+ aos_mutex_t *wait_list_lock;
+ aos_sem_t *wait_node_sem;
+
+ bh_assert(thread_data != NULL);
+ wait_list_lock = &thread_data->wait_list_lock;
+ thread_wait_list = thread_data->thread_wait_list;
+ wait_node_sem = &thread_data->wait_node.sem;
+
+ /* Free thread data firstly */
+ BH_FREE(thread_data);
+
+ aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER);
+ if (thread_wait_list) {
+ /* Signal each joining thread */
+ os_thread_wait_list head = thread_wait_list;
+ while (head) {
+ os_thread_wait_list next = head->next;
+ aos_sem_signal(&head->sem);
+ head = next;
+ }
+ }
+ aos_mutex_unlock(wait_list_lock);
+
+ /* Free sem and lock */
+ aos_sem_free(wait_node_sem);
+ aos_mutex_free(wait_list_lock);
+}
+
+static void
+os_thread_wrapper(void *arg)
+{
+ os_thread_data *thread_data = arg;
+
+ /* Set thread custom data */
+ if (!aos_task_setspecific(thread_data_key, thread_data))
+ thread_data->start_routine(thread_data->arg);
+
+ os_thread_cleanup();
+}
+
+int
+os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(p_tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+int
+os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ os_thread_data *thread_data;
+ char thread_name[32];
+
+ if (!p_tid || !stack_size)
+ return BHT_ERROR;
+
+ /* Create and initialize thread data */
+ if (!(thread_data = BH_MALLOC(sizeof(os_thread_data))))
+ return BHT_ERROR;
+
+ memset(thread_data, 0, sizeof(os_thread_data));
+
+ thread_data->start_routine = start;
+ thread_data->arg = arg;
+
+ if (aos_sem_new(&thread_data->wait_node.sem, 1) != 0)
+ goto fail1;
+
+ if (aos_mutex_new(&thread_data->wait_list_lock))
+ goto fail2;
+
+ snprintf(thread_name, sizeof(thread_name), "%s%d", "wasm-thread-",
+ ++thread_name_index);
+
+ /* Create the thread */
+ if (aos_task_new_ext((aos_task_t *)thread_data, thread_name,
+ os_thread_wrapper, thread_data, stack_size, prio))
+ goto fail3;
+
+ aos_msleep(10);
+ *p_tid = (korp_tid)thread_data;
+ return BHT_OK;
+
+fail3:
+ aos_mutex_free(&thread_data->wait_list_lock);
+fail2:
+ aos_sem_free(&thread_data->wait_node.sem);
+fail1:
+ BH_FREE(thread_data);
+ return BHT_ERROR;
+}
+
+korp_tid
+os_self_thread()
+{
+ return (korp_tid)aos_task_getspecific(thread_data_key);
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+ (void)value_ptr;
+ os_thread_data *thread_data, *curr_thread_data;
+
+ /* Get thread data of current thread */
+ curr_thread_data = thread_data_current();
+ curr_thread_data->wait_node.next = NULL;
+
+ /* Get thread data */
+ thread_data = (os_thread_data *)thread;
+
+ aos_mutex_lock(&thread_data->wait_list_lock, AOS_WAIT_FOREVER);
+ if (!thread_data->thread_wait_list)
+ thread_data->thread_wait_list = &curr_thread_data->wait_node;
+ else {
+ /* Add to end of waiting list */
+ os_thread_wait_node *p = thread_data->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = &curr_thread_data->wait_node;
+ }
+ aos_mutex_unlock(&thread_data->wait_list_lock);
+
+ /* Wait the sem */
+ aos_sem_wait(&curr_thread_data->wait_node.sem, AOS_WAIT_FOREVER);
+
+ return BHT_OK;
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ aos_mutex_free(mutex);
+ return BHT_OK;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ return aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ return aos_mutex_unlock(mutex);
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ if (aos_mutex_new(&cond->wait_list_lock) != 0)
+ return BHT_ERROR;
+
+ cond->thread_wait_list = NULL;
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ aos_mutex_free(&cond->wait_list_lock);
+ return BHT_OK;
+}
+
+static int
+os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed,
+ uint32 mills)
+{
+ os_thread_wait_node *node = &thread_data_current()->wait_node;
+
+ node->next = NULL;
+
+ aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
+ if (!cond->thread_wait_list)
+ cond->thread_wait_list = node;
+ else {
+ /* Add to end of wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = node;
+ }
+ aos_mutex_unlock(&cond->wait_list_lock);
+
+ /* Unlock mutex, wait sem and lock mutex again */
+ aos_mutex_unlock(mutex);
+ aos_sem_wait(&node->sem, timed ? mills : AOS_WAIT_FOREVER);
+ aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
+
+ /* Remove wait node from wait list */
+ aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
+ if (cond->thread_wait_list == node)
+ cond->thread_wait_list = node->next;
+ else {
+ /* Remove from the wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next != node)
+ p = p->next;
+ p->next = node->next;
+ }
+ aos_mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return os_cond_wait_internal(cond, mutex, false, 0);
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ if (useconds == BHT_WAIT_FOREVER) {
+ return os_cond_wait_internal(cond, mutex, false, 0);
+ }
+ else {
+ uint64 mills_64 = useconds / 1000;
+ uint32 mills;
+
+ if (mills_64 < (uint64)(UINT32_MAX - 1)) {
+ mills = (uint64)mills_64;
+ }
+ else {
+ mills = UINT32_MAX - 1;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+ return os_cond_wait_internal(cond, mutex, true, mills);
+ }
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ /* Signal the head wait node of wait list */
+ aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
+ if (cond->thread_wait_list)
+ aos_sem_signal(&cond->thread_wait_list->sem);
+ aos_mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+ /* TODO: get alios stack boundary */
+ return NULL;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_time.c
new file mode 100644
index 000000000..549252738
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/alios_time.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+uint64
+os_time_get_boot_microsecond()
+{
+ return (uint64)aos_now_ms() * 1000;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/platform_internal.h
new file mode 100644
index 000000000..f6a4ba11e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/platform_internal.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <aos/kernel.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef BH_PLATFORM_ALIOS_THINGS
+#define BH_PLATFORM_ALIOS_THINGS
+#endif
+
+#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 30
+
+typedef aos_task_t korp_thread;
+typedef korp_thread *korp_tid;
+typedef aos_task_t *aos_tid_t;
+typedef aos_mutex_t korp_mutex;
+typedef aos_sem_t korp_sem;
+
+struct os_thread_wait_node;
+typedef struct os_thread_wait_node *os_thread_wait_list;
+typedef struct korp_cond {
+ aos_mutex_t wait_list_lock;
+ os_thread_wait_list thread_wait_list;
+} korp_cond;
+
+#define os_printf printf
+#define os_vprintf vprintf
+
+/* clang-format off */
+/* math functions which are not provided by os*/
+double sqrt(double x);
+double floor(double x);
+double ceil(double x);
+double fmin(double x, double y);
+double fmax(double x, double y);
+double rint(double x);
+double fabs(double x);
+double trunc(double x);
+float sqrtf(float 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 fabsf(float x);
+float truncf(float x);
+int signbit(double x);
+int isnan(double x);
+/* clang-format on */
+
+#endif /* end of _BH_PLATFORM_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/shared_platform.cmake
new file mode 100644
index 000000000..a3aaddd4a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/alios/shared_platform.cmake
@@ -0,0 +1,16 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_ALIOS_THINGS)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_init.c
new file mode 100644
index 000000000..1e7cf4447
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_init.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#define API_NOT_SUPPORT_ERROR(API, VERSION) \
+ __android_log_print(ANDROID_LOG_ERROR, "wasm_runtime::", \
+ "%s() is only supported when __ANDROID_API__ >= %s.", \
+ #API, #VERSION);
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *fmt, va_list ap)
+{
+ return __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap);
+}
+
+#if __ANDROID_API__ < 19
+
+int
+futimens(int __dir_fd, const struct timespec __times[2])
+{
+ API_NOT_SUPPORT_ERROR(futimens, 19);
+ return -1;
+}
+
+#endif
+
+#if __ANDROID_API__ < 21
+
+int
+posix_fallocate(int __fd, off_t __offset, off_t __length)
+{
+ API_NOT_SUPPORT_ERROR(posix_fallocate, 21);
+ return -1;
+}
+
+int
+posix_fadvise(int fd, off_t offset, off_t len, int advice)
+{
+ API_NOT_SUPPORT_ERROR(posix_fadvise, 21);
+ return -1;
+}
+
+int
+linkat(int __old_dir_fd, const char *__old_path, int __new_dir_fd,
+ const char *__new_path, int __flags)
+{
+ API_NOT_SUPPORT_ERROR(linkat, 21);
+ return -1;
+}
+
+int
+symlinkat(const char *__old_path, int __new_dir_fd, const char *__new_path)
+{
+ API_NOT_SUPPORT_ERROR(symlinkat, 21);
+ return -1;
+}
+
+ssize_t
+readlinkat(int __dir_fd, const char *__path, char *__buf, size_t __buf_size)
+{
+ API_NOT_SUPPORT_ERROR(readlinkat, 21);
+ return -1;
+}
+
+int
+accept4(int __fd, struct sockaddr *__addr, socklen_t *__addr_length,
+ int __flags)
+{
+ API_NOT_SUPPORT_ERROR(accept4, 21);
+ return -1;
+}
+
+int
+dup3(int oldfd, int newfd, int cloexec)
+{
+ API_NOT_SUPPORT_ERROR(dup3, 21);
+ return -1;
+}
+
+int
+pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id)
+{
+ API_NOT_SUPPORT_ERROR(pthread_condattr_setclock, 21);
+ return -1;
+}
+
+int
+epoll_create1(int flags)
+{
+ API_NOT_SUPPORT_ERROR(epoll_create1, 21);
+ return -1;
+}
+
+int
+epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout,
+ const sigset_t *sigmask)
+{
+ API_NOT_SUPPORT_ERROR(epoll_pwait, 21);
+ return -1;
+}
+
+int
+inotify_init1(int flags)
+{
+ API_NOT_SUPPORT_ERROR(inotify_init1, 21);
+ return -1;
+}
+
+#endif
+
+#if __ANDROID_API__ < 23
+
+long
+telldir(DIR *__dir)
+{
+ API_NOT_SUPPORT_ERROR(telldir, 23);
+ return -1;
+}
+
+void
+seekdir(DIR *__dir, long __location)
+{
+ API_NOT_SUPPORT_ERROR(seekdir, 23);
+}
+
+#endif
+
+#if __ANDROID_API__ < 24
+
+ssize_t
+preadv(int __fd, const struct iovec *__iov, int __count, off_t __offset)
+{
+ API_NOT_SUPPORT_ERROR(preadv, 24);
+ return -1;
+}
+
+ssize_t
+pwritev(int __fd, const struct iovec *__iov, int __count, off_t __offset)
+{
+ API_NOT_SUPPORT_ERROR(pwritev, 24);
+ return -1;
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_internal.h
new file mode 100644
index 000000000..521fa0c55
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/platform_internal.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sched.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+#include <android/log.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_ANDROID
+#define BH_PLATFORM_ANDROID
+#endif
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define os_thread_local_attribute __thread
+
+#define bh_socket_t int
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#define os_alloca alloca
+
+#define os_getpagesize getpagesize
+
+typedef void (*os_signal_handler)(void *sig_addr);
+
+int
+os_thread_signal_init(os_signal_handler handler);
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+void
+os_signal_unmask();
+
+void
+os_sigreturn();
+#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+typedef long int __syscall_slong_t;
+
+#if __ANDROID_API__ < 19
+
+int
+futimens(int __dir_fd, const struct timespec __times[2]);
+
+#endif
+
+#if __ANDROID_API__ < 21
+
+int
+posix_fallocate(int __fd, off_t __offset, off_t __length);
+
+int
+posix_fadvise(int fd, off_t offset, off_t len, int advice);
+
+int
+linkat(int __old_dir_fd, const char *__old_path, int __new_dir_fd,
+ const char *__new_path, int __flags);
+
+int
+symlinkat(const char *__old_path, int __new_dir_fd, const char *__new_path);
+
+ssize_t
+readlinkat(int __dir_fd, const char *__path, char *__buf, size_t __buf_size);
+
+#endif
+
+#if __ANDROID_API__ < 23
+
+long
+telldir(DIR *__dir);
+
+void
+seekdir(DIR *__dir, long __location);
+
+#endif
+
+#if __ANDROID_API__ < 24
+
+ssize_t
+preadv(int __fd, const struct iovec *__iov, int __count, off_t __offset);
+
+ssize_t
+pwritev(int __fd, const struct iovec *__iov, int __count, off_t __offset);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/shared_platform.cmake
new file mode 100644
index 000000000..13beb8e77
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/android/shared_platform.cmake
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_ANDROID)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_malloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_malloc.c
new file mode 100644
index 000000000..e47a8cce1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_malloc.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+void *
+os_malloc(unsigned size)
+{
+ return NULL;
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return NULL;
+}
+
+void
+os_free(void *ptr)
+{}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_thread.c
new file mode 100644
index 000000000..9f68bc8f9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_thread.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+/* clang-format off */
+#define bh_assert(v) do { \
+ if (!(v)) { \
+ int _count = 1; \
+ os_printf("\nASSERTION FAILED: %s, at %s, line %d\n",\
+ #v, __FILE__, __LINE__); \
+ /* divived by 0 to make it abort */ \
+ os_printf("%d\n", _count / (_count - 1)); \
+ while (1); \
+ } \
+} while (0)
+/* clang-format on */
+
+struct os_thread_data;
+typedef struct os_thread_wait_node {
+ /* Binary semaphore */
+ SemaphoreHandle_t sem;
+ os_thread_wait_list next;
+} os_thread_wait_node;
+
+typedef struct os_thread_data {
+ /* Next thread data */
+ struct os_thread_data *next;
+ /* Thread handle */
+ TaskHandle_t handle;
+ /* Thread start routine */
+ thread_start_routine_t start_routine;
+ /* Thread start routine argument */
+ void *arg;
+ /* Thread local root */
+ void *tlr;
+ /* Wait node of current thread */
+ os_thread_wait_node wait_node;
+ /* Lock for waiting list */
+ SemaphoreHandle_t wait_list_lock;
+ /* Waiting list of other threads who are joining this thread */
+ os_thread_wait_list thread_wait_list;
+} os_thread_data;
+
+static bool is_thread_sys_inited = false;
+
+/* Lock for thread data list */
+static SemaphoreHandle_t thread_data_lock;
+
+/* Thread data list */
+static os_thread_data *thread_data_list = NULL;
+/* Thread data of supervisor thread */
+static os_thread_data supervisor_thread_data;
+
+/* Thread name index */
+static int thread_name_index;
+
+static void
+thread_data_list_add(os_thread_data *thread_data)
+{
+ xSemaphoreTake(thread_data_lock, portMAX_DELAY);
+ if (!thread_data_list)
+ thread_data_list = thread_data;
+ else {
+ /* If already in list, just return */
+ os_thread_data *p = thread_data_list;
+ while (p) {
+ if (p == thread_data) {
+ xSemaphoreGive(thread_data_lock);
+ return;
+ }
+ p = p->next;
+ }
+
+ /* Set as head of list */
+ thread_data->next = thread_data_list;
+ thread_data_list = thread_data;
+ }
+ xSemaphoreGive(thread_data_lock);
+}
+
+static void
+thread_data_list_remove(os_thread_data *thread_data)
+{
+ xSemaphoreTake(thread_data_lock, portMAX_DELAY);
+ if (thread_data_list) {
+ if (thread_data_list == thread_data)
+ thread_data_list = thread_data_list->next;
+ else {
+ /* Search and remove it from list */
+ os_thread_data *p = thread_data_list;
+ while (p && p->next != thread_data)
+ p = p->next;
+ if (p && p->next == thread_data)
+ p->next = p->next->next;
+ }
+ }
+ xSemaphoreGive(thread_data_lock);
+}
+
+static os_thread_data *
+thread_data_list_lookup(TaskHandle_t handle)
+{
+ xSemaphoreTake(thread_data_lock, portMAX_DELAY);
+ if (thread_data_list) {
+ os_thread_data *p = thread_data_list;
+ while (p) {
+ if (p->handle == handle) {
+ /* Found */
+ xSemaphoreGive(thread_data_lock);
+ return p;
+ }
+ p = p->next;
+ }
+ }
+ xSemaphoreGive(thread_data_lock);
+ return NULL;
+}
+
+int
+os_thread_sys_init()
+{
+ if (is_thread_sys_inited)
+ return BHT_OK;
+
+ if (!(thread_data_lock = xSemaphoreCreateMutex()))
+ return BHT_ERROR;
+
+ /* Initialize supervisor thread data */
+ memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
+
+ if (!(supervisor_thread_data.wait_node.sem = xSemaphoreCreateBinary())) {
+ vSemaphoreDelete(thread_data_lock);
+ return BHT_ERROR;
+ }
+
+ supervisor_thread_data.handle = xTaskGetCurrentTaskHandle();
+ /* Set as head of thread data list */
+ thread_data_list = &supervisor_thread_data;
+
+ is_thread_sys_inited = true;
+ return BHT_OK;
+}
+
+void
+os_thread_sys_destroy()
+{
+ if (is_thread_sys_inited) {
+ vSemaphoreDelete(supervisor_thread_data.wait_node.sem);
+ vSemaphoreDelete(thread_data_lock);
+ is_thread_sys_inited = false;
+ }
+}
+
+static os_thread_data *
+thread_data_current()
+{
+ TaskHandle_t handle = xTaskGetCurrentTaskHandle();
+ return thread_data_list_lookup(handle);
+}
+
+static void
+os_thread_cleanup(void)
+{
+ os_thread_data *thread_data = thread_data_current();
+ os_thread_wait_list thread_wait_list;
+ SemaphoreHandle_t wait_list_lock;
+ SemaphoreHandle_t wait_node_sem;
+
+ bh_assert(thread_data != NULL);
+ wait_list_lock = thread_data->wait_list_lock;
+ thread_wait_list = thread_data->thread_wait_list;
+ wait_node_sem = thread_data->wait_node.sem;
+
+ xSemaphoreTake(wait_list_lock, portMAX_DELAY);
+ if (thread_wait_list) {
+ /* Signal each joining thread */
+ os_thread_wait_list head = thread_wait_list;
+ while (head) {
+ os_thread_wait_list next = head->next;
+ xSemaphoreGive(head->sem);
+ head = next;
+ }
+ }
+ xSemaphoreGive(wait_list_lock);
+
+ /* Free sem and lock */
+ vSemaphoreDelete(wait_node_sem);
+ vSemaphoreDelete(wait_list_lock);
+
+ thread_data_list_remove(thread_data);
+ BH_FREE(thread_data);
+}
+
+static void
+os_thread_wrapper(void *arg)
+{
+ os_thread_data *thread_data = arg;
+
+ thread_data->handle = xTaskGetCurrentTaskHandle();
+ thread_data_list_add(thread_data);
+
+ thread_data->start_routine(thread_data->arg);
+ os_thread_cleanup();
+ vTaskDelete(NULL);
+}
+
+int
+os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(p_tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+int
+os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ os_thread_data *thread_data;
+ char thread_name[32];
+
+ if (!p_tid || !stack_size)
+ return BHT_ERROR;
+
+ /* Create and initialize thread data */
+ if (!(thread_data = BH_MALLOC(sizeof(os_thread_data))))
+ return BHT_ERROR;
+
+ memset(thread_data, 0, sizeof(os_thread_data));
+
+ thread_data->start_routine = start;
+ thread_data->arg = arg;
+
+ if (!(thread_data->wait_node.sem = xSemaphoreCreateBinary()))
+ goto fail1;
+
+ if (!(thread_data->wait_list_lock = xSemaphoreCreateMutex()))
+ goto fail2;
+
+ snprintf(thread_name, sizeof(thread_name), "%s%d", "wasm-thread-",
+ ++thread_name_index);
+
+ /* Create the thread */
+ if (pdPASS
+ != xTaskCreate(os_thread_wrapper, thread_name, stack_size / 4,
+ thread_data, prio, &thread_data->handle))
+ goto fail3;
+
+ thread_data_list_add(thread_data);
+ *p_tid = thread_data->handle;
+ return BHT_OK;
+
+fail3:
+ vSemaphoreDelete(thread_data->wait_list_lock);
+fail2:
+ vSemaphoreDelete(thread_data->wait_node.sem);
+fail1:
+ BH_FREE(thread_data);
+ return BHT_ERROR;
+}
+
+korp_tid
+os_self_thread()
+{
+ return xTaskGetCurrentTaskHandle();
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+ os_thread_data *thread_data, *curr_thread_data;
+ TaskHandle_t handle = thread;
+
+ (void)value_ptr;
+
+ /* Get thread data of current thread */
+ curr_thread_data = thread_data_current();
+ curr_thread_data->wait_node.next = NULL;
+
+ /* Get thread data */
+ thread_data = thread_data_list_lookup(handle);
+
+ xSemaphoreTake(thread_data->wait_list_lock, portMAX_DELAY);
+ if (!thread_data->thread_wait_list)
+ thread_data->thread_wait_list = &curr_thread_data->wait_node;
+ else {
+ /* Add to end of waiting list */
+ os_thread_wait_node *p = thread_data->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = &curr_thread_data->wait_node;
+ }
+ xSemaphoreGive(thread_data->wait_list_lock);
+
+ /* Wait the sem */
+ xSemaphoreTake(curr_thread_data->wait_node.sem, portMAX_DELAY);
+ return BHT_OK;
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ SemaphoreHandle_t semaphore;
+
+ if (!(semaphore = xSemaphoreCreateMutex()))
+ return BHT_ERROR;
+ mutex->sem = semaphore;
+ mutex->is_recursive = false;
+ return BHT_OK;
+}
+
+int
+os_recursive_mutex_init(korp_mutex *mutex)
+{
+ SemaphoreHandle_t semaphore;
+
+ if (!(semaphore = xSemaphoreCreateRecursiveMutex()))
+ return BHT_ERROR;
+ mutex->sem = semaphore;
+ mutex->is_recursive = true;
+ return BHT_OK;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ vSemaphoreDelete(mutex->sem);
+ return BHT_OK;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ int ret = -1;
+
+ if (!mutex->is_recursive)
+ ret = xSemaphoreTake(mutex->sem, portMAX_DELAY);
+ else
+ ret = xSemaphoreTakeRecursive(mutex->sem, portMAX_DELAY);
+ return ret == pdPASS ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ int ret = -1;
+
+ if (!mutex->is_recursive)
+ ret = xSemaphoreGive(mutex->sem);
+ else
+ ret = xSemaphoreGiveRecursive(mutex->sem);
+ return ret == pdPASS ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ if (!(cond->wait_list_lock = xSemaphoreCreateMutex()))
+ return BHT_ERROR;
+
+ cond->thread_wait_list = NULL;
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ vSemaphoreDelete(cond->wait_list_lock);
+ return BHT_OK;
+}
+
+static int
+os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed, int mills)
+{
+ os_thread_wait_node *node = &thread_data_current()->wait_node;
+
+ node->next = NULL;
+
+ xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY);
+ if (!cond->thread_wait_list)
+ cond->thread_wait_list = node;
+ else {
+ /* Add to end of wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = node;
+ }
+ xSemaphoreGive(cond->wait_list_lock);
+
+ /* Unlock mutex, wait sem and lock mutex again */
+ os_mutex_unlock(mutex);
+ xSemaphoreTake(node->sem, timed ? mills / portTICK_RATE_MS : portMAX_DELAY);
+ os_mutex_lock(mutex);
+
+ /* Remove wait node from wait list */
+ xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY);
+ if (cond->thread_wait_list == node)
+ cond->thread_wait_list = node->next;
+ else {
+ /* Remove from the wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next != node)
+ p = p->next;
+ p->next = node->next;
+ }
+ xSemaphoreGive(cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return os_cond_wait_internal(cond, mutex, false, 0);
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ if (useconds == BHT_WAIT_FOREVER) {
+ return os_cond_wait_internal(cond, mutex, false, 0);
+ }
+ else {
+ uint64 mills_64 = useconds / 1000;
+ int32 mills;
+
+ if (mills_64 < (uint64)INT32_MAX) {
+ mills = (int32)mills_64;
+ }
+ else {
+ mills = INT32_MAX;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+ return os_cond_wait_internal(cond, mutex, true, mills);
+ }
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ /* Signal the head wait node of wait list */
+ xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY);
+ if (cond->thread_wait_list)
+ xSemaphoreGive(cond->thread_wait_list->sem);
+ xSemaphoreGive(cond->wait_list_lock);
+
+ return BHT_OK;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_time.c
new file mode 100644
index 000000000..4497d8c6c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/freertos_time.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+uint64
+os_time_get_boot_microsecond()
+{
+ TickType_t ticks = xTaskGetTickCount();
+ return (uint64)1000 * 1000 / configTICK_RATE_HZ * ticks;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/platform_api_freertos.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/platform_api_freertos.cmake
new file mode 100644
index 000000000..ebfc19d78
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/freertos/platform_api_freertos.cmake
@@ -0,0 +1,8 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_COMMON_FREERTOS_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+file (GLOB_RECURSE source_all ${PLATFORM_COMMON_FREERTOS_DIR}/*.c)
+
+set (PLATFORM_COMMON_FREERTOS_SOURCE ${source_all} )
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/COPYRIGHT b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/COPYRIGHT
new file mode 100644
index 000000000..a0e1c83a9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/COPYRIGHT
@@ -0,0 +1,126 @@
+# $FreeBSD$
+# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94
+
+The compilation of software known as FreeBSD is distributed under the
+following terms:
+
+Copyright (c) 1992-2019 The FreeBSD Project.
+
+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.
+
+The 4.4BSD and 4.4BSD-Lite software is distributed under the following
+terms:
+
+All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite
+Releases is copyrighted by The Regents of the University of California.
+
+Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+This product includes software developed by the University of
+California, Berkeley and its contributors.
+4. Neither the name of the University 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 REGENTS 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 REGENTS 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 Institute of Electrical and Electronics Engineers and the American
+National Standards Committee X3, on Information Processing Systems have
+given us permission to reprint portions of their documentation.
+
+In the following statement, the phrase ``this text'' refers to portions
+of the system documentation.
+
+Portions of this text are reprinted and reproduced in electronic form in
+the second BSD Networking Software Release, from IEEE Std 1003.1-1988, IEEE
+Standard Portable Operating System Interface for Computer Environments
+(POSIX), copyright C 1988 by the Institute of Electrical and Electronics
+Engineers, Inc. In the event of any discrepancy between these versions
+and the original IEEE Standard, the original IEEE Standard is the referee
+document.
+
+In the following statement, the phrase ``This material'' refers to portions
+of the system documentation.
+
+This material is reproduced with permission from American National
+Standards Committee X3, on Information Processing Systems. Computer and
+Business Equipment Manufacturers Association (CBEMA), 311 First St., NW,
+Suite 500, Washington, DC 20001-2178. The developmental work of
+Programming Language C was completed by the X3J11 Technical Committee.
+
+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 Regents of the University
+of California.
+
+
+NOTE: The copyright of UC Berkeley's Berkeley Software Distribution ("BSD")
+source has been updated. The copyright addendum may be found at
+ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change and is
+included below.
+
+July 22, 1999
+
+To All Licensees, Distributors of Any Version of BSD:
+
+As you know, certain of the Berkeley Software Distribution ("BSD") source
+code files require that further distributions of products containing all or
+portions of the software, acknowledge within their advertising materials
+that such products contain software developed by UC Berkeley and its
+contributors.
+
+Specifically, the provision reads:
+
+" * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors."
+
+Effective immediately, licensees and distributors are no longer required to
+include the acknowledgement within advertising materials. Accordingly, the
+foregoing paragraph of those BSD Unix files containing it is hereby deleted
+in its entirety.
+
+William Hoskins
+Director, Office of Technology Licensing
+University of California, Berkeley
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/math.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/math.c
new file mode 100644
index 000000000..2ba9f4d28
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/math.c
@@ -0,0 +1,1681 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * 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 "platform_common.h"
+
+#define __FDLIBM_STDC__
+
+#ifndef FLT_EVAL_METHOD
+#define FLT_EVAL_METHOD 0
+#endif
+
+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) *(pdouble2pint(&x))
+#define __LOB(x) *(1 + pdouble2pint(&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)
+
+/* Set the less significant 32 bits of a double from an int. */
+#define SET_LOW_WORD_L(d, v) \
+ do { \
+ ieee_double_shape_type_little sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.lsw = (v); \
+ (d) = sh_u.value; \
+ } while (0)
+
+/* Set the more significant 32 bits of a double from an int. */
+#define SET_LOW_WORD_B(d, v) \
+ do { \
+ ieee_double_shape_type_big sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.lsw = (v); \
+ (d) = sh_u.value; \
+ } while (0)
+
+/* Get the less significant 32 bit int from a double. */
+#define GET_LOW_WORD_L(i, d) \
+ do { \
+ ieee_double_shape_type_little gl_u; \
+ gl_u.value = (d); \
+ (i) = gl_u.parts.lsw; \
+ } while (0)
+
+/* Get the less significant 32 bit int from a double. */
+#define GET_LOW_WORD_B(i, d) \
+ do { \
+ ieee_double_shape_type_big gl_u; \
+ gl_u.value = (d); \
+ (i) = gl_u.parts.lsw; \
+ } 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 GET_LOW_WORD(d, v) \
+ do { \
+ if (is_little_endian()) \
+ GET_LOW_WORD_L(d, v); \
+ else \
+ GET_LOW_WORD_B(d, v); \
+ } while (0)
+
+#define SET_LOW_WORD(d, v) \
+ do { \
+ if (is_little_endian()) \
+ SET_LOW_WORD_L(d, v); \
+ else \
+ SET_LOW_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 */
+ };
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ atanhi[] = {
+ 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+ };
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ atanlo[] = {
+ 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+ };
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ aT[] = {
+ 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
+ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
+ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
+ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
+ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
+ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
+ };
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+ zero = 0.0,
+ pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+ pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+ pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
+ pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+#ifdef __STDC__
+static const double
+#else
+static double
+#endif
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+two = 2.0,
+two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+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_atan(double x);
+static double
+freebsd_atan2(double y, double x);
+
+static double
+freebsd_atan(double x)
+{
+ double w, s1, s2, z;
+ int32_t ix, hx, id;
+
+ GET_HIGH_WORD(hx, x);
+ ix = hx & 0x7fffffff;
+ if (ix >= 0x44100000) { /* if |x| >= 2^66 */
+ u_int32_t low;
+ GET_LOW_WORD(low, x);
+ if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (low != 0)))
+ return x + x; /* NaN */
+ if (hx > 0)
+ return atanhi[3] + *(volatile double *)&atanlo[3];
+ else
+ return -atanhi[3] - *(volatile double *)&atanlo[3];
+ }
+ if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
+ if (ix < 0x3e400000) { /* |x| < 2^-27 */
+ if (huge + x > one)
+ return x; /* raise inexact */
+ }
+ id = -1;
+ }
+ else {
+ x = freebsd_fabs(x);
+ if (ix < 0x3ff30000) { /* |x| < 1.1875 */
+ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+ id = 0;
+ x = (2.0 * x - one) / (2.0 + x);
+ }
+ else { /* 11/16<=|x|< 19/16 */
+ id = 1;
+ x = (x - one) / (x + one);
+ }
+ }
+ else {
+ if (ix < 0x40038000) { /* |x| < 2.4375 */
+ id = 2;
+ x = (x - 1.5) / (one + 1.5 * x);
+ }
+ else { /* 2.4375 <= |x| < 2^66 */
+ id = 3;
+ x = -1.0 / x;
+ }
+ }
+ }
+ /* end of argument reduction */
+ z = x * x;
+ w = z * z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z
+ * (aT[0]
+ + w
+ * (aT[2]
+ + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
+ s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
+ if (id < 0)
+ return x - x * (s1 + s2);
+ else {
+ z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
+ return (hx < 0) ? -z : z;
+ }
+}
+
+static double
+freebsd_atan2(double y, double x)
+{
+ double z;
+ int32_t k, m, hx, hy, ix, iy;
+ u_int32_t lx, ly;
+
+ EXTRACT_WORDS(hx, lx, x);
+ ix = hx & 0x7fffffff;
+ EXTRACT_WORDS(hy, ly, y);
+ iy = hy & 0x7fffffff;
+ if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000)
+ || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) /* x or y is NaN */
+ return x + y;
+ if (hx == 0x3ff00000 && lx == 0)
+ return freebsd_atan(y); /* x=1.0 */
+ m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if ((iy | ly) == 0) {
+ switch (m) {
+ case 0:
+ case 1:
+ return y; /* atan(+-0,+anything)=+-0 */
+ case 2:
+ return pi + tiny; /* atan(+0,-anything) = pi */
+ case 3:
+ default:
+ return -pi - tiny; /* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if ((ix | lx) == 0)
+ return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
+
+ /* when x is INF */
+ if (ix == 0x7ff00000) {
+ if (iy == 0x7ff00000) {
+ switch (m) {
+ case 0:
+ return pi_o_4 + tiny; /* atan(+INF,+INF) */
+ case 1:
+ return -pi_o_4 - tiny; /* atan(-INF,+INF) */
+ case 2:
+ return 3.0 * pi_o_4 + tiny; /*atan(+INF,-INF)*/
+ case 3:
+ default:
+ return -3.0 * pi_o_4 - tiny; /*atan(-INF,-INF)*/
+ }
+ }
+ else {
+ switch (m) {
+ case 0:
+ return zero; /* atan(+...,+INF) */
+ case 1:
+ return -zero; /* atan(-...,+INF) */
+ case 2:
+ return pi + tiny; /* atan(+...,-INF) */
+ case 3:
+ default:
+ return -pi - tiny; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if (iy == 0x7ff00000)
+ return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
+
+ /* compute y/x */
+ k = (iy - ix) >> 20;
+ if (k > 60) { /* |y/x| > 2**60 */
+ z = pi_o_2 + 0.5 * pi_lo;
+ m &= 1;
+ }
+ else if (hx < 0 && k < -60)
+ z = 0.0; /* 0 > |y|/x > -2**-60 */
+ else
+ z = freebsd_atan(fabs(y / x)); /* safe to do y/x */
+ switch (m) {
+ case 0:
+ return z; /* atan(+,+) */
+ case 1:
+ return -z; /* atan(-,+) */
+ case 2:
+ return pi - (z - pi_lo); /* atan(+,-) */
+ default: /* case 3 */
+ return (z - pi_lo) - pi; /* atan(-,-) */
+ }
+}
+
+#ifndef BH_HAS_SQRTF
+static float
+freebsd_sqrtf(float x)
+{
+ float z;
+ int32_t sign = (int)0x80000000;
+ int32_t ix, s, q, m, t, i;
+ u_int32_t r;
+
+ GET_FLOAT_WORD(ix, x);
+
+ /* take care of Inf and NaN */
+ if ((ix & 0x7f800000) == 0x7f800000) {
+ return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+ sqrt(-inf)=sNaN */
+ }
+ /* take care of zero */
+ if (ix <= 0) {
+ if ((ix & (~sign)) == 0)
+ return x; /* sqrt(+-0) = +-0 */
+ else if (ix < 0)
+ return (x - x) / (x - x); /* sqrt(-ve) = sNaN */
+ }
+ /* normalize x */
+ m = (ix >> 23);
+ if (m == 0) { /* subnormal x */
+ for (i = 0; (ix & 0x00800000) == 0; i++)
+ ix <<= 1;
+ m -= i - 1;
+ }
+ m -= 127; /* unbias exponent */
+ ix = (ix & 0x007fffff) | 0x00800000;
+ if (m & 1) /* odd m, double x to make it even */
+ ix += ix;
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix += ix;
+ q = s = 0; /* q = sqrt(x) */
+ r = 0x01000000; /* r = moving bit from right to left */
+
+ while (r != 0) {
+ t = s + r;
+ if (t <= ix) {
+ s = t + r;
+ ix -= t;
+ q += r;
+ }
+ ix += ix;
+ r >>= 1;
+ }
+
+ /* use floating add to find out rounding direction */
+ if (ix != 0) {
+ z = one - tiny; /* trigger inexact flag */
+ if (z >= one) {
+ z = one + tiny;
+ if (z > one)
+ q += 2;
+ else
+ q += (q & 1);
+ }
+ }
+ ix = (q >> 1) + 0x3f000000;
+ ix += (m << 23);
+ SET_FLOAT_WORD(z, ix);
+ return z;
+}
+#endif /* end of BH_HAS_SQRTF */
+
+#ifndef BH_HAS_SQRT
+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 < ix0) || ((t == ix0) && (t1 <= ix1))) {
+ s1 = t1 + r;
+ if (((t1 & sign) == sign) && (s1 & sign) == 0)
+ s0 += 1;
+ ix0 -= t;
+ if (ix1 < t1)
+ ix0 -= 1;
+ ix1 -= t1;
+ q1 += r;
+ }
+ ix0 += ix0 + ((ix1 & sign) >> 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;
+}
+#endif /* end of BH_HAS_SQRT */
+
+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 < i1)
+ i0 += 1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+
+ INSERT_WORDS(x, i0, i1);
+
+ return x;
+}
+
+static double
+freebsd_ceil(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 = 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 < i1)
+ i0 += 1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x, i0, i1);
+ return x;
+}
+
+static double
+freebsd_rint(double x)
+{
+ int32_t i0, j0, sx;
+ u_int32_t i, i1;
+ double w, t;
+ EXTRACT_WORDS(i0, i1, x);
+ sx = (i0 >> 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 float
+freebsd_fabsf(float x)
+{
+ u_int32_t ix;
+ GET_FLOAT_WORD(ix, x);
+ SET_FLOAT_WORD(x, ix & 0x7fffffff);
+ return x;
+}
+
+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] = { 0 };
+
+ 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] = { 0 };
+
+ 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] = { 0 };
+
+ 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] = { 0 };
+
+ 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);
+}
+
+static double
+freebsd_copysign(double x, double y)
+{
+ u_int32_t hx, hy;
+ GET_HIGH_WORD(hx, x);
+ GET_HIGH_WORD(hy, y);
+ SET_HIGH_WORD(x, (hx & 0x7fffffff) | (hy & 0x80000000));
+ return x;
+}
+
+static double
+freebsd_scalbn(double x, int n)
+{
+ int32_t k, hx, lx;
+ EXTRACT_WORDS(hx, lx, x);
+ k = (hx & 0x7ff00000) >> 20; /* extract exponent */
+ if (k == 0) { /* 0 or subnormal x */
+ if ((lx | (hx & 0x7fffffff)) == 0)
+ return x; /* +-0 */
+ x *= two54;
+ GET_HIGH_WORD(hx, x);
+ k = ((hx & 0x7ff00000) >> 20) - 54;
+ if (n < -50000)
+ return tiny * x; /*underflow*/
+ }
+ if (k == 0x7ff)
+ return x + x; /* NaN or Inf */
+ k = k + n;
+ if (k > 0x7fe)
+ return huge * freebsd_copysign(huge, x); /* overflow */
+ if (k > 0) /* normal result */
+ {
+ SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
+ return x;
+ }
+ if (k <= -54) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge * freebsd_copysign(huge, x); /*overflow*/
+ else
+ return tiny * freebsd_copysign(tiny, x); /*underflow*/
+ }
+ k += 54; /* subnormal result */
+ SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
+ return x * twom54;
+}
+
+static double
+freebsd_pow(double x, double y)
+{
+ double z, ax, z_h, z_l, p_h, p_l;
+ double y1, t1, t2, r, s, t, u, v, w;
+ int32_t i, j, k, yisint, n;
+ int32_t hx, hy, ix, iy;
+ u_int32_t lx, ly;
+
+ EXTRACT_WORDS(hx, lx, x);
+ EXTRACT_WORDS(hy, ly, y);
+ ix = hx & 0x7fffffff;
+ iy = hy & 0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if ((iy | ly) == 0)
+ return one;
+
+ /* x==1: 1**y = 1, even if y is NaN */
+ if (hx == 0x3ff00000 && lx == 0)
+ return one;
+
+ /* y!=zero: result is NaN if either arg is NaN */
+ if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || iy > 0x7ff00000
+ || ((iy == 0x7ff00000) && (ly != 0)))
+ return (x + 0.0) + (y + 0.0);
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if (hx < 0) {
+ if (iy >= 0x43400000)
+ yisint = 2; /* even integer y */
+ else if (iy >= 0x3ff00000) {
+ k = (iy >> 20) - 0x3ff; /* exponent */
+ if (k > 20) {
+ j = ly >> (52 - k);
+ if ((j << (52 - k)) == ly)
+ yisint = 2 - (j & 1);
+ }
+ else if (ly == 0) {
+ j = iy >> (20 - k);
+ if ((j << (20 - k)) == iy)
+ yisint = 2 - (j & 1);
+ }
+ }
+ }
+
+ /* special value of y */
+ if (ly == 0) {
+ if (iy == 0x7ff00000) { /* y is +-inf */
+ if (((ix - 0x3ff00000) | lx) == 0)
+ return one; /* (-1)**+-inf is NaN */
+ else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */
+ return (hy >= 0) ? y : zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy < 0) ? -y : zero;
+ }
+ if (iy == 0x3ff00000) { /* y is +-1 */
+ if (hy < 0)
+ return one / x;
+ else
+ return x;
+ }
+ if (hy == 0x40000000)
+ return x * x; /* y is 2 */
+ if (hy == 0x40080000)
+ return x * x * x; /* y is 3 */
+ if (hy == 0x40100000) { /* y is 4 */
+ u = x * x;
+ return u * u;
+ }
+ if (hy == 0x3fe00000) { /* y is 0.5 */
+ if (hx >= 0) /* x >= +0 */
+ return sqrt(x);
+ }
+ }
+
+ ax = fabs(x);
+ /* special value of x */
+ if (lx == 0) {
+ if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) {
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if (hy < 0)
+ z = one / z; /* z = (1/|x|) */
+ if (hx < 0) {
+ if (((ix - 0x3ff00000) | yisint) == 0) {
+ z = (z - z) / (z - z); /* (-1)**non-int is NaN */
+ }
+ else if (yisint == 1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+ }
+
+ /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be
+ n = (hx>>31)+1;
+ but ANSI C says a right shift of a signed negative quantity is
+ implementation defined. */
+ n = ((u_int32_t)hx >> 31) - 1;
+
+ /* (x<0)**(non-int) is NaN */
+ if ((n | yisint) == 0)
+ return (x - x) / (x - x);
+
+ s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if ((n | (yisint - 1)) == 0)
+ s = -one; /* (-ve)**(odd int) */
+
+ /* |y| is huge */
+ if (iy > 0x41e00000) { /* if |y| > 2**31 */
+ if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */
+ if (ix <= 0x3fefffff)
+ return (hy < 0) ? huge * huge : tiny * tiny;
+ if (ix >= 0x3ff00000)
+ return (hy > 0) ? huge * huge : tiny * tiny;
+ }
+ /* over/underflow if x is not close to one */
+ if (ix < 0x3fefffff)
+ return (hy < 0) ? s * huge * huge : s * tiny * tiny;
+ if (ix > 0x3ff00000)
+ return (hy > 0) ? s * huge * huge : s * tiny * tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = ax - one; /* t has 20 trailing zeros */
+ w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25));
+ u = ivln2_h * t; /* ivln2_h has 21 sig. bits */
+ v = t * ivln2_l - w * ivln2;
+ t1 = u + v;
+ SET_LOW_WORD(t1, 0);
+ t2 = v - (t1 - u);
+ }
+ else {
+ double ss, s2, s_h, s_l, t_h, t_l;
+ n = 0;
+ /* take care subnormal number */
+ if (ix < 0x00100000) {
+ ax *= two53;
+ n -= 53;
+ GET_HIGH_WORD(ix, ax);
+ }
+ n += ((ix) >> 20) - 0x3ff;
+ j = ix & 0x000fffff;
+ /* determine interval */
+ ix = j | 0x3ff00000; /* normalize ix */
+ if (j <= 0x3988E)
+ k = 0; /* |x|<sqrt(3/2) */
+ else if (j < 0xBB67A)
+ k = 1; /* |x|<sqrt(3) */
+ else {
+ k = 0;
+ n += 1;
+ ix -= 0x00100000;
+ }
+ SET_HIGH_WORD(ax, ix);
+
+ /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one / (ax + bp[k]);
+ ss = u * v;
+ s_h = ss;
+ SET_LOW_WORD(s_h, 0);
+ /* t_h=ax+bp[k] High */
+ t_h = zero;
+ SET_HIGH_WORD(t_h, ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18));
+ t_l = ax - (t_h - bp[k]);
+ s_l = v * ((u - s_h * t_h) - s_h * t_l);
+ /* compute log(ax) */
+ s2 = ss * ss;
+ r = s2 * s2
+ * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6)))));
+ r += s_l * (s_h + ss);
+ s2 = s_h * s_h;
+ t_h = 3.0 + s2 + r;
+ SET_LOW_WORD(t_h, 0);
+ t_l = r - ((t_h - 3.0) - s2);
+ /* u+v = ss*(1+...) */
+ u = s_h * t_h;
+ v = s_l * t_h + t_l * ss;
+ /* 2/(3log2)*(ss+...) */
+ p_h = u + v;
+ SET_LOW_WORD(p_h, 0);
+ p_l = v - (p_h - u);
+ z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l * p_h + p_l * cp + dp_l[k];
+ /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (double)n;
+ t1 = (((z_h + z_l) + dp_h[k]) + t);
+ SET_LOW_WORD(t1, 0);
+ t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
+ }
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ y1 = y;
+ SET_LOW_WORD(y1, 0);
+ p_l = (y - y1) * t1 + y * t2;
+ p_h = y1 * t1;
+ z = p_l + p_h;
+ EXTRACT_WORDS(j, i, z);
+ if (j >= 0x40900000) { /* z >= 1024 */
+ if (((j - 0x40900000) | i) != 0) /* if z > 1024 */
+ return s * huge * huge; /* overflow */
+ else {
+ if (p_l + ovt > z - p_h)
+ return s * huge * huge; /* overflow */
+ }
+ }
+ else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */
+ if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */
+ return s * tiny * tiny; /* underflow */
+ else {
+ if (p_l <= z - p_h)
+ return s * tiny * tiny; /* underflow */
+ }
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j & 0x7fffffff;
+ k = (i >> 20) - 0x3ff;
+ n = 0;
+ if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j + (0x00100000 >> (k + 1));
+ k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */
+ t = zero;
+ SET_HIGH_WORD(t, n & ~(0x000fffff >> k));
+ n = ((n & 0x000fffff) | 0x00100000) >> (20 - k);
+ if (j < 0)
+ n = -n;
+ p_h -= t;
+ }
+ t = p_l + p_h;
+ SET_LOW_WORD(t, 0);
+ u = t * lg2_h;
+ v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
+ z = u + v;
+ w = v - (z - u);
+ t = z * z;
+ t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+ r = (z * t1) / (t1 - two) - (w + z * w);
+ z = one - (r - z);
+ GET_HIGH_WORD(j, z);
+ j += (n << 20);
+ if ((j >> 20) <= 0)
+ z = freebsd_scalbn(z, n); /* subnormal output */
+ else
+ SET_HIGH_WORD(z, j);
+ return s * z;
+}
+
+double
+atan(double x)
+{
+ return freebsd_atan(x);
+}
+
+double
+atan2(double y, double x)
+{
+ return freebsd_atan2(y, x);
+}
+
+#ifndef BH_HAS_SQRT
+double
+sqrt(double x)
+{
+ return freebsd_sqrt(x);
+}
+#endif
+
+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
+fabsf(float x)
+{
+ return freebsd_fabsf(x);
+}
+
+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);
+}
+
+#ifndef BH_HAS_SQRTF
+float
+sqrtf(float x)
+{
+ return freebsd_sqrtf(x);
+}
+#endif
+
+double
+pow(double x, double y)
+{
+ return freebsd_pow(x, y);
+}
+
+double
+scalbn(double x, int n)
+{
+ return freebsd_scalbn(x, n);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/platform_api_math.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/platform_api_math.cmake
new file mode 100644
index 000000000..09c74bfc5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/math/platform_api_math.cmake
@@ -0,0 +1,8 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_COMMON_MATH_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+file (GLOB_RECURSE source_all ${PLATFORM_COMMON_MATH_DIR}/*.c)
+
+set (PLATFORM_COMMON_MATH_SOURCE ${source_all} )
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/platform_api_posix.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/platform_api_posix.cmake
new file mode 100644
index 000000000..4abefff1e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/platform_api_posix.cmake
@@ -0,0 +1,8 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_COMMON_POSIX_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+file (GLOB_RECURSE source_all ${PLATFORM_COMMON_POSIX_DIR}/*.c)
+
+set (PLATFORM_COMMON_POSIX_SOURCE ${source_all} )
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_malloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_malloc.c
new file mode 100644
index 000000000..912998ee0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_malloc.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+void *
+os_malloc(unsigned size)
+{
+ return malloc(size);
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return realloc(ptr, size);
+}
+
+void
+os_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ int ret = -1;
+ FILE *f;
+ char line[128] = { 0 };
+ unsigned int out_idx = 0;
+
+ if (!out || !size)
+ goto quit;
+
+ f = fopen("/proc/self/status", "r");
+ if (!f) {
+ perror("fopen failed: ");
+ goto quit;
+ }
+
+ memset(out, 0, size);
+
+ while (fgets(line, sizeof(line), f)) {
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+ if (strncmp(line, "Vm", 2) == 0 || strncmp(line, "Rss", 3) == 0) {
+#else
+ if (strncmp(line, "VmRSS", 5) == 0
+ || strncmp(line, "RssAnon", 7) == 0) {
+#endif
+ size_t line_len = strlen(line);
+ if (line_len >= size - 1 - out_idx)
+ goto close_file;
+
+ /* copying without null-terminated byte */
+ memcpy(out + out_idx, line, line_len);
+ out_idx += line_len;
+ }
+ }
+
+ if (ferror(f)) {
+ perror("fgets failed: ");
+ goto close_file;
+ }
+
+ ret = 0;
+close_file:
+ fclose(f);
+quit:
+ return ret;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_memmap.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_memmap.c
new file mode 100644
index 000000000..2dfbee453
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_memmap.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+#ifndef BH_ENABLE_TRACE_MMAP
+#define BH_ENABLE_TRACE_MMAP 0
+#endif
+
+#if BH_ENABLE_TRACE_MMAP != 0
+static size_t total_size_mmapped = 0;
+static size_t total_size_munmapped = 0;
+#endif
+
+#define HUGE_PAGE_SIZE (2 * 1024 * 1024)
+
+#if !defined(__APPLE__) && !defined(__NuttX__) && defined(MADV_HUGEPAGE)
+static inline uintptr_t
+round_up(uintptr_t v, uintptr_t b)
+{
+ uintptr_t m = b - 1;
+ return (v + m) & ~m;
+}
+
+static inline uintptr_t
+round_down(uintptr_t v, uintptr_t b)
+{
+ uintptr_t m = b - 1;
+ return v & ~m;
+}
+#endif
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ int map_prot = PROT_NONE;
+ int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
+ uint64 request_size, page_size;
+ uint8 *addr = MAP_FAILED;
+ uint32 i;
+
+ page_size = (uint64)getpagesize();
+ request_size = (size + page_size - 1) & ~(page_size - 1);
+
+#if !defined(__APPLE__) && !defined(__NuttX__) && defined(MADV_HUGEPAGE)
+ /* huge page isn't supported on MacOS and NuttX */
+ if (request_size >= HUGE_PAGE_SIZE)
+ /* apply one extra huge page */
+ request_size += HUGE_PAGE_SIZE;
+#endif
+
+ if ((size_t)request_size < size)
+ /* integer overflow */
+ return NULL;
+
+ if (request_size > 16 * (uint64)UINT32_MAX)
+ /* at most 16 G is allowed */
+ 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)
+#ifndef __APPLE__
+ if (flags & MMAP_MAP_32BIT)
+ map_flags |= MAP_32BIT;
+#endif
+#endif
+
+ if (flags & MMAP_MAP_FIXED)
+ map_flags |= MAP_FIXED;
+
+#if defined(BUILD_TARGET_RISCV64_LP64D) || defined(BUILD_TARGET_RISCV64_LP64)
+ /* As AOT relocation in RISCV64 may require that the code/data mapped
+ * is in range 0 to 2GB, we try to map the memory with hint address
+ * (mmap's first argument) to meet the requirement.
+ */
+ if (!hint && !(flags & MMAP_MAP_FIXED) && (flags & MMAP_MAP_32BIT)) {
+ uint8 *stack_addr = (uint8 *)&map_prot;
+ uint8 *text_addr = (uint8 *)os_mmap;
+ /* hint address begins with 1MB */
+ static uint8 *hint_addr = (uint8 *)(uintptr_t)BH_MB;
+
+ if ((hint_addr - text_addr >= 0 && hint_addr - text_addr < 100 * BH_MB)
+ || (text_addr - hint_addr >= 0
+ && text_addr - hint_addr < 100 * BH_MB)) {
+ /* hint address is possibly in text section, skip it */
+ hint_addr += 100 * BH_MB;
+ }
+
+ if ((hint_addr - stack_addr >= 0 && hint_addr - stack_addr < 8 * BH_MB)
+ || (stack_addr - hint_addr >= 0
+ && stack_addr - hint_addr < 8 * BH_MB)) {
+ /* hint address is possibly in native stack area, skip it */
+ hint_addr += 8 * BH_MB;
+ }
+
+ /* try 10 times, step with 1MB each time */
+ for (i = 0; i < 10 && hint_addr < (uint8 *)(uintptr_t)(2ULL * BH_GB);
+ i++) {
+ addr = mmap(hint_addr, request_size, map_prot, map_flags, -1, 0);
+ if (addr != MAP_FAILED) {
+ if (addr > (uint8 *)(uintptr_t)(2ULL * BH_GB)) {
+ /* unmap and try again if the mapped address doesn't
+ * meet the requirement */
+ os_munmap(addr, request_size);
+ }
+ else {
+ /* success, reset next hint address */
+ hint_addr += request_size;
+ break;
+ }
+ }
+ hint_addr += BH_MB;
+ }
+ }
+#endif /* end of BUILD_TARGET_RISCV64_LP64D || BUILD_TARGET_RISCV64_LP64 */
+
+ /* memory has't been mapped or was mapped failed previously */
+ if (addr == MAP_FAILED) {
+ /* try 5 times */
+ for (i = 0; i < 5; i++) {
+ addr = mmap(hint, request_size, map_prot, map_flags, -1, 0);
+ if (addr != MAP_FAILED)
+ break;
+ }
+ }
+
+ if (addr == MAP_FAILED) {
+#if BH_ENABLE_TRACE_MMAP != 0
+ os_printf("mmap failed\n");
+#endif
+ return NULL;
+ }
+
+#if BH_ENABLE_TRACE_MMAP != 0
+ total_size_mmapped += request_size;
+ os_printf("mmap return: %p with size: %zu, total_size_mmapped: %zu, "
+ "total_size_munmapped: %zu\n",
+ addr, request_size, total_size_mmapped, total_size_munmapped);
+#endif
+
+#if !defined(__APPLE__) && !defined(__NuttX__) && defined(MADV_HUGEPAGE)
+ /* huge page isn't supported on MacOS and NuttX */
+ if (request_size > HUGE_PAGE_SIZE) {
+ uintptr_t huge_start, huge_end;
+ size_t prefix_size = 0, suffix_size = HUGE_PAGE_SIZE;
+
+ huge_start = round_up((uintptr_t)addr, HUGE_PAGE_SIZE);
+
+ if (huge_start > (uintptr_t)addr) {
+ prefix_size += huge_start - (uintptr_t)addr;
+ suffix_size -= huge_start - (uintptr_t)addr;
+ }
+
+ /* unmap one extra huge page */
+
+ if (prefix_size > 0) {
+ munmap(addr, prefix_size);
+#if BH_ENABLE_TRACE_MMAP != 0
+ total_size_munmapped += prefix_size;
+ os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, "
+ "total_size_munmapped: %zu\n",
+ addr, prefix_size, total_size_mmapped,
+ total_size_munmapped);
+#endif
+ }
+ if (suffix_size > 0) {
+ munmap(addr + request_size - suffix_size, suffix_size);
+#if BH_ENABLE_TRACE_MMAP != 0
+ total_size_munmapped += suffix_size;
+ os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, "
+ "total_size_munmapped: %zu\n",
+ addr + request_size - suffix_size, suffix_size,
+ total_size_mmapped, total_size_munmapped);
+#endif
+ }
+
+ addr = (uint8 *)huge_start;
+ request_size -= HUGE_PAGE_SIZE;
+
+ huge_end = round_down(huge_start + request_size, HUGE_PAGE_SIZE);
+ if (huge_end > huge_start) {
+ int ret = madvise((void *)huge_start, huge_end - huge_start,
+ MADV_HUGEPAGE);
+ if (ret) {
+#if BH_ENABLE_TRACE_MMAP != 0
+ os_printf(
+ "warning: madvise(%p, %lu) huge page failed, return %d\n",
+ (void *)huge_start, huge_end - huge_start, ret);
+#endif
+ }
+ }
+ }
+#endif /* end of __APPLE__ || __NuttX__ || !MADV_HUGEPAGE */
+
+ return addr;
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ uint64 page_size = (uint64)getpagesize();
+ uint64 request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (addr) {
+ if (munmap(addr, request_size)) {
+ os_printf("os_munmap error addr:%p, size:0x%" PRIx64 ", errno:%d\n",
+ addr, request_size, errno);
+ return;
+ }
+#if BH_ENABLE_TRACE_MMAP != 0
+ total_size_munmapped += request_size;
+ os_printf("munmap %p with size: %zu, total_size_mmapped: %zu, "
+ "total_size_munmapped: %zu\n",
+ addr, request_size, total_size_mmapped, total_size_munmapped);
+#endif
+ }
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ int map_prot = PROT_NONE;
+ uint64 page_size = (uint64)getpagesize();
+ uint64 request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ 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, request_size, map_prot);
+}
+
+void
+os_dcache_flush(void)
+{}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_socket.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_socket.c
new file mode 100644
index 000000000..e33781d7d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_socket.c
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+
+static bool
+textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out,
+ socklen_t *out_len)
+{
+ struct sockaddr_in *v4;
+#ifdef IPPROTO_IPV6
+ struct sockaddr_in6 *v6;
+#endif
+
+ assert(textual);
+
+ v4 = (struct sockaddr_in *)out;
+ if (inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) {
+ v4->sin_family = AF_INET;
+ v4->sin_port = htons(port);
+ *out_len = sizeof(struct sockaddr_in);
+ return true;
+ }
+
+#ifdef IPPROTO_IPV6
+ v6 = (struct sockaddr_in6 *)out;
+ if (inet_pton(AF_INET6, textual, &v6->sin6_addr.s6_addr) == 1) {
+ v6->sin6_family = AF_INET6;
+ v6->sin6_port = htons(port);
+ *out_len = sizeof(struct sockaddr_in6);
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static int
+sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr,
+ bh_sockaddr_t *bh_sockaddr)
+{
+ switch (sockaddr->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
+
+ bh_sockaddr->port = ntohs(addr->sin_port);
+ bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
+ bh_sockaddr->is_ipv4 = true;
+ return BHT_OK;
+ }
+#ifdef IPPROTO_IPV6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
+ size_t i;
+
+ bh_sockaddr->port = ntohs(addr->sin6_port);
+
+ for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
+ / sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
+ i++) {
+ uint16 part_addr = addr->sin6_addr.s6_addr[i * 2]
+ | (addr->sin6_addr.s6_addr[i * 2 + 1] << 8);
+ bh_sockaddr->addr_bufer.ipv6[i] = ntohs(part_addr);
+ }
+
+ bh_sockaddr->is_ipv4 = false;
+ return BHT_OK;
+ }
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+ }
+}
+
+static void
+bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
+ struct sockaddr_storage *sockaddr, socklen_t *socklen)
+{
+ if (bh_sockaddr->is_ipv4) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
+ addr->sin_port = htons(bh_sockaddr->port);
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4);
+ *socklen = sizeof(*addr);
+ }
+#ifdef IPPROTO_IPV6
+ else {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
+ size_t i;
+ addr->sin6_port = htons(bh_sockaddr->port);
+ addr->sin6_family = AF_INET6;
+
+ for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
+ / sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
+ i++) {
+ uint16 part_addr = htons(bh_sockaddr->addr_bufer.ipv6[i]);
+ addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr;
+ addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8;
+ }
+
+ *socklen = sizeof(*addr);
+ }
+#endif
+}
+
+int
+os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
+{
+ int af = is_ipv4 ? AF_INET : AF_INET6;
+
+ if (!sock) {
+ return BHT_ERROR;
+ }
+
+ if (is_tcp) {
+ *sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
+ }
+ else {
+ *sock = socket(af, SOCK_DGRAM, 0);
+ }
+
+ return (*sock == -1) ? BHT_ERROR : BHT_OK;
+}
+
+int
+os_socket_bind(bh_socket_t socket, const char *host, int *port)
+{
+ struct sockaddr_storage addr = { 0 };
+ struct linger ling;
+ socklen_t socklen;
+ int ret;
+
+ assert(host);
+ assert(port);
+
+ ling.l_onoff = 1;
+ ling.l_linger = 0;
+
+ if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr,
+ &socklen)) {
+ goto fail;
+ }
+
+ ret = fcntl(socket, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ ret = setsockopt(socket, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
+ if (ret < 0) {
+ goto fail;
+ }
+
+ ret = bind(socket, (struct sockaddr *)&addr, socklen);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ socklen = sizeof(addr);
+ if (getsockname(socket, (void *)&addr, &socklen) == -1) {
+ goto fail;
+ }
+
+ if (addr.ss_family == AF_INET) {
+ *port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
+ }
+ else {
+#ifdef IPPROTO_IPV6
+ *port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
+#else
+ goto fail;
+#endif
+ }
+
+ return BHT_OK;
+
+fail:
+ return BHT_ERROR;
+}
+
+int
+os_socket_settimeout(bh_socket_t socket, uint64 timeout_us)
+{
+ struct timeval tv;
+ tv.tv_sec = timeout_us / 1000000UL;
+ tv.tv_usec = timeout_us % 1000000UL;
+
+ if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv,
+ sizeof(tv))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_listen(bh_socket_t socket, int max_client)
+{
+ if (listen(socket, max_client) != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
+ unsigned int *addrlen)
+{
+ *sock = accept(server_sock, addr, addrlen);
+
+ if (*sock < 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_connect(bh_socket_t socket, const char *addr, int port)
+{
+ struct sockaddr_storage addr_in = { 0 };
+ socklen_t addr_len;
+ int ret = 0;
+
+ if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr_in,
+ &addr_len)) {
+ return BHT_ERROR;
+ }
+
+ ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
+ if (ret == -1) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
+{
+ return recv(socket, buf, len, 0);
+}
+
+int
+os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
+ bh_sockaddr_t *src_addr)
+{
+ struct sockaddr_storage sock_addr = { 0 };
+ socklen_t socklen = sizeof(sock_addr);
+ int ret;
+
+ ret = recvfrom(socket, buf, len, flags, (struct sockaddr *)&sock_addr,
+ &socklen);
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (src_addr && socklen > 0) {
+ if (sockaddr_to_bh_sockaddr((struct sockaddr *)&sock_addr, src_addr)
+ == BHT_ERROR) {
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+int
+os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
+{
+ return send(socket, buf, len, 0);
+}
+
+int
+os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
+ int flags, const bh_sockaddr_t *dest_addr)
+{
+ struct sockaddr_storage sock_addr = { 0 };
+ socklen_t socklen = 0;
+
+ bh_sockaddr_to_sockaddr(dest_addr, &sock_addr, &socklen);
+
+ return sendto(socket, buf, len, flags, (const struct sockaddr *)&sock_addr,
+ socklen);
+}
+
+int
+os_socket_close(bh_socket_t socket)
+{
+ close(socket);
+ return BHT_OK;
+}
+
+int
+os_socket_shutdown(bh_socket_t socket)
+{
+ shutdown(socket, O_RDWR);
+ return BHT_OK;
+}
+
+int
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
+{
+ if (!cp)
+ return BHT_ERROR;
+
+ if (is_ipv4) {
+ if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
+ return BHT_ERROR;
+ }
+ /* Note: ntohl(INADDR_NONE) == INADDR_NONE */
+ out->ipv4 = ntohl(out->ipv4);
+ }
+ else {
+#ifdef IPPROTO_IPV6
+ if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
+ return BHT_ERROR;
+ }
+ for (int i = 0; i < 8; i++) {
+ out->ipv6[i] = ntohs(out->ipv6[i]);
+ }
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+ }
+
+ return BHT_OK;
+}
+
+static int
+getaddrinfo_error_to_errno(int error)
+{
+ switch (error) {
+ case EAI_AGAIN:
+ return EAGAIN;
+ case EAI_FAIL:
+ return EFAULT;
+ case EAI_MEMORY:
+ return ENOMEM;
+ case EAI_SYSTEM:
+ return errno;
+ default:
+ return EINVAL;
+ }
+}
+
+static int
+is_addrinfo_supported(struct addrinfo *info)
+{
+ return
+ // Allow only IPv4 and IPv6
+ (info->ai_family == AF_INET || info->ai_family == AF_INET6)
+ // Allow only UDP and TCP
+ && (info->ai_socktype == SOCK_DGRAM || info->ai_socktype == SOCK_STREAM)
+ && (info->ai_protocol == IPPROTO_TCP
+ || info->ai_protocol == IPPROTO_UDP);
+}
+
+int
+os_socket_addr_resolve(const char *host, const char *service,
+ uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
+ bh_addr_info_t *addr_info, size_t addr_info_size,
+ size_t *max_info_size)
+{
+ struct addrinfo hints = { 0 }, *res, *result;
+ int hints_enabled = hint_is_tcp || hint_is_ipv4;
+ int ret;
+ size_t pos = 0;
+
+ if (hints_enabled) {
+ if (hint_is_ipv4) {
+ hints.ai_family = *hint_is_ipv4 ? AF_INET : AF_INET6;
+ }
+ if (hint_is_tcp) {
+ hints.ai_socktype = *hint_is_tcp ? SOCK_STREAM : SOCK_DGRAM;
+ }
+ }
+
+ ret = getaddrinfo(host, strlen(service) == 0 ? NULL : service,
+ hints_enabled ? &hints : NULL, &result);
+ if (ret != BHT_OK) {
+ errno = getaddrinfo_error_to_errno(ret);
+ return BHT_ERROR;
+ }
+
+ res = result;
+ while (res) {
+ if (addr_info_size > pos) {
+ if (!is_addrinfo_supported(res)) {
+ res = res->ai_next;
+ continue;
+ }
+
+ ret =
+ sockaddr_to_bh_sockaddr(res->ai_addr, &addr_info[pos].sockaddr);
+
+ if (ret == BHT_ERROR) {
+ freeaddrinfo(result);
+ return BHT_ERROR;
+ }
+
+ addr_info[pos].is_tcp = res->ai_socktype == SOCK_STREAM;
+ }
+
+ pos++;
+ res = res->ai_next;
+ }
+
+ *max_info_size = pos;
+ freeaddrinfo(result);
+
+ return BHT_OK;
+}
+
+static int
+os_socket_setbooloption(bh_socket_t socket, int level, int optname,
+ bool is_enabled)
+{
+ int option = (int)is_enabled;
+ if (setsockopt(socket, level, optname, &option, sizeof(option)) != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+static int
+os_socket_getbooloption(bh_socket_t socket, int level, int optname,
+ bool *is_enabled)
+{
+ assert(is_enabled);
+
+ int optval;
+ socklen_t optval_size = sizeof(optval);
+ if (getsockopt(socket, level, optname, &optval, &optval_size) != 0) {
+ return BHT_ERROR;
+ }
+ *is_enabled = (bool)optval;
+ return BHT_OK;
+}
+
+int
+os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+ int buf_size_int = (int)bufsiz;
+ if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int,
+ sizeof(buf_size_int))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+ assert(bufsiz);
+
+ int buf_size_int;
+ socklen_t bufsiz_len = sizeof(buf_size_int);
+ if (getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int, &bufsiz_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+ *bufsiz = (size_t)buf_size_int;
+
+ return BHT_OK;
+}
+
+int
+os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+ int buf_size_int = (int)bufsiz;
+ if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int,
+ sizeof(buf_size_int))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+ assert(bufsiz);
+
+ int buf_size_int;
+ socklen_t bufsiz_len = sizeof(buf_size_int);
+ if (getsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int, &bufsiz_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+ *bufsiz = (size_t)buf_size_int;
+
+ return BHT_OK;
+}
+
+int
+os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
+ is_enabled);
+}
+
+int
+os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
+ is_enabled);
+}
+
+int
+os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
+ is_enabled);
+}
+
+int
+os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
+ is_enabled);
+}
+
+int
+os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled)
+{
+#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
+ is_enabled);
+#else
+ errno = ENOTSUP;
+ return BHT_ERROR;
+#endif /* defined(SO_REUSEPORT) */
+}
+
+int
+os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled)
+{
+#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
+ is_enabled);
+#else
+ errno = ENOTSUP;
+ return BHT_ERROR;
+#endif /* defined(SO_REUSEPORT) */
+}
+
+int
+os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s)
+{
+ struct linger linger_opts = { .l_onoff = (int)is_enabled,
+ .l_linger = linger_s };
+ if (setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts,
+ sizeof(linger_opts))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s)
+{
+ assert(is_enabled);
+ assert(linger_s);
+
+ struct linger linger_opts;
+ socklen_t linger_opts_len = sizeof(linger_opts);
+ if (getsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts,
+ &linger_opts_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+ *linger_s = linger_opts.l_linger;
+ *is_enabled = (bool)linger_opts.l_onoff;
+ return BHT_OK;
+}
+
+int
+os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_NODELAY,
+ is_enabled);
+}
+
+int
+os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_NODELAY,
+ is_enabled);
+}
+
+int
+os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled)
+{
+#ifdef TCP_QUICKACK
+ return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_QUICKACK,
+ is_enabled);
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled)
+{
+#ifdef TCP_QUICKACK
+ return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_QUICKACK,
+ is_enabled);
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s)
+{
+ int time_s_int = (int)time_s;
+#ifdef TCP_KEEPIDLE
+ if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int,
+ sizeof(time_s_int))
+ != 0) {
+ return BHT_ERROR;
+ }
+ return BHT_OK;
+#elif defined(TCP_KEEPALIVE)
+ if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int,
+ sizeof(time_s_int))
+ != 0) {
+ return BHT_ERROR;
+ }
+ return BHT_OK;
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s)
+{
+ assert(time_s);
+ int time_s_int;
+ socklen_t time_s_len = sizeof(time_s_int);
+#ifdef TCP_KEEPIDLE
+ if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, &time_s_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+ *time_s = (uint32)time_s_int;
+ return BHT_OK;
+#elif defined(TCP_KEEPALIVE)
+ if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, &time_s_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+ *time_s = (uint32)time_s_int;
+ return BHT_OK;
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s)
+{
+ int time_s_int = (int)time_s;
+#ifdef TCP_KEEPINTVL
+ if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int,
+ sizeof(time_s_int))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s)
+{
+#ifdef TCP_KEEPINTVL
+ assert(time_s);
+ int time_s_int;
+ socklen_t time_s_len = sizeof(time_s_int);
+ if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int, &time_s_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+ *time_s = (uint32)time_s_int;
+ return BHT_OK;
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled)
+{
+#ifdef TCP_FASTOPEN_CONNECT
+ return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+ is_enabled);
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled)
+{
+#ifdef TCP_FASTOPEN_CONNECT
+ return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+ is_enabled);
+#else
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled)
+{
+ if (ipv6) {
+#ifdef IPPROTO_IPV6
+ return os_socket_setbooloption(socket, IPPROTO_IPV6,
+ IPV6_MULTICAST_LOOP, is_enabled);
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+ }
+ else {
+ return os_socket_setbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
+ is_enabled);
+ }
+}
+
+int
+os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled)
+{
+ if (ipv6) {
+#ifdef IPPROTO_IPV6
+ return os_socket_getbooloption(socket, IPPROTO_IPV6,
+ IPV6_MULTICAST_LOOP, is_enabled);
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+ }
+ else {
+ return os_socket_getbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
+ is_enabled);
+ }
+}
+
+int
+os_socket_set_ip_add_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6)
+{
+ assert(imr_multiaddr);
+ if (is_ipv6) {
+#ifdef IPPROTO_IPV6
+ struct ipv6_mreq mreq;
+ for (int i = 0; i < 8; i++) {
+ ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
+ imr_multiaddr->ipv6[i];
+ }
+ mreq.ipv6mr_interface = imr_interface;
+ if (setsockopt(socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
+ sizeof(mreq))
+ != 0) {
+ return BHT_ERROR;
+ }
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+ }
+ else {
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
+ mreq.imr_interface.s_addr = imr_interface;
+ if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq))
+ != 0) {
+ return BHT_ERROR;
+ }
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_set_ip_drop_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6)
+{
+ assert(imr_multiaddr);
+ if (is_ipv6) {
+#ifdef IPPROTO_IPV6
+ struct ipv6_mreq mreq;
+ for (int i = 0; i < 8; i++) {
+ ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
+ imr_multiaddr->ipv6[i];
+ }
+ mreq.ipv6mr_interface = imr_interface;
+ if (setsockopt(socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq,
+ sizeof(mreq))
+ != 0) {
+ return BHT_ERROR;
+ }
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+ }
+ else {
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
+ mreq.imr_interface.s_addr = imr_interface;
+ if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq,
+ sizeof(mreq))
+ != 0) {
+ return BHT_ERROR;
+ }
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+ if (setsockopt(socket, IPPROTO_IP, IP_TTL, &ttl_s, sizeof(ttl_s)) != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+ socklen_t opt_len = sizeof(ttl_s);
+ if (getsockopt(socket, IPPROTO_IP, IP_TTL, ttl_s, &opt_len) != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+ if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl_s, sizeof(ttl_s))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+ socklen_t opt_len = sizeof(ttl_s);
+ if (getsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, &opt_len)
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled)
+{
+#ifdef IPPROTO_IPV6
+ return os_socket_setbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
+ is_enabled);
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled)
+{
+#ifdef IPPROTO_IPV6
+ return os_socket_getbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
+ is_enabled);
+#else
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+#endif
+}
+
+int
+os_socket_set_broadcast(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_BROADCAST,
+ is_enabled);
+}
+
+int
+os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_BROADCAST,
+ is_enabled);
+}
+
+int
+os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+ struct timeval tv;
+ tv.tv_sec = timeout_us / 1000000UL;
+ tv.tv_usec = timeout_us % 1000000UL;
+ if (setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
+ return BHT_ERROR;
+ }
+ return BHT_OK;
+}
+
+int
+os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+ struct timeval tv;
+ socklen_t tv_len = sizeof(tv);
+ if (getsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len) != 0) {
+ return BHT_ERROR;
+ }
+ *timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
+ return BHT_OK;
+}
+
+int
+os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+ struct timeval tv;
+ tv.tv_sec = timeout_us / 1000000UL;
+ tv.tv_usec = timeout_us % 1000000UL;
+ if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
+ return BHT_ERROR;
+ }
+ return BHT_OK;
+}
+
+int
+os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+ struct timeval tv;
+ socklen_t tv_len = sizeof(tv);
+ if (getsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len) != 0) {
+ return BHT_ERROR;
+ }
+ *timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
+ return BHT_OK;
+}
+
+int
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ struct sockaddr_storage addr_storage = { 0 };
+ socklen_t addr_len = sizeof(addr_storage);
+ int ret;
+
+ ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
+
+ if (ret != BHT_OK) {
+ return BHT_ERROR;
+ }
+
+ return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, sockaddr);
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ struct sockaddr_storage addr_storage = { 0 };
+ socklen_t addr_len = sizeof(addr_storage);
+ int ret;
+
+ ret = getpeername(socket, (struct sockaddr *)&addr_storage, &addr_len);
+
+ if (ret != BHT_OK) {
+ return BHT_ERROR;
+ }
+
+ return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, sockaddr);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_thread.c
new file mode 100644
index 000000000..5e814c418
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_thread.c
@@ -0,0 +1,680 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+typedef struct {
+ thread_start_routine_t start;
+ void *arg;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_signal_handler signal_handler;
+#endif
+} thread_wrapper_arg;
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+/* The signal handler passed to os_thread_signal_init() */
+static os_thread_local_attribute os_signal_handler signal_handler;
+#endif
+
+static void *
+os_thread_wrapper(void *arg)
+{
+ thread_wrapper_arg *targ = arg;
+ thread_start_routine_t start_func = targ->start;
+ void *thread_arg = targ->arg;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_signal_handler handler = targ->signal_handler;
+#endif
+
+#if 0
+ os_printf("THREAD CREATED %jx\n", (uintmax_t)(uintptr_t)pthread_self());
+#endif
+ BH_FREE(targ);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (os_thread_signal_init(handler) != 0)
+ return NULL;
+#endif
+ start_func(thread_arg);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_thread_signal_destroy();
+#endif
+ return NULL;
+}
+
+int
+os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ pthread_attr_t tattr;
+ thread_wrapper_arg *targ;
+
+ assert(stack_size > 0);
+ assert(tid);
+ assert(start);
+
+ pthread_attr_init(&tattr);
+ pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
+ if (pthread_attr_setstacksize(&tattr, stack_size) != 0) {
+ os_printf("Invalid thread stack size %u. "
+ "Min stack size on Linux = %u\n",
+ stack_size, (unsigned int)PTHREAD_STACK_MIN);
+ pthread_attr_destroy(&tattr);
+ return BHT_ERROR;
+ }
+
+ targ = (thread_wrapper_arg *)BH_MALLOC(sizeof(*targ));
+ if (!targ) {
+ pthread_attr_destroy(&tattr);
+ return BHT_ERROR;
+ }
+
+ targ->start = start;
+ targ->arg = arg;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ targ->signal_handler = signal_handler;
+#endif
+
+ if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) {
+ pthread_attr_destroy(&tattr);
+ BH_FREE(targ);
+ return BHT_ERROR;
+ }
+
+ pthread_attr_destroy(&tattr);
+ return BHT_OK;
+}
+
+int
+os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+korp_tid
+os_self_thread()
+{
+ return (korp_tid)pthread_self();
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_recursive_mutex_init(korp_mutex *mutex)
+{
+ int ret;
+
+ pthread_mutexattr_t mattr;
+
+ assert(mutex);
+ ret = pthread_mutexattr_init(&mattr);
+ if (ret)
+ return BHT_ERROR;
+
+ pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
+ ret = pthread_mutex_init(mutex, &mattr);
+ pthread_mutexattr_destroy(&mattr);
+
+ return ret == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ int ret;
+
+ assert(mutex);
+ ret = pthread_mutex_destroy(mutex);
+
+ return ret == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ int ret;
+
+ assert(mutex);
+ ret = pthread_mutex_lock(mutex);
+
+ return ret == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ int ret;
+
+ assert(mutex);
+ ret = pthread_mutex_unlock(mutex);
+
+ return ret == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ assert(cond);
+
+ if (pthread_cond_init(cond, NULL) != BHT_OK)
+ return BHT_ERROR;
+
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ assert(cond);
+
+ if (pthread_cond_destroy(cond) != BHT_OK)
+ return BHT_ERROR;
+
+ return BHT_OK;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ assert(cond);
+ assert(mutex);
+
+ if (pthread_cond_wait(cond, mutex) != BHT_OK)
+ return BHT_ERROR;
+
+ return BHT_OK;
+}
+
+korp_sem *
+os_sem_open(const char *name, int oflags, int mode, int val)
+{
+ return sem_open(name, oflags, mode, val);
+}
+
+int
+os_sem_close(korp_sem *sem)
+{
+ return sem_close(sem);
+}
+
+int
+os_sem_wait(korp_sem *sem)
+{
+ return sem_wait(sem);
+}
+
+int
+os_sem_trywait(korp_sem *sem)
+{
+ return sem_trywait(sem);
+}
+
+int
+os_sem_post(korp_sem *sem)
+{
+ return sem_post(sem);
+}
+
+int
+os_sem_getvalue(korp_sem *sem, int *sval)
+{
+#if defined(__APPLE__)
+ /*
+ * macOS doesn't have working sem_getvalue.
+ * It's marked as deprecated in the system header.
+ * Mock it up here to avoid compile-time deprecation warnings.
+ */
+ errno = ENOSYS;
+ return -1;
+#else
+ return sem_getvalue(sem, sval);
+#endif
+}
+
+int
+os_sem_unlink(const char *name)
+{
+ return sem_unlink(name);
+}
+
+static void
+msec_nsec_to_abstime(struct timespec *ts, uint64 usec)
+{
+ struct timeval tv;
+ time_t tv_sec_new;
+ long int tv_nsec_new;
+
+ gettimeofday(&tv, NULL);
+
+ tv_sec_new = (time_t)(tv.tv_sec + usec / 1000000);
+ if (tv_sec_new >= tv.tv_sec) {
+ ts->tv_sec = tv_sec_new;
+ }
+ else {
+ /* integer overflow */
+ ts->tv_sec = BH_TIME_T_MAX;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+
+ tv_nsec_new = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000);
+ if (tv.tv_usec * 1000 >= tv.tv_usec && tv_nsec_new >= tv.tv_usec * 1000) {
+ ts->tv_nsec = tv_nsec_new;
+ }
+ else {
+ /* integer overflow */
+ ts->tv_nsec = LONG_MAX;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+
+ if (ts->tv_nsec >= 1000000000L && ts->tv_sec < BH_TIME_T_MAX) {
+ ts->tv_sec++;
+ ts->tv_nsec -= 1000000000L;
+ }
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ int ret;
+ struct timespec abstime;
+
+ if (useconds == BHT_WAIT_FOREVER)
+ ret = pthread_cond_wait(cond, mutex);
+ else {
+ msec_nsec_to_abstime(&abstime, useconds);
+ ret = pthread_cond_timedwait(cond, mutex, &abstime);
+ }
+
+ if (ret != BHT_OK && ret != ETIMEDOUT)
+ return BHT_ERROR;
+
+ return ret;
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ assert(cond);
+
+ if (pthread_cond_signal(cond) != BHT_OK)
+ return BHT_ERROR;
+
+ return BHT_OK;
+}
+
+int
+os_cond_broadcast(korp_cond *cond)
+{
+ assert(cond);
+
+ if (pthread_cond_broadcast(cond) != BHT_OK)
+ return BHT_ERROR;
+
+ return BHT_OK;
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+ return pthread_join(thread, value_ptr);
+}
+
+int
+os_thread_detach(korp_tid thread)
+{
+ return pthread_detach(thread);
+}
+
+void
+os_thread_exit(void *retval)
+{
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_thread_signal_destroy();
+#endif
+ return pthread_exit(retval);
+}
+
+#if defined(os_thread_local_attribute)
+static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
+#endif
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+ pthread_t self;
+#ifdef __linux__
+ pthread_attr_t attr;
+ size_t guard_size;
+#endif
+ uint8 *addr = NULL;
+ size_t stack_size, max_stack_size;
+ int page_size;
+
+#if defined(os_thread_local_attribute)
+ if (thread_stack_boundary)
+ return thread_stack_boundary;
+#endif
+
+ page_size = getpagesize();
+ self = pthread_self();
+ max_stack_size =
+ (size_t)(APP_THREAD_STACK_SIZE_MAX + page_size - 1) & ~(page_size - 1);
+
+ if (max_stack_size < APP_THREAD_STACK_SIZE_DEFAULT)
+ max_stack_size = APP_THREAD_STACK_SIZE_DEFAULT;
+
+#ifdef __linux__
+ if (pthread_getattr_np(self, &attr) == 0) {
+ pthread_attr_getstack(&attr, (void **)&addr, &stack_size);
+ pthread_attr_getguardsize(&attr, &guard_size);
+ pthread_attr_destroy(&attr);
+ if (stack_size > max_stack_size)
+ addr = addr + stack_size - max_stack_size;
+ if (guard_size < (size_t)page_size)
+ /* Reserved 1 guard page at least for safety */
+ guard_size = (size_t)page_size;
+ addr += guard_size;
+ }
+ (void)stack_size;
+#elif defined(__APPLE__) || defined(__NuttX__)
+ if ((addr = (uint8 *)pthread_get_stackaddr_np(self))) {
+ stack_size = pthread_get_stacksize_np(self);
+
+ /**
+ * Check whether stack_addr is the base or end of the stack,
+ * change it to the base if it is the end of stack.
+ */
+ if (addr <= (uint8 *)&stack_size)
+ addr = addr + stack_size;
+
+ if (stack_size > max_stack_size)
+ stack_size = max_stack_size;
+
+ addr -= stack_size;
+ /* Reserved 1 guard page at least for safety */
+ addr += page_size;
+ }
+#endif
+
+#if defined(os_thread_local_attribute)
+ thread_stack_boundary = addr;
+#endif
+ return addr;
+}
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+
+#define SIG_ALT_STACK_SIZE (32 * 1024)
+
+/**
+ * Whether thread signal enviornment is initialized:
+ * the signal handler is registered, the stack pages are touched,
+ * the stack guard pages are set and signal alternate stack are set.
+ */
+static os_thread_local_attribute bool thread_signal_inited = false;
+
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+/* The signal alternate stack base addr */
+static os_thread_local_attribute uint8 *sigalt_stack_base_addr;
+
+#if defined(__clang__)
+#pragma clang optimize off
+#elif defined(__GNUC__)
+#pragma GCC push_options
+#pragma GCC optimize("O0")
+__attribute__((no_sanitize_address))
+#endif
+static uint32
+touch_pages(uint8 *stack_min_addr, uint32 page_size)
+{
+ uint8 sum = 0;
+ while (1) {
+ volatile uint8 *touch_addr = (volatile uint8 *)os_alloca(page_size / 2);
+ if (touch_addr < stack_min_addr + page_size) {
+ sum += *(stack_min_addr + page_size - 1);
+ break;
+ }
+ *touch_addr = 0;
+ sum += *touch_addr;
+ }
+ return sum;
+}
+#if defined(__clang__)
+#pragma clang optimize on
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+
+static bool
+init_stack_guard_pages()
+{
+ uint32 page_size = os_getpagesize();
+ uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+ uint8 *stack_min_addr = os_thread_get_stack_boundary();
+
+ if (stack_min_addr == NULL)
+ return false;
+
+ /* Touch each stack page to ensure that it has been mapped: the OS
+ may lazily grow the stack mapping as a guard page is hit. */
+ (void)touch_pages(stack_min_addr, page_size);
+ /* First time to call aot function, protect guard pages */
+ if (os_mprotect(stack_min_addr, page_size * guard_page_count,
+ MMAP_PROT_NONE)
+ != 0) {
+ return false;
+ }
+ return true;
+}
+
+static void
+destroy_stack_guard_pages()
+{
+ uint32 page_size = os_getpagesize();
+ uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+ uint8 *stack_min_addr = os_thread_get_stack_boundary();
+
+ os_mprotect(stack_min_addr, page_size * guard_page_count,
+ MMAP_PROT_READ | MMAP_PROT_WRITE);
+}
+#endif /* end of WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 */
+
+static void
+mask_signals(int how)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGSEGV);
+ sigaddset(&set, SIGBUS);
+ pthread_sigmask(how, &set, NULL);
+}
+
+static os_thread_local_attribute struct sigaction prev_sig_act_SIGSEGV;
+static os_thread_local_attribute struct sigaction prev_sig_act_SIGBUS;
+
+static void
+signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
+{
+ void *sig_addr = sig_info->si_addr;
+ struct sigaction *prev_sig_act = NULL;
+
+ mask_signals(SIG_BLOCK);
+
+ /* Try to handle signal with the registered signal handler */
+ if (signal_handler && (sig_num == SIGSEGV || sig_num == SIGBUS)) {
+ signal_handler(sig_addr);
+ }
+
+ if (sig_num == SIGSEGV)
+ prev_sig_act = &prev_sig_act_SIGSEGV;
+ else if (sig_num == SIGBUS)
+ prev_sig_act = &prev_sig_act_SIGBUS;
+
+ /* Forward the signal to next handler if found */
+ if (prev_sig_act && (prev_sig_act->sa_flags & SA_SIGINFO)) {
+ prev_sig_act->sa_sigaction(sig_num, sig_info, sig_ucontext);
+ }
+ else if (prev_sig_act
+ && ((void *)prev_sig_act->sa_sigaction == SIG_DFL
+ || (void *)prev_sig_act->sa_sigaction == SIG_IGN)) {
+ sigaction(sig_num, prev_sig_act, NULL);
+ }
+ /* Output signal info and then crash if signal is unhandled */
+ else {
+ switch (sig_num) {
+ case SIGSEGV:
+ os_printf("unhandled SIGSEGV, si_addr: %p\n", sig_addr);
+ break;
+ case SIGBUS:
+ os_printf("unhandled SIGBUS, si_addr: %p\n", sig_addr);
+ break;
+ default:
+ os_printf("unhandle signal %d, si_addr: %p\n", sig_num,
+ sig_addr);
+ break;
+ }
+
+ abort();
+ }
+}
+
+int
+os_thread_signal_init(os_signal_handler handler)
+{
+ struct sigaction sig_act;
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ stack_t sigalt_stack_info;
+ uint32 map_size = SIG_ALT_STACK_SIZE;
+ uint8 *map_addr;
+#endif
+
+ if (thread_signal_inited)
+ return 0;
+
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ if (!init_stack_guard_pages()) {
+ os_printf("Failed to init stack guard pages\n");
+ return -1;
+ }
+
+ /* Initialize memory for signal alternate stack of current thread */
+ if (!(map_addr = os_mmap(NULL, map_size, MMAP_PROT_READ | MMAP_PROT_WRITE,
+ MMAP_MAP_NONE))) {
+ os_printf("Failed to mmap memory for alternate stack\n");
+ goto fail1;
+ }
+
+ /* Initialize signal alternate stack */
+ memset(map_addr, 0, map_size);
+ sigalt_stack_info.ss_sp = map_addr;
+ sigalt_stack_info.ss_size = map_size;
+ sigalt_stack_info.ss_flags = 0;
+ if (sigaltstack(&sigalt_stack_info, NULL) != 0) {
+ os_printf("Failed to init signal alternate stack\n");
+ goto fail2;
+ }
+#endif
+
+ memset(&prev_sig_act_SIGSEGV, 0, sizeof(struct sigaction));
+ memset(&prev_sig_act_SIGBUS, 0, sizeof(struct sigaction));
+
+ /* Install signal hanlder */
+ sig_act.sa_sigaction = signal_callback;
+ sig_act.sa_flags = SA_SIGINFO | SA_NODEFER;
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ sig_act.sa_flags |= SA_ONSTACK;
+#endif
+ sigemptyset(&sig_act.sa_mask);
+ if (sigaction(SIGSEGV, &sig_act, &prev_sig_act_SIGSEGV) != 0
+ || sigaction(SIGBUS, &sig_act, &prev_sig_act_SIGBUS) != 0) {
+ os_printf("Failed to register signal handler\n");
+ goto fail3;
+ }
+
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ sigalt_stack_base_addr = map_addr;
+#endif
+ signal_handler = handler;
+ thread_signal_inited = true;
+ return 0;
+
+fail3:
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ memset(&sigalt_stack_info, 0, sizeof(stack_t));
+ sigalt_stack_info.ss_flags = SS_DISABLE;
+ sigalt_stack_info.ss_size = map_size;
+ sigaltstack(&sigalt_stack_info, NULL);
+fail2:
+ os_munmap(map_addr, map_size);
+fail1:
+ destroy_stack_guard_pages();
+#endif
+ return -1;
+}
+
+void
+os_thread_signal_destroy()
+{
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ stack_t sigalt_stack_info;
+#endif
+
+ if (!thread_signal_inited)
+ return;
+
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ /* Disable signal alternate stack */
+ memset(&sigalt_stack_info, 0, sizeof(stack_t));
+ sigalt_stack_info.ss_flags = SS_DISABLE;
+ sigalt_stack_info.ss_size = SIG_ALT_STACK_SIZE;
+ sigaltstack(&sigalt_stack_info, NULL);
+
+ os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE);
+
+ destroy_stack_guard_pages();
+#endif
+
+ thread_signal_inited = false;
+}
+
+bool
+os_thread_signal_inited()
+{
+ return thread_signal_inited;
+}
+
+void
+os_signal_unmask()
+{
+ mask_signals(SIG_UNBLOCK);
+}
+
+void
+os_sigreturn()
+{
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+#if defined(__APPLE__)
+#define UC_RESET_ALT_STACK 0x80000000
+ extern int __sigreturn(void *, int);
+
+ /* It's necessary to call __sigreturn to restore the sigaltstack state
+ after exiting the signal handler. */
+ __sigreturn(NULL, UC_RESET_ALT_STACK);
+#endif
+#endif
+}
+#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_time.c
new file mode 100644
index 000000000..bcf5ca3ce
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/common/posix/posix_time.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+uint64
+os_time_get_boot_microsecond()
+{
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
+ return 0;
+ }
+
+ return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_init.c
new file mode 100644
index 000000000..2aae13fa1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_init.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+#ifndef BH_VPRINTF
+ ret += vprintf(format, ap);
+#else
+ ret += BH_VPRINTF(format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+ return vprintf(format, ap);
+#else
+ return BH_VPRINTF(format, ap);
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_internal.h
new file mode 100644
index 000000000..3fd1c258e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/platform_internal.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sched.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_DARWIN
+#define BH_PLATFORM_DARWIN
+#endif
+
+#define BH_HAS_DLFCN 1
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define os_thread_local_attribute __thread
+
+#define bh_socket_t int
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#define os_alloca alloca
+
+#define os_getpagesize getpagesize
+
+typedef void (*os_signal_handler)(void *sig_addr);
+
+int
+os_thread_signal_init(os_signal_handler handler);
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+void
+os_signal_unmask();
+
+void
+os_sigreturn();
+#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/shared_platform.cmake
new file mode 100644
index 000000000..5eecd65c7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/darwin/shared_platform.cmake
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_DARWIN)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_init.c
new file mode 100644
index 000000000..38a0e8049
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_init.c
@@ -0,0 +1,6 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "../linux/platform_init.c" \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_internal.h
new file mode 100644
index 000000000..1ece346be
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/platform_internal.h
@@ -0,0 +1,6 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "../linux/platform_internal.h"
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/shared_platform.cmake
new file mode 100644
index 000000000..9b84c5841
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/ego/shared_platform.cmake
@@ -0,0 +1,20 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_EGO)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+set (PLATFORM_SHARED_SOURCE
+ ${PLATFORM_COMMON_POSIX_SOURCE}
+ ${CMAKE_CURRENT_LIST_DIR}/platform_init.c
+)
+
+LIST (APPEND RUNTIME_LIB_HEADER_LIST
+ ${CMAKE_CURRENT_LIST_DIR}/platform_internal.h
+) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_malloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_malloc.c
new file mode 100644
index 000000000..08ec88305
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_malloc.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+void *
+os_malloc(unsigned size)
+{
+ void *buf_origin;
+ void *buf_fixed;
+ uintptr_t *addr_field;
+
+ buf_origin = malloc(size + 8 + sizeof(uintptr_t));
+ if (!buf_origin) {
+ return NULL;
+ }
+ buf_fixed = buf_origin + sizeof(void *);
+ if ((uintptr_t)buf_fixed & (uintptr_t)0x7) {
+ buf_fixed = (void *)((uintptr_t)(buf_fixed + 8) & (~(uintptr_t)7));
+ }
+
+ addr_field = buf_fixed - sizeof(uintptr_t);
+ *addr_field = (uintptr_t)buf_origin;
+
+ return buf_fixed;
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ void *mem_origin;
+ void *mem_new;
+ void *mem_new_fixed;
+ uintptr_t *addr_field;
+
+ if (!ptr) {
+ return os_malloc(size);
+ }
+
+ addr_field = ptr - sizeof(uintptr_t);
+ mem_origin = (void *)(*addr_field);
+ mem_new = realloc(mem_origin, size + 8 + sizeof(uintptr_t));
+ if (!mem_new) {
+ return NULL;
+ }
+
+ if (mem_origin != mem_new) {
+ mem_new_fixed = mem_new + sizeof(uintptr_t);
+ if ((uint32)mem_new_fixed & 0x7) {
+ mem_new_fixed =
+ (void *)((uintptr_t)(mem_new + 8) & (~(uintptr_t)7));
+ }
+
+ addr_field = mem_new_fixed - sizeof(uintptr_t);
+ *addr_field = (uintptr_t)mem_new;
+
+ return mem_new_fixed;
+ }
+
+ return ptr;
+}
+
+void
+os_free(void *ptr)
+{
+ void *mem_origin;
+ uintptr_t *addr_field;
+
+ if (ptr) {
+ addr_field = ptr - sizeof(uintptr_t);
+ mem_origin = (void *)(*addr_field);
+
+ free(mem_origin);
+ }
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_memmap.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_memmap.c
new file mode 100644
index 000000000..693094a63
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_memmap.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ if (prot & MMAP_PROT_EXEC) {
+ // Memory allocation with MALLOC_CAP_EXEC will return 4-byte aligned
+ // Reserve extra 4 byte to fixup alignment and size for the pointer to
+ // the originally allocated address
+ void *buf_origin =
+ heap_caps_malloc(size + 4 + sizeof(uintptr_t), MALLOC_CAP_EXEC);
+ if (!buf_origin) {
+ return NULL;
+ }
+ void *buf_fixed = buf_origin + sizeof(void *);
+ if ((uintptr_t)buf_fixed & (uintptr_t)0x7) {
+ buf_fixed = (void *)((uintptr_t)(buf_fixed + 4) & (~(uintptr_t)7));
+ }
+
+ uintptr_t *addr_field = buf_fixed - sizeof(uintptr_t);
+ *addr_field = (uintptr_t)buf_origin;
+ return buf_fixed;
+ }
+ else {
+ return os_malloc(size);
+ }
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ // We don't need special handling of the executable allocations
+ // here, free() of esp-idf handles it properly
+ return os_free(addr);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ return 0;
+}
+
+void
+os_dcache_flush()
+{}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_platform.c
new file mode 100644
index 000000000..35b893d81
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_platform.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+ ret += vprintf(format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+ return vprintf(format, ap);
+}
+
+uint64
+os_time_get_boot_microsecond(void)
+{
+ return (uint64)esp_timer_get_time();
+}
+
+uint8 *
+os_thread_get_stack_boundary(void)
+{
+#if defined(CONFIG_FREERTOS_USE_TRACE_FACILITY)
+ TaskStatus_t pxTaskStatus;
+ vTaskGetInfo(xTaskGetCurrentTaskHandle(), &pxTaskStatus, pdTRUE, eInvalid);
+ return pxTaskStatus.pxStackBase;
+#else // !defined(CONFIG_FREERTOS_USE_TRACE_FACILITY)
+ return NULL;
+#endif
+}
+
+int
+os_usleep(uint32 usec)
+{
+ return usleep(usec);
+}
+
+/* Below parts of readv & writev are ported from Nuttx, under Apache License
+ * v2.0 */
+
+ssize_t
+readv(int fildes, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ntotal;
+ ssize_t nread;
+ size_t remaining;
+ uint8_t *buffer;
+ int i;
+
+ /* Process each entry in the struct iovec array */
+
+ for (i = 0, ntotal = 0; i < iovcnt; i++) {
+ /* Ignore zero-length reads */
+
+ if (iov[i].iov_len > 0) {
+ buffer = iov[i].iov_base;
+ remaining = iov[i].iov_len;
+
+ /* Read repeatedly as necessary to fill buffer */
+
+ do {
+ /* NOTE: read() is a cancellation point */
+
+ nread = read(fildes, buffer, remaining);
+
+ /* Check for a read error */
+
+ if (nread < 0) {
+ return nread;
+ }
+
+ /* Check for an end-of-file condition */
+
+ else if (nread == 0) {
+ return ntotal;
+ }
+
+ /* Update pointers and counts in order to handle partial
+ * buffer reads.
+ */
+
+ buffer += nread;
+ remaining -= nread;
+ ntotal += nread;
+ } while (remaining > 0);
+ }
+ }
+
+ return ntotal;
+}
+
+ssize_t
+writev(int fildes, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ntotal;
+ ssize_t nwritten;
+ size_t remaining;
+ uint8_t *buffer;
+ int i;
+
+ /* Process each entry in the struct iovec array */
+
+ for (i = 0, ntotal = 0; i < iovcnt; i++) {
+ /* Ignore zero-length writes */
+
+ if (iov[i].iov_len > 0) {
+ buffer = iov[i].iov_base;
+ remaining = iov[i].iov_len;
+
+ /* Write repeatedly as necessary to write the entire buffer */
+
+ do {
+ /* NOTE: write() is a cancellation point */
+
+ nwritten = write(fildes, buffer, remaining);
+
+ /* Check for a write error */
+
+ if (nwritten < 0) {
+ return ntotal ? ntotal : -1;
+ }
+
+ /* Update pointers and counts in order to handle partial
+ * buffer writes.
+ */
+
+ buffer += nwritten;
+ remaining -= nwritten;
+ ntotal += nwritten;
+ } while (remaining > 0);
+ }
+ }
+
+ return ntotal;
+}
+
+int
+openat(int fd, const char *path, int oflags, ...)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+fstatat(int fd, const char *path, struct stat *buf, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+mkdirat(int fd, const char *path, mode_t mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+ssize_t
+readlinkat(int fd, const char *path, char *buf, size_t bufsize)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int
+linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+renameat(int fromfd, const char *from, int tofd, const char *to)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+symlinkat(const char *target, int fd, const char *path)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+unlinkat(int fd, const char *path, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+utimensat(int fd, const char *path, const struct timespec *ts, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+DIR *
+fdopendir(int fd)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 2)
+int
+ftruncate(int fd, off_t length)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+int
+futimens(int fd, const struct timespec *times)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+nanosleep(const struct timespec *req, struct timespec *rem)
+{
+ errno = ENOSYS;
+ return -1;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_socket.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_socket.c
new file mode 100644
index 000000000..9f441b712
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_socket.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#include <arpa/inet.h>
+
+static void
+textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr_in *out)
+{
+ assert(textual);
+
+ out->sin_family = AF_INET;
+ out->sin_port = htons(port);
+ out->sin_addr.s_addr = inet_addr(textual);
+}
+
+static int
+sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen,
+ bh_sockaddr_t *bh_sockaddr)
+{
+ switch (sockaddr->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
+
+ assert(socklen >= sizeof(struct sockaddr_in));
+
+ bh_sockaddr->port = ntohs(addr->sin_port);
+ bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
+ bh_sockaddr->is_ipv4 = true;
+ return BHT_OK;
+ }
+ default:
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+ }
+}
+
+int
+os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
+{
+ if (!sock) {
+ return BHT_ERROR;
+ }
+
+ if (is_tcp) {
+ *sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ }
+ else {
+ *sock = socket(AF_INET, SOCK_DGRAM, 0);
+ }
+
+ return (*sock == -1) ? BHT_ERROR : BHT_OK;
+}
+
+int
+os_socket_bind(bh_socket_t socket, const char *host, int *port)
+{
+ struct sockaddr_in addr;
+ socklen_t socklen;
+ int ret;
+
+ assert(host);
+ assert(port);
+
+ addr.sin_addr.s_addr = inet_addr(host);
+ addr.sin_port = htons(*port);
+ addr.sin_family = AF_INET;
+
+ ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret < 0) {
+ goto fail;
+ }
+
+ socklen = sizeof(addr);
+ if (getsockname(socket, (struct sockaddr *)&addr, &socklen) == -1) {
+ goto fail;
+ }
+
+ *port = ntohs(addr.sin_port);
+
+ return BHT_OK;
+
+fail:
+ return BHT_ERROR;
+}
+
+int
+os_socket_settimeout(bh_socket_t socket, uint64 timeout_us)
+{
+ struct timeval tv;
+ tv.tv_sec = timeout_us / 1000000UL;
+ tv.tv_usec = timeout_us % 1000000UL;
+
+ if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv,
+ sizeof(tv))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_listen(bh_socket_t socket, int max_client)
+{
+ if (listen(socket, max_client) != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
+ unsigned int *addrlen)
+{
+ struct sockaddr addr_tmp;
+ socklen_t len = sizeof(struct sockaddr);
+
+ *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
+
+ if (*sock < 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_connect(bh_socket_t socket, const char *addr, int port)
+{
+ struct sockaddr_in addr_in = { 0 };
+ socklen_t addr_len = sizeof(struct sockaddr_in);
+ int ret = 0;
+
+ textual_addr_to_sockaddr(addr, port, &addr_in);
+
+ ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
+ if (ret == -1) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
+{
+ return recv(socket, buf, len, 0);
+}
+
+int
+os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
+{
+ return send(socket, buf, len, 0);
+}
+
+int
+os_socket_close(bh_socket_t socket)
+{
+ close(socket);
+ return BHT_OK;
+}
+
+int
+os_socket_shutdown(bh_socket_t socket)
+{
+ shutdown(socket, O_RDWR);
+ return BHT_OK;
+}
+
+int
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
+{
+ if (!cp)
+ return BHT_ERROR;
+
+ if (is_ipv4) {
+ if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
+ return BHT_ERROR;
+ }
+ /* Note: ntohl(INADDR_NONE) == INADDR_NONE */
+ out->ipv4 = ntohl(out->ipv4);
+ }
+ else {
+ if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
+ return BHT_ERROR;
+ }
+ for (int i = 0; i < 8; i++) {
+ out->ipv6[i] = ntohs(out->ipv6[i]);
+ }
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+
+ if (getpeername(socket, (struct sockaddr *)&addr, &addr_len) == -1) {
+ return BHT_ERROR;
+ }
+
+ return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr, addr_len,
+ sockaddr);
+}
+
+int
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+
+ if (getsockname(socket, (struct sockaddr *)&addr, &addr_len) == -1) {
+ return BHT_ERROR;
+ }
+
+ return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr, addr_len,
+ sockaddr);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_thread.c
new file mode 100644
index 000000000..637cd4177
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/espidf_thread.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+typedef struct {
+ thread_start_routine_t start;
+ void *arg;
+} thread_wrapper_arg;
+
+static void *
+os_thread_wrapper(void *arg)
+{
+ thread_wrapper_arg *targ = arg;
+ thread_start_routine_t start_func = targ->start;
+ void *thread_arg = targ->arg;
+
+#if 0
+ os_printf("THREAD CREATED %jx\n", (uintmax_t)(uintptr_t)pthread_self());
+#endif
+ BH_FREE(targ);
+ start_func(thread_arg);
+ return NULL;
+}
+
+korp_tid
+os_self_thread(void)
+{
+ /* only allowed if this is a thread, xTaskCreate is not enough look at
+ * product_mini for how to use this*/
+ return pthread_self();
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ return pthread_mutex_init(mutex, NULL);
+}
+
+int
+os_recursive_mutex_init(korp_mutex *mutex)
+{
+ int ret;
+
+ pthread_mutexattr_t mattr;
+
+ assert(mutex);
+ ret = pthread_mutexattr_init(&mattr);
+ if (ret)
+ return BHT_ERROR;
+
+ pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
+ ret = pthread_mutex_init(mutex, &mattr);
+ pthread_mutexattr_destroy(&mattr);
+
+ return ret == 0 ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ return pthread_mutex_destroy(mutex);
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ return pthread_mutex_lock(mutex);
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ return pthread_mutex_unlock(mutex);
+}
+
+int
+os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ pthread_attr_t tattr;
+ thread_wrapper_arg *targ;
+
+ assert(stack_size > 0);
+ assert(tid);
+ assert(start);
+
+ pthread_attr_init(&tattr);
+ pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
+ if (pthread_attr_setstacksize(&tattr, stack_size) != 0) {
+ os_printf("Invalid thread stack size %u. Min stack size = %u",
+ stack_size, PTHREAD_STACK_MIN);
+ pthread_attr_destroy(&tattr);
+ return BHT_ERROR;
+ }
+
+ targ = (thread_wrapper_arg *)BH_MALLOC(sizeof(*targ));
+ if (!targ) {
+ pthread_attr_destroy(&tattr);
+ return BHT_ERROR;
+ }
+
+ targ->start = start;
+ targ->arg = arg;
+
+ if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) {
+ pthread_attr_destroy(&tattr);
+ os_free(targ);
+ return BHT_ERROR;
+ }
+
+ pthread_attr_destroy(&tattr);
+ return BHT_OK;
+}
+
+int
+os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+int
+os_thread_join(korp_tid thread, void **retval)
+{
+ return pthread_join(thread, retval);
+}
+
+int
+os_thread_detach(korp_tid tid)
+{
+ return pthread_detach(tid);
+}
+
+void
+os_thread_exit(void *retval)
+{
+ pthread_exit(retval);
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ return pthread_cond_init(cond, NULL);
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ return pthread_cond_destroy(cond);
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return pthread_cond_wait(cond, mutex);
+}
+
+static void
+msec_nsec_to_abstime(struct timespec *ts, uint64 usec)
+{
+ struct timeval tv;
+ time_t tv_sec_new;
+ long int tv_nsec_new;
+
+ gettimeofday(&tv, NULL);
+
+ tv_sec_new = (time_t)(tv.tv_sec + usec / 1000000);
+ if (tv_sec_new >= tv.tv_sec) {
+ ts->tv_sec = tv_sec_new;
+ }
+ else {
+ /* integer overflow */
+ ts->tv_sec = BH_TIME_T_MAX;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+
+ tv_nsec_new = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000);
+ if (tv.tv_usec * 1000 >= tv.tv_usec && tv_nsec_new >= tv.tv_usec * 1000) {
+ ts->tv_nsec = tv_nsec_new;
+ }
+ else {
+ /* integer overflow */
+ ts->tv_nsec = LONG_MAX;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+
+ if (ts->tv_nsec >= 1000000000L && ts->tv_sec < BH_TIME_T_MAX) {
+ ts->tv_sec++;
+ ts->tv_nsec -= 1000000000L;
+ }
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ int ret;
+ struct timespec abstime;
+
+ if (useconds == BHT_WAIT_FOREVER)
+ ret = pthread_cond_wait(cond, mutex);
+ else {
+ msec_nsec_to_abstime(&abstime, useconds);
+ ret = pthread_cond_timedwait(cond, mutex, &abstime);
+ }
+
+ if (ret != BHT_OK && ret != ETIMEDOUT)
+ return BHT_ERROR;
+
+ return ret;
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ return pthread_cond_signal(cond);
+}
+
+int
+os_cond_broadcast(korp_cond *cond)
+{
+ return pthread_cond_broadcast(cond);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/platform_internal.h
new file mode 100644
index 000000000..81304ea80
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/platform_internal.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <dirent.h>
+
+#include "esp_pthread.h"
+#include "esp_timer.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_ESP_IDF
+#define BH_PLATFORM_ESP_IDF
+#endif
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef unsigned int korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 5
+
+/* Special value for tv_nsec field of timespec */
+
+#define UTIME_NOW ((1l << 30) - 1l)
+#ifndef __cplusplus
+#define UTIME_OMIT ((1l << 30) - 2l)
+#endif
+
+#ifdef DT_UNKNOWN
+#undef DT_UNKNOWN
+#endif
+
+#ifdef DT_REG
+#undef DT_REG
+#endif
+
+#ifdef DT_DIR
+#undef DT_DIR
+#endif
+
+/* Below parts of d_type define are ported from Nuttx, under Apache License v2.0
+ */
+
+/* File type code for the d_type field in dirent structure.
+ * Note that because of the simplified filesystem organization of the NuttX,
+ * top-level, pseudo-file system, an inode can be BOTH a file and a directory
+ */
+
+#define DTYPE_UNKNOWN 0
+#define DTYPE_FIFO 1
+#define DTYPE_CHR 2
+#define DTYPE_SEM 3
+#define DTYPE_DIRECTORY 4
+#define DTYPE_MQ 5
+#define DTYPE_BLK 6
+#define DTYPE_SHM 7
+#define DTYPE_FILE 8
+#define DTYPE_MTD 9
+#define DTYPE_LINK 10
+#define DTYPE_SOCK 12
+
+/* The d_type field of the dirent structure is not specified by POSIX. It
+ * is a non-standard, 4.5BSD extension that is implemented by most OSs. A
+ * POSIX compliant OS may not implement the d_type field at all. Many OS's
+ * (including glibc) may use the following alternative naming for the file
+ * type names:
+ */
+
+#define DT_UNKNOWN DTYPE_UNKNOWN
+#define DT_FIFO DTYPE_FIFO
+#define DT_CHR DTYPE_CHR
+#define DT_SEM DTYPE_SEM
+#define DT_DIR DTYPE_DIRECTORY
+#define DT_MQ DTYPE_MQ
+#define DT_BLK DTYPE_BLK
+#define DT_SHM DTYPE_SHM
+#define DT_REG DTYPE_FILE
+#define DT_MTD DTYPE_MTD
+#define DT_LNK DTYPE_LINK
+#define DT_SOCK DTYPE_SOCK
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/shared_platform.cmake
new file mode 100644
index 000000000..13bc45dcb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/esp-idf/shared_platform.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_ESP_IDF)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_init.c
new file mode 100644
index 000000000..2aae13fa1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_init.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+#ifndef BH_VPRINTF
+ ret += vprintf(format, ap);
+#else
+ ret += BH_VPRINTF(format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+ return vprintf(format, ap);
+#else
+ return BH_VPRINTF(format, ap);
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_internal.h
new file mode 100644
index 000000000..7b4789c99
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/platform_internal.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sched.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_FREEBSD
+#define BH_PLATFORM_FREEBSD
+#endif
+
+#define BH_HAS_DLFCN 1
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define os_thread_local_attribute __thread
+
+#define bh_socket_t int
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#define os_alloca alloca
+
+#define os_getpagesize getpagesize
+
+typedef void (*os_signal_handler)(void *sig_addr);
+
+int
+os_thread_signal_init(os_signal_handler handler);
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+void
+os_signal_unmask();
+
+void
+os_sigreturn();
+#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/shared_platform.cmake
new file mode 100644
index 000000000..12583fc63
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/freebsd/shared_platform.cmake
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_FREEBSD)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_extension.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_extension.h
new file mode 100644
index 000000000..94fe16ea3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_extension.h
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef PLATFORM_API_EXTENSION_H
+#define PLATFORM_API_EXTENSION_H
+
+#include "platform_common.h"
+/**
+ * The related data structures should be defined
+ * in platform_internal.h
+ **/
+#include "platform_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************
+ * *
+ * Extension interface *
+ * *
+ ***************************************************/
+
+/****************************************************
+ * Section 1 *
+ * Multi thread support *
+ ****************************************************/
+
+/**
+ * NOTES:
+ * 1. If you are building VM core only, it must be implemented to
+ * enable multi-thread support, otherwise no need to implement it
+ * 2. To build the app-mgr and app-framework, you must implement it
+ */
+
+/**
+ * Creates a thread
+ *
+ * @param p_tid [OUTPUT] the pointer of tid
+ * @param start main routine of the thread
+ * @param arg argument passed to main routine
+ * @param stack_size bytes of stack size
+ *
+ * @return 0 if success.
+ */
+int
+os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size);
+
+/**
+ * Creates a thread with priority
+ *
+ * @param p_tid [OUTPUT] the pointer of tid
+ * @param start main routine of the thread
+ * @param arg argument passed to main routine
+ * @param stack_size bytes of stack size
+ * @param prio the priority
+ *
+ * @return 0 if success.
+ */
+int
+os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio);
+
+/**
+ * Waits for the thread specified by thread to terminate
+ *
+ * @param thread the thread to wait
+ * @param retval if not NULL, output the exit status of the terminated thread
+ *
+ * @return return 0 if success
+ */
+int
+os_thread_join(korp_tid thread, void **retval);
+
+/**
+ * Detach the thread specified by thread
+ *
+ * @param thread the thread to detach
+ *
+ * @return return 0 if success
+ */
+int os_thread_detach(korp_tid);
+
+/**
+ * Exit current thread
+ *
+ * @param retval the return value of the current thread
+ */
+void
+os_thread_exit(void *retval);
+
+/* Try to define os_atomic_thread_fence if it isn't defined in
+ platform's platform_internal.h */
+#ifndef os_atomic_thread_fence
+
+#if !defined(__GNUC_PREREQ) && (defined(__GNUC__) || defined(__GNUG__)) \
+ && !defined(__clang__) && defined(__GNUC_MINOR__)
+#define __GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#endif
+
+/* Clang's __GNUC_PREREQ macro has a different meaning than GCC one,
+ so we have to handle this case specially */
+#if defined(__clang__)
+/* Clang provides stdatomic.h since 3.6.0
+ See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+#define BH_HAS_STD_ATOMIC
+#endif
+#elif defined(__GNUC_PREREQ)
+/* Even though older versions of GCC support C11, atomics were
+ not implemented until 4.9. See
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */
+#if __GNUC_PREREQ(4, 9)
+#define BH_HAS_STD_ATOMIC
+#elif __GNUC_PREREQ(4, 7)
+#define os_memory_order_acquire __ATOMIC_ACQUIRE
+#define os_memory_order_release __ATOMIC_RELEASE
+#define os_memory_order_seq_cst __ATOMIC_SEQ_CST
+#define os_atomic_thread_fence __atomic_thread_fence
+#endif /* end of __GNUC_PREREQ(4, 9) */
+#endif /* end of defined(__GNUC_PREREQ) */
+
+#if defined(BH_HAS_STD_ATOMIC) && !defined(__cplusplus)
+#include <stdatomic.h>
+#define os_memory_order_acquire memory_order_acquire
+#define os_memory_order_release memory_order_release
+#define os_memory_order_seq_cst memory_order_seq_cst
+#define os_atomic_thread_fence atomic_thread_fence
+#endif
+
+#endif /* end of os_atomic_thread_fence */
+
+/**
+ * Initialize current thread environment if current thread
+ * is created by developer but not runtime
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_thread_env_init(void);
+
+/**
+ * Destroy current thread environment
+ */
+void
+os_thread_env_destroy(void);
+
+/**
+ * Whether the thread environment is initialized
+ */
+bool
+os_thread_env_inited(void);
+
+/**
+ * Suspend execution of the calling thread for (at least)
+ * usec microseconds
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_usleep(uint32 usec);
+
+/**
+ * Creates a recursive mutex
+ *
+ * @param mutex [OUTPUT] pointer to mutex initialized.
+ *
+ * @return 0 if success
+ */
+int
+os_recursive_mutex_init(korp_mutex *mutex);
+
+/**
+ * This function creates a condition variable
+ *
+ * @param cond [OUTPUT] pointer to condition variable
+ *
+ * @return 0 if success
+ */
+int
+os_cond_init(korp_cond *cond);
+
+/**
+ * This function destroys condition variable
+ *
+ * @param cond pointer to condition variable
+ *
+ * @return 0 if success
+ */
+int
+os_cond_destroy(korp_cond *cond);
+
+/**
+ * Wait a condition variable.
+ *
+ * @param cond pointer to condition variable
+ * @param mutex pointer to mutex to protect the condition variable
+ *
+ * @return 0 if success
+ */
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex);
+
+/**
+ * Wait a condition varible or return if time specified passes.
+ *
+ * @param cond pointer to condition variable
+ * @param mutex pointer to mutex to protect the condition variable
+ * @param useconds microseconds to wait
+ *
+ * @return 0 if success
+ */
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds);
+
+/**
+ * Signals the condition variable
+ *
+ * @param cond condition variable
+ *
+ * @return 0 if success
+ */
+int
+os_cond_signal(korp_cond *cond);
+
+/**
+ * Broadcast the condition variable
+ *
+ * @param cond condition variable
+ *
+ * @return 0 if success
+ */
+int
+os_cond_broadcast(korp_cond *cond);
+
+/**
+ * Creates a new POSIX-like semaphore or opens an existing
+ * semaphore. The semaphore is identified by name. For details of
+ * the construction of name, please refer to
+ * https://man7.org/linux/man-pages/man3/sem_open.3.html.
+ *
+ * @param name semaphore name
+ * @param oflasg specifies flags that control the operation of the call
+ * @param mode permission flags
+ * @param val initial value of the named semaphore.
+ *
+ * @return korp_sem * if success, NULL otherwise
+ */
+korp_sem *
+os_sem_open(const char *name, int oflags, int mode, int val);
+
+/**
+ * Closes the named semaphore referred to by sem,
+ * allowing any resources that the system has allocated to the
+ * calling process for this semaphore to be freed.
+ *
+ * @param sem
+ *
+ * @return 0 if success
+ */
+int
+os_sem_close(korp_sem *sem);
+
+/**
+ * Decrements (locks) the semaphore pointed to by sem.
+ * If the semaphore's value is greater than zero, then the decrement
+ * proceeds, and the function returns, immediately. If the
+ * semaphore currently has the value zero, then the call blocks
+ * until either it becomes possible to perform the decrement (i.e.,
+ * the semaphore value rises above zero), or a signal handler
+ * interrupts the call.
+ *
+ * @return 0 if success
+ */
+int
+os_sem_wait(korp_sem *sem);
+
+/**
+ * Is the same as sem_wait(), except that if the
+ * decrement cannot be immediately performed, then call returns an
+ * error (errno set to EAGAIN) instead of blocking.
+ *
+ * @return 0 if success
+ */
+int
+os_sem_trywait(korp_sem *sem);
+
+/**
+ * Increments (unlocks) the semaphore pointed to by sem.
+ * If the semaphore's value consequently becomes greater than zero,
+ * then another process or thread blocked in a sem_wait(3) call will
+ * be woken up and proceed to lock the semaphore.
+ *
+ * @return 0 if success
+ */
+int
+os_sem_post(korp_sem *sem);
+
+/**
+ * Places the current value of the semaphore pointed
+ * to sem into the integer pointed to by sval.
+ *
+ * @return 0 if success
+ */
+int
+os_sem_getvalue(korp_sem *sem, int *sval);
+
+/**
+ * Remove the named semaphore referred to by name.
+ * The semaphore name is removed immediately. The semaphore is
+ * destroyed once all other processes that have the semaphore open
+ * close it.
+ *
+ * @param name semaphore name
+ *
+ * @return 0 if success
+ */
+int
+os_sem_unlink(const char *name);
+
+/****************************************************
+ * Section 2 *
+ * Socket support *
+ ****************************************************/
+
+/**
+ * NOTES:
+ * Socket APIs are required by source debugging feature.
+ * If you don't need source debugging feature, then no
+ * need to implement these APIs
+ */
+
+typedef union {
+ uint32 ipv4;
+ uint16 ipv6[8];
+ uint8 data[1];
+} bh_ip_addr_buffer_t;
+
+typedef struct {
+ bh_ip_addr_buffer_t addr_bufer;
+ uint16 port;
+ bool is_ipv4;
+} bh_sockaddr_t;
+
+/**
+ * Create a socket
+ *
+ * @param sock [OUTPUT] the pointer of socket
+ * @param is_ipv4 true for IPv4, false for IPv6
+ * @param is_tcp true for tcp, false for udp
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp);
+
+/**
+ * Assign the address and port to the socket
+ *
+ * @param socket the socket to bind
+ * @param addr the ip address, only IPv4 supported currently
+ * @param port [INPUT/OUTPUT] the port number, if the value is 0,
+ * it will use a port assigned by OS. On return it will
+ * contain the actual bound port number
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_bind(bh_socket_t socket, const char *addr, int *port);
+
+/**
+ * Set timeout for the given socket
+ *
+ * @param socket the socket to set timeout
+ * @param timeout_us timeout in microseconds
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_settimeout(bh_socket_t socket, uint64 timeout_us);
+
+/**
+ * Make the socket as a passive socket to accept incoming connection requests
+ *
+ * @param socket the socket to listen
+ * @param max_client maximum clients
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_listen(bh_socket_t socket, int max_client);
+
+/**
+ * Accept an incoming connection
+ *
+ * @param server_sock the socket to accept new connections
+ * @param sock [OUTPUT] the connected socket
+ * @param addr [OUTPUT] the address of the peer socket. If addr is NULL,
+ * nothing is filled in, and addrlen will not be used
+ * @param addrlen [INPUT/OUTPUT] the size (in bytes) of the structure
+ * pointed to by addr, on return it will contain the actual
+ * size of the peer address
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
+ unsigned int *addrlen);
+
+/**
+ * initiate a connection on a socket
+ *
+ * @param socket the socket to connect with
+ * @param addr the ip address, only IPv4 supported currently
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_connect(bh_socket_t socket, const char *addr, int port);
+
+/**
+ * Blocking receive message from a socket.
+ *
+ * @param socket the socket to receive message from
+ * @param buf the buffer to store the data
+ * @param len length of the buffer, this API does not guarantee that
+ * [len] bytes are received
+ *
+ * @return number of bytes received if success, -1 otherwise
+ */
+int
+os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
+
+/**
+ * Blocking receive message from a socket.
+ *
+ * @param socket the socket to send message
+ * @param buf the buffer to store the data
+ * @param len length of the buffer, this API does not guarantee that
+ * [len] bytes are received
+ * @param flags control the operation
+ * @param src_addr source address
+ *
+ * @return number of bytes sent if success, -1 otherwise
+ */
+int
+os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
+ bh_sockaddr_t *src_addr);
+
+/**
+ * Blocking send message on a socket
+ *
+ * @param socket the socket to send message
+ * @param buf the buffer of data to be sent
+ * @param len length of the buffer
+ *
+ * @return number of bytes sent if success, -1 otherwise
+ */
+int
+os_socket_send(bh_socket_t socket, const void *buf, unsigned int len);
+
+/**
+ * Blocking send message on a socket to the target address
+ *
+ * @param socket the socket to send message
+ * @param buf the buffer of data to be sent
+ * @param len length of the buffer
+ * @param flags control the operation
+ * @param dest_addr target address
+ *
+ * @return number of bytes sent if success, -1 otherwise
+ */
+int
+os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
+ int flags, const bh_sockaddr_t *dest_addr);
+
+/**
+ * Close a socket
+ *
+ * @param socket the socket to be closed
+ *
+ * @return always return 0
+ */
+int
+os_socket_close(bh_socket_t socket);
+
+/**
+ * Shutdown a socket
+ *
+ * @param socket the socket to be shutdown
+ *
+ * @return always return 0
+ */
+int
+os_socket_shutdown(bh_socket_t socket);
+
+/**
+ * converts cp into a number in host byte order suitable for use as
+ * an Internet network address
+ *
+ * @param is_ipv4 a flag that indicates whether the string is an IPv4 or
+ * IPv6 address
+ *
+ * @param cp a string in IPv4 numbers-and-dots notation or IPv6
+ * numbers-and-colons notation
+ *
+ * @param out an output buffer to store binary address
+ *
+ * @return On success, the function returns 0.
+ * If the input is invalid, -1 is returned
+ */
+int
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out);
+
+typedef struct {
+ bh_sockaddr_t sockaddr;
+ uint8_t is_tcp;
+} bh_addr_info_t;
+
+/**
+ * Resolve a host a hostname and a service to one or more IP addresses
+ *
+ * @param host a host to resolve
+ *
+ * @param service a service to find a port for
+ *
+ * @param hint_is_tcp an optional flag that determines a preferred socket type
+ (TCP or UDP).
+ *
+ * @param hint_is_ipv4 an optional flag that determines a preferred address
+ family (IPv4 or IPv6)
+ *
+ * @param addr_info a buffer for resolved addresses
+ *
+ * @param addr_info_size a size of the buffer for resolved addresses
+
+ * @param max_info_size a maximum number of addresses available (can be bigger
+ or smaller than buffer size)
+
+ * @return On success, the function returns 0; otherwise, it returns -1
+ */
+int
+os_socket_addr_resolve(const char *host, const char *service,
+ uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
+ bh_addr_info_t *addr_info, size_t addr_info_size,
+ size_t *max_info_size);
+
+/**
+ * Returns an binary address and a port of the local socket
+ *
+ * @param socket the local socket
+ *
+ * @param sockaddr a buffer for storing the address
+ *
+ * @return On success, returns 0; otherwise, it returns -1.
+ */
+int
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr);
+
+/**
+ * Returns an binary address and a port of the remote socket
+ *
+ * @param socket the remote socket
+ *
+ * @param sockaddr a buffer for storing the address
+ *
+ * @return On success, returns 0; otherwise, it returns -1.
+ */
+int
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr);
+
+/**
+ * Set the maximum send buffer size.
+ *
+ * @param socket the socket to set
+ * @param bufsiz requested kernel buffer size
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz);
+
+/**
+ * Get the maximum send buffer size.
+ *
+ * @param socket the socket to set
+ * @param bufsiz the returned kernel buffer size
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz);
+
+/**
+ * Set the maximum receive buffer size.
+ *
+ * @param socket the socket to set
+ * @param bufsiz requested kernel buffer size
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz);
+
+/**
+ * Get the maximum receive buffer size.
+ *
+ * @param socket the socket to set
+ * @param bufsiz the returned kernel buffer size
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz);
+
+/**
+ * Enable sending of keep-alive messages on connection-oriented sockets
+ *
+ * @param socket the socket to set the flag
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get if sending of keep-alive messages on connection-oriented sockets is
+ * enabled
+ *
+ * @param socket the socket to check
+ * @param is_enabled 1 if enabled or 0 if disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Set the send timeout until reporting an error
+ *
+ * @param socket the socket to set
+ * @param time_us microseconds until timeout
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us);
+
+/**
+ * Get the send timeout until reporting an error
+ *
+ * @param socket the socket to set
+ * @param time_us the returned microseconds until timeout
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us);
+
+/**
+ * Set the recv timeout until reporting an error
+ *
+ * @param socket the socket to set
+ * @param time_us microseconds until timeout
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us);
+
+/**
+ * Get the recv timeout until reporting an error
+ *
+ * @param socket the socket to set
+ * @param time_us the returned microseconds until timeout
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us);
+
+/**
+ * Enable re-use of local addresses
+ *
+ * @param socket the socket to set
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get whether re-use of local addresses is enabled
+ *
+ * @param socket the socket to set
+ * @param is_enabled 1 for enabled or 0 for disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Enable re-use of local ports
+ *
+ * @param socket the socket to set
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get whether re-use of local ports is enabled
+ *
+ * @param socket the socket to set
+ * @param is_enabled 1 for enabled or 0 for disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Set the linger options for the given socket
+ *
+ * @param socket the socket to set
+ * @param is_enabled whether linger is enabled
+ * @param linger_s linger time (seconds)
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s);
+
+/**
+ * Get the linger options for the given socket
+ *
+ * @param socket the socket to get
+ * @param is_enabled whether linger is enabled
+ * @param linger_s linger time (seconds)
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s);
+
+/**
+ * Set no delay TCP
+ * If set, disable the Nagle algorithm.
+ * This means that segments are always sent as soon as possible,
+ * even if there is only a small amount of data
+ *
+ * @param socket the socket to set the flag
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get no delay TCP
+ * If set, disable the Nagle algorithm.
+ * This means that segments are always sent as soon as possible,
+ * even if there is only a small amount of data
+ *
+ * @param socket the socket to check
+ * @param is_enabled 1 if enabled or 0 if disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Enable/Disable tcp quickack mode
+ * In quickack mode, acks are sent immediately, rather than delayed if needed in
+ * accordance to normal TCP operation
+ *
+ * @param socket the socket to set the flag
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Enable/Disable tcp quickack mode
+ * In quickack mode, acks are sent immediately, rather than delayed if needed in
+ * accordance to normal TCP operation
+ *
+ * @param socket the socket to check
+ * @param is_enabled 1 if enabled or 0 if disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Set the time the connection needs to remain idle before sending keepalive
+ * probes
+ *
+ * @param socket the socket to set
+ * @param time_s seconds until keepalive probes are sent
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32_t time_s);
+
+/**
+ * Gets the time the connection needs to remain idle before sending keepalive
+ * probes
+ *
+ * @param socket the socket to check
+ * @param time_s seconds until keepalive probes are sent
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32_t *time_s);
+
+/**
+ * Set the time between individual keepalive probes
+ *
+ * @param socket the socket to set
+ * @param time_us seconds between individual keepalive probes
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32_t time_s);
+
+/**
+ * Get the time between individual keepalive probes
+ *
+ * @param socket the socket to get
+ * @param time_s seconds between individual keepalive probes
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32_t *time_s);
+
+/**
+ * Set use of TCP Fast Open
+ *
+ * @param socket the socket to set
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get whether use of TCP Fast Open is enabled
+ *
+ * @param socket the socket to get
+ * @param is_enabled 1 to enabled or 0 to disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Set enable or disable IPv4 or IPv6 multicast loopback.
+ *
+ * @param socket the socket to set
+ * @param ipv6 true to set ipv6 loopback or false for ipv4
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled);
+
+/**
+ * Get enable or disable IPv4 or IPv6 multicast loopback.
+ *
+ * @param socket the socket to check
+ * @param ipv6 true to set ipv6 loopback or false for ipv4
+ * @param is_enabled 1 for enabled or 0 for disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6,
+ bool *is_enabled);
+
+/**
+ * Add membership to a group
+ *
+ * @param socket the socket to add membership to
+ * @param imr_multiaddr the group multicast address (IPv4 or IPv6)
+ * @param imr_interface the interface to join on
+ * @param is_ipv6 whether the imr_multiaddr is IPv4 or IPv6 (true for IPv6)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_ip_add_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6);
+
+/**
+ * Drop membership of a group
+ *
+ * @param socket the socket to drop membership to
+ * @param imr_multiaddr the group multicast address (IPv4 or IPv6)
+ * @param imr_interface the interface to join on
+ * @param is_ipv6 whether the imr_multiaddr is IPv4 or IPv6 (true for IPv6)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_ip_drop_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6);
+
+/**
+ * Set the current time-to-live field that is
+ * used in every packet sent from this socket.
+ * @param socket the socket to set the flag
+ * @param ttl_s time to live (seconds)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s);
+
+/**
+ * Retrieve the current time-to-live field that is
+ * used in every packet sent from this socket.
+ * @param socket the socket to set the flag
+ * @param ttl_s time to live (seconds)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s);
+
+/**
+ * Set the time-to-live value of outgoing multicast
+ * packets for this socket
+ * @param socket the socket to set the flag
+ * @param ttl_s time to live (seconds)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s);
+
+/**
+ * Read the time-to-live value of outgoing multicast
+ * packets for this socket
+ * @param socket the socket to set the flag
+ * @param ttl_s time to live (seconds)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s);
+
+/**
+ * Restrict to sending and receiving IPv6 packets only
+ *
+ * @param socket the socket to set
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get whether only sending and receiving IPv6 packets
+ *
+ * @param socket the socket to check
+ * @param is_enabled 1 for enabled or 0 for disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Set whether broadcast is enabled
+ * When enabled, datagram sockets are allowed
+ * to send packets to a broadcast address.
+ *
+ * @param socket the socket to set the flag
+ * @param is_enabled 1 to enable or 0 to disable
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_set_broadcast(bh_socket_t socket, bool is_enabled);
+
+/**
+ * Get whether broadcast is enabled
+ * When enabled, datagram sockets are allowed
+ * to send packets to a broadcast address.
+ *
+ * @param socket the socket to check
+ * @param is_enabled 1 if enabled or 0 if disabled
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled);
+
+/**
+ * Dump memory information of the current process
+ * It may have variant implementations in different platforms
+ *
+ * @param out the output buffer. It is for sure the return content
+ * is a c-string which ends up with '\0'
+ * @param size the size of the output buffer
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int
+os_dumps_proc_mem_info(char *out, unsigned int size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef PLATFORM_API_EXTENSION_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_vmcore.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_vmcore.h
new file mode 100644
index 000000000..c2f03c9e5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_api_vmcore.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_API_VMCORE_H
+#define _PLATFORM_API_VMCORE_H
+
+#include "platform_common.h"
+#include "platform_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************
+ * Section 1 *
+ * Interfaces required by the runtime *
+ ****************************************************/
+
+/**
+ * Initialize the platform internal resources if needed,
+ * this function is called by wasm_runtime_init() and
+ * wasm_runtime_full_init()
+ *
+ * @return 0 if success
+ */
+int
+bh_platform_init(void);
+
+/**
+ * Destroy the platform internal resources if needed,
+ * this function is called by wasm_runtime_destroy()
+ */
+void
+bh_platform_destroy(void);
+
+/**
+ ******** memory allocator APIs **********
+ */
+
+void *
+os_malloc(unsigned size);
+
+void *
+os_realloc(void *ptr, unsigned size);
+
+void
+os_free(void *ptr);
+
+/**
+ * Note: the above APIs can simply return NULL if wasm runtime
+ * isn't initialized with Alloc_With_System_Allocator.
+ * Refer to wasm_runtime_full_init().
+ */
+
+int
+os_printf(const char *format, ...);
+
+int
+os_vprintf(const char *format, va_list ap);
+
+/**
+ * Get microseconds after boot.
+ */
+uint64
+os_time_get_boot_microsecond(void);
+
+/**
+ * Get current thread id.
+ * Implementation optional: Used by runtime for logging only.
+ */
+korp_tid
+os_self_thread(void);
+
+/**
+ * Get current thread's stack boundary address, used for runtime
+ * to check the native stack overflow. Return NULL if it is not
+ * easy to implement, but may have potential issue.
+ */
+uint8 *
+os_thread_get_stack_boundary(void);
+
+/**
+ ************** mutext APIs ***********
+ * vmcore: Not required until pthread is supported by runtime
+ * app-mgr: Must be implemented
+ */
+
+int
+os_mutex_init(korp_mutex *mutex);
+
+int
+os_mutex_destroy(korp_mutex *mutex);
+
+int
+os_mutex_lock(korp_mutex *mutex);
+
+int
+os_mutex_unlock(korp_mutex *mutex);
+
+/**************************************************
+ * Section 2 *
+ * APIs required by WAMR AOT *
+ **************************************************/
+
+/* Memory map modes */
+enum {
+ MMAP_PROT_NONE = 0,
+ MMAP_PROT_READ = 1,
+ MMAP_PROT_WRITE = 2,
+ MMAP_PROT_EXEC = 4
+};
+
+/* Memory map 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 *
+os_mmap(void *hint, size_t size, int prot, int flags);
+void
+os_munmap(void *addr, size_t size);
+int
+os_mprotect(void *addr, size_t size, int prot);
+
+/**
+ * Flush cpu data cache, in some CPUs, after applying relocation to the
+ * AOT code, the code may haven't been written back to the cpu data cache,
+ * which may cause unexpected behaviour when executing the AOT code.
+ * Implement this function if required, or just leave it empty.
+ */
+void
+os_dcache_flush(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef _PLATFORM_API_VMCORE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_common.h
new file mode 100644
index 000000000..28001af74
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/include/platform_common.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_COMMON_H
+#define _PLATFORM_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "platform_internal.h"
+#include "../../../config.h"
+
+#define BH_MAX_THREAD 32
+
+#define BHT_ERROR (-1)
+#define BHT_TIMED_OUT (1)
+#define BHT_OK (0)
+
+#define BHT_WAIT_FOREVER ((uint64)-1LL)
+
+#define BH_KB (1024)
+#define BH_MB ((BH_KB)*1024)
+#define BH_GB ((BH_MB)*1024)
+
+#ifndef BH_MALLOC
+#define BH_MALLOC os_malloc
+#endif
+
+#ifndef BH_FREE
+#define BH_FREE os_free
+#endif
+
+#ifndef BH_TIME_T_MAX
+#define BH_TIME_T_MAX LONG_MAX
+#endif
+
+#if defined(_MSC_BUILD)
+#if defined(COMPILING_WASM_RUNTIME_API)
+__declspec(dllexport) void *BH_MALLOC(unsigned int size);
+__declspec(dllexport) void BH_FREE(void *ptr);
+#else
+__declspec(dllimport) void *BH_MALLOC(unsigned int size);
+__declspec(dllimport) void BH_FREE(void *ptr);
+#endif
+#else
+void *
+BH_MALLOC(unsigned int size);
+void
+BH_FREE(void *ptr);
+#endif
+
+#if defined(BH_VPRINTF)
+#if defined(MSVC)
+__declspec(dllimport) int BH_VPRINTF(const char *format, va_list ap);
+#else
+int
+BH_VPRINTF(const char *format, va_list ap);
+#endif
+#endif
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+#if !defined(BH_HAS_DLFCN)
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
+#define BH_HAS_DLFCN 1
+#else
+#define BH_HAS_DLFCN 0
+#endif
+#endif
+
+#ifndef __cplusplus
+
+#ifndef true
+#define true 1
+#endif
+
+#ifndef false
+#define false 0
+#endif
+
+#ifndef inline
+#define inline __inline
+#endif
+
+#endif
+
+/* Return the offset of the given field in the given type */
+#ifndef offsetof
+/* GCC 4.0 and later has the builtin. */
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define offsetof(Type, field) __builtin_offsetof(Type, field)
+#else
+#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
+#endif
+#endif
+
+typedef uint8_t uint8;
+typedef int8_t int8;
+typedef uint16_t uint16;
+typedef int16_t int16;
+typedef uint32_t uint32;
+typedef int32_t int32;
+typedef float float32;
+typedef double float64;
+typedef uint64_t uint64;
+typedef int64_t int64;
+
+typedef void *(*thread_start_routine_t)(void *);
+
+#ifndef bh_socket_t
+/* If no socket defined on current platform,
+ give a fake definition to make the compiler happy */
+#define bh_socket_t int
+#endif
+
+/* Format specifiers macros in case
+ they are not provided by compiler */
+#ifndef __PRI64_PREFIX
+#if UINTPTR_MAX == UINT64_MAX
+#define __PRI64_PREFIX "l"
+#define __PRIPTR_PREFIX "l"
+#else
+#define __PRI64_PREFIX "ll"
+#define __PRIPTR_PREFIX
+#endif
+#endif /* #ifndef __PRI64_PREFIX */
+
+/* Macros for printing format specifiers */
+#ifndef PRId32
+#define PRId32 "d"
+#endif
+#ifndef PRIi32
+#define PRIi32 "i"
+#endif
+#ifndef PRIu32
+#define PRIu32 "u"
+#endif
+#ifndef PRIx32
+#define PRIx32 "x"
+#endif
+#ifndef PRIX32
+#define PRIX32 "X"
+#endif
+
+#ifndef PRId64
+#define PRId64 __PRI64_PREFIX "d"
+#endif
+#ifndef PRIu64
+#define PRIu64 __PRI64_PREFIX "u"
+#endif
+#ifndef PRIx64
+#define PRIx64 __PRI64_PREFIX "x"
+#endif
+#ifndef PRIX64
+#define PRIX64 __PRI64_PREFIX "X"
+#endif
+#ifndef PRIxPTR
+#define PRIxPTR __PRIPTR_PREFIX "x"
+#endif
+#ifndef PRIXPTR
+#define PRIXPTR __PRIPTR_PREFIX "X"
+#endif
+
+/* Macros for scanning format specifiers */
+#ifndef SCNd32
+#define SCNd32 "d"
+#endif
+#ifndef SCNi32
+#define SCNi32 "i"
+#endif
+#ifndef SCNu32
+#define SCNu32 "u"
+#endif
+#ifndef SCNx32
+#define SCNx32 "x"
+#endif
+
+#ifndef SCNd64
+#define SCNd64 __PRI64_PREFIX "d"
+#endif
+#ifndef SCNu64
+#define SCNu64 __PRI64_PREFIX "u"
+#endif
+#ifndef SCNx64
+#define SCNx64 __PRI64_PREFIX "x"
+#endif
+#ifndef SCNxPTR
+#define SCNxPTR __PRIPTR_PREFIX "x"
+#endif
+
+#ifndef NAN
+#define NAN (0.0 / 0.0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef _PLATFORM_COMMON_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/platform_internal.h
new file mode 100644
index 000000000..d18f015ee
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/platform_internal.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <sgx_thread.h>
+#include <pthread.h>
+
+#include "sgx_error.h"
+#include "sgx_file.h"
+#include "sgx_pthread.h"
+#include "sgx_time.h"
+#include "sgx_socket.h"
+#include "sgx_signal.h"
+#include "sgx_trts.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_LINUX_SGX
+#define BH_PLATFORM_LINUX_SGX
+#endif
+
+#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_thread;
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef unsigned int korp_sem;
+
+#ifndef SGX_DISABLE_PTHREAD
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#endif
+
+typedef int (*os_print_function_t)(const char *message);
+void
+os_set_print_function(os_print_function_t pf);
+
+char *
+strcpy(char *dest, const char *src);
+
+#define os_memory_order_acquire __ATOMIC_ACQUIRE
+#define os_memory_order_release __ATOMIC_RELEASE
+#define os_memory_order_seq_cst __ATOMIC_SEQ_CST
+#define os_atomic_thread_fence __atomic_thread_fence
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.c
new file mode 100644
index 000000000..a8ae8d2f9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.c
@@ -0,0 +1,1117 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "sgx_error.h"
+#include "sgx_file.h"
+
+#if WASM_ENABLE_SGX_IPFS != 0
+#include "sgx_ipfs.h"
+#endif
+
+#ifndef SGX_DISABLE_WASI
+
+#define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__)
+#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
+
+/** fd **/
+int
+ocall_open(int *p_fd, const char *pathname, int flags, bool has_mode,
+ unsigned mode);
+
+int
+ocall_openat(int *p_fd, int dirfd, const char *pathname, int flags,
+ bool has_mode, unsigned mode);
+
+int
+ocall_read(ssize_t *p_ret, int fd, void *buf, size_t read_size);
+
+int
+ocall_close(int *p_ret, int fd);
+
+int
+ocall_lseek(off_t *p_ret, int fd, off_t offset, int whence);
+
+int
+ocall_ftruncate(int *p_ret, int fd, off_t length);
+
+int
+ocall_fsync(int *p_ret, int fd);
+
+int
+ocall_fdatasync(int *p_ret, int fd);
+
+int
+ocall_isatty(int *p_ret, int fd);
+/** fd end **/
+
+/** DIR **/
+int
+ocall_fdopendir(int fd, void **p_dirp);
+
+int
+ocall_readdir(void **p_dirent, void *dirp);
+
+int
+ocall_rewinddir(void *dirp);
+
+int
+ocall_seekdir(void *dirp, long loc);
+
+int
+ocall_telldir(long *p_dir, void *dirp);
+
+int
+ocall_closedir(int *p_ret, void *dirp);
+/** DIR end **/
+
+/** stat **/
+int
+ocall_stat(int *p_ret, const char *pathname, void *buf, unsigned int buf_len);
+int
+ocall_fstat(int *p_ret, int fd, void *buf, unsigned int buf_len);
+int
+ocall_fstatat(int *p_ret, int dirfd, const char *pathname, void *buf,
+ unsigned int buf_len, int flags);
+/** stat end **/
+
+/** link **/
+int
+ocall_mkdirat(int *p_ret, int dirfd, const char *pathname, unsigned mode);
+int
+ocall_link(int *p_ret, const char *oldpath, const char *newpath);
+int
+ocall_linkat(int *p_ret, int olddirfd, const char *oldpath, int newdirfd,
+ const char *newpath, int flags);
+int
+ocall_unlinkat(int *p_ret, int dirfd, const char *pathname, int flags);
+int
+ocall_readlink(ssize_t *p_ret, const char *pathname, char *buf, size_t bufsiz);
+int
+ocall_readlinkat(ssize_t *p_ret, int dirfd, const char *pathname, char *buf,
+ size_t bufsiz);
+int
+ocall_renameat(int *p_ret, int olddirfd, const char *oldpath, int newdirfd,
+ const char *newpath);
+int
+ocall_symlinkat(int *p_ret, const char *target, int newdirfd,
+ const char *linkpath);
+/** link end **/
+
+/** control **/
+int
+ocall_ioctl(int *p_ret, int fd, unsigned long request, void *arg,
+ unsigned int arg_len);
+int
+ocall_fcntl(int *p_ret, int fd, int cmd);
+int
+ocall_fcntl_long(int *p_ret, int fd, int cmd, long arg);
+/** control end **/
+
+/** **/
+int
+ocall_realpath(int *p_ret, const char *path, char *buf, unsigned int buf_len);
+int
+ocall_posix_fallocate(int *p_ret, int fd, off_t offset, off_t len);
+int
+ocall_poll(int *p_ret, void *fds, unsigned nfds, int timeout,
+ unsigned int fds_len);
+int
+ocall_getopt(int *p_ret, int argc, char *argv_buf, unsigned int argv_buf_len,
+ const char *optstring);
+int
+ocall_sched_yield(int *p_ret);
+
+/** struct iovec **/
+ssize_t
+ocall_readv(ssize_t *p_ret, int fd, char *iov_buf, unsigned int buf_size,
+ int iovcnt, bool has_offset, off_t offset);
+ssize_t
+ocall_writev(ssize_t *p_ret, int fd, char *iov_buf, unsigned int buf_size,
+ int iovcnt, bool has_offset, off_t offset);
+/** iovec end **/
+
+int
+ocall_get_errno(int *p_ret);
+
+int
+open(const char *pathname, int flags, ...)
+{
+ int fd;
+ bool has_mode = false;
+ mode_t mode = 0;
+
+ if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ has_mode = true;
+ }
+
+ if (SGX_SUCCESS != ocall_open(&fd, pathname, flags, has_mode, mode)) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (fd >= 0 && (flags & O_CLOEXEC))
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ if (fd == -1)
+ errno = get_errno();
+ return fd;
+}
+
+int
+openat(int dirfd, const char *pathname, int flags, ...)
+{
+ int fd;
+ bool has_mode = false;
+ mode_t mode = 0;
+
+ if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ has_mode = true;
+ }
+
+ if (SGX_SUCCESS
+ != ocall_openat(&fd, dirfd, pathname, flags, has_mode, mode)) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (fd >= 0 && (flags & O_CLOEXEC))
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ if (fd == -1)
+ errno = get_errno();
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ struct stat sb;
+ int ret = fstatat(dirfd, pathname, &sb, 0);
+ if (ret < 0) {
+ if (ocall_close(&ret, fd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+ return -1;
+ }
+
+ // Ony files are managed by SGX IPFS
+ if (S_ISREG(sb.st_mode)) {
+ // When WAMR uses Intel SGX IPFS to enabled, it opens a second
+ // file descriptor to interact with the secure file.
+ // The first file descriptor opened earlier is used to interact
+ // with the metadata of the file (e.g., time, flags, etc.).
+ void *file_ptr = ipfs_fopen(fd, flags);
+ if (file_ptr == NULL) {
+ if (ocall_close(&ret, fd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+ return -1;
+ }
+ }
+#endif
+
+ return fd;
+}
+
+int
+close(int fd)
+{
+ int ret;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ // Close the IPFS file pointer in addition of the file descriptor
+ ret = ipfs_close(fd);
+ if (ret == -1)
+ errno = get_errno();
+#endif
+
+ if (ocall_close(&ret, fd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+ssize_t
+read(int fd, void *buf, size_t size)
+{
+ ssize_t ret;
+ int size_read_max = 2048, size_read, total_size_read = 0, count, i;
+ char *p = buf;
+
+ if (buf == NULL) {
+ TRACE_FUNC();
+ return -1;
+ }
+
+ count = (size + size_read_max - 1) / size_read_max;
+ for (i = 0; i < count; i++) {
+ size_read = (i < count - 1) ? size_read_max : size - size_read_max * i;
+
+ if (ocall_read(&ret, fd, p, size_read) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1) {
+ /* read failed */
+ errno = get_errno();
+ return -1;
+ }
+
+ p += ret;
+ total_size_read += ret;
+
+ if (ret < size_read)
+ /* end of file */
+ break;
+ }
+ return total_size_read;
+}
+
+DIR *
+fdopendir(int fd)
+{
+ DIR *result = NULL;
+
+ result = (DIR *)BH_MALLOC(sizeof(DIR));
+ if (!result)
+ return NULL;
+
+ if (ocall_fdopendir(fd, (void **)result) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ BH_FREE(result);
+ return NULL;
+ }
+
+ if ((void *)*result == NULL) { /* opendir failed */
+ TRACE_FUNC();
+ BH_FREE(result);
+ errno = get_errno();
+ return NULL;
+ }
+
+ return result;
+}
+
+struct dirent *
+readdir(DIR *dirp)
+{
+ struct dirent *result;
+
+ if (dirp == NULL)
+ return NULL;
+
+ if (ocall_readdir((void **)&result, (void *)*dirp) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return NULL;
+ }
+
+ if (!result)
+ errno = get_errno();
+ return result;
+}
+
+void
+rewinddir(DIR *dirp)
+{
+ if (ocall_rewinddir((void *)*dirp) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+}
+
+void
+seekdir(DIR *dirp, long loc)
+{
+ if (ocall_seekdir((void *)*dirp, loc) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+}
+
+long
+telldir(DIR *dirp)
+{
+ long ret;
+
+ if (ocall_telldir(&ret, (void *)*dirp) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+closedir(DIR *dirp)
+{
+ int ret;
+
+ if (ocall_closedir(&ret, (void *)*dirp) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ BH_FREE(dirp);
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+static ssize_t
+readv_internal(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
+ off_t offset)
+{
+ ssize_t ret, size_left;
+ struct iovec *iov1;
+ int i;
+ char *p;
+ uint64 total_size = sizeof(struct iovec) * (uint64)iovcnt;
+
+ if (iov == NULL || iovcnt < 1)
+ return -1;
+
+ for (i = 0; i < iovcnt; i++) {
+ total_size += iov[i].iov_len;
+ }
+
+ if (total_size >= UINT32_MAX)
+ return -1;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ if (fd > 2) {
+ return ipfs_read(fd, iov, iovcnt, has_offset, offset);
+ }
+#endif
+
+ iov1 = BH_MALLOC((uint32)total_size);
+
+ if (iov1 == NULL)
+ return -1;
+
+ memset(iov1, 0, (uint32)total_size);
+
+ p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
+
+ for (i = 0; i < iovcnt; i++) {
+ iov1[i].iov_len = iov[i].iov_len;
+ iov1[i].iov_base = p;
+ p += iov[i].iov_len;
+ }
+
+ if (ocall_readv(&ret, fd, (char *)iov1, (uint32)total_size, iovcnt,
+ has_offset, offset)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ BH_FREE(iov1);
+ return -1;
+ }
+
+ p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
+
+ size_left = ret;
+ for (i = 0; i < iovcnt; i++) {
+ if (size_left > iov[i].iov_len) {
+ memcpy(iov[i].iov_base, (uintptr_t)p + (char *)iov1,
+ iov[i].iov_len);
+ p += iov[i].iov_len;
+ size_left -= iov[i].iov_len;
+ }
+ else {
+ memcpy(iov[i].iov_base, (uintptr_t)p + (char *)iov1, size_left);
+ break;
+ }
+ }
+
+ BH_FREE(iov1);
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+static ssize_t
+writev_internal(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
+ off_t offset)
+{
+ ssize_t ret;
+ struct iovec *iov1;
+ int i;
+ char *p;
+ uint64 total_size = sizeof(struct iovec) * (uint64)iovcnt;
+
+ if (iov == NULL || iovcnt < 1)
+ return -1;
+
+ for (i = 0; i < iovcnt; i++) {
+ total_size += iov[i].iov_len;
+ }
+
+ if (total_size >= UINT32_MAX)
+ return -1;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ if (fd > 2) {
+ return ipfs_write(fd, iov, iovcnt, has_offset, offset);
+ }
+#endif
+
+ iov1 = BH_MALLOC((uint32)total_size);
+
+ if (iov1 == NULL)
+ return -1;
+
+ memset(iov1, 0, (uint32)total_size);
+
+ p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
+
+ for (i = 0; i < iovcnt; i++) {
+ iov1[i].iov_len = iov[i].iov_len;
+ iov1[i].iov_base = p;
+ memcpy((uintptr_t)p + (char *)iov1, iov[i].iov_base, iov[i].iov_len);
+ p += iov[i].iov_len;
+ }
+
+ if (ocall_writev(&ret, fd, (char *)iov1, (uint32)total_size, iovcnt,
+ has_offset, offset)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ BH_FREE(iov1);
+ return -1;
+ }
+
+ BH_FREE(iov1);
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+ssize_t
+readv(int fd, const struct iovec *iov, int iovcnt)
+{
+ return readv_internal(fd, iov, iovcnt, false, 0);
+}
+
+ssize_t
+writev(int fd, const struct iovec *iov, int iovcnt)
+{
+ return writev_internal(fd, iov, iovcnt, false, 0);
+}
+
+ssize_t
+preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+ return readv_internal(fd, iov, iovcnt, true, offset);
+}
+
+ssize_t
+pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+ return writev_internal(fd, iov, iovcnt, true, offset);
+}
+
+off_t
+lseek(int fd, off_t offset, int whence)
+{
+ off_t ret;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ ret = ipfs_lseek(fd, offset, whence);
+#else
+ if (ocall_lseek(&ret, fd, (long)offset, whence) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+#endif
+
+ return ret;
+}
+
+int
+ftruncate(int fd, off_t length)
+{
+ int ret;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ ret = ipfs_ftruncate(fd, length);
+#else
+ if (ocall_ftruncate(&ret, fd, length) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+#endif
+
+ return ret;
+}
+
+int
+stat(const char *pathname, struct stat *statbuf)
+{
+ int ret;
+
+ if (statbuf == NULL)
+ return -1;
+
+ if (ocall_stat(&ret, pathname, (void *)statbuf, sizeof(struct stat))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+fstat(int fd, struct stat *statbuf)
+{
+ int ret;
+
+ if (statbuf == NULL)
+ return -1;
+
+ if (ocall_fstat(&ret, fd, (void *)statbuf, sizeof(struct stat))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags)
+{
+ int ret;
+
+ if (statbuf == NULL)
+ return -1;
+
+ if (ocall_fstatat(&ret, dirfd, pathname, (void *)statbuf,
+ sizeof(struct stat), flags)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+fsync(int fd)
+{
+ int ret;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ ret = ipfs_fflush(fd);
+#else
+ if (ocall_fsync(&ret, fd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+#endif
+
+ return ret;
+}
+
+int
+fdatasync(int fd)
+{
+ int ret;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ ret = ipfs_fflush(fd);
+#else
+ if (ocall_fdatasync(&ret, fd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+#endif
+
+ return ret;
+}
+
+int
+mkdirat(int dirfd, const char *pathname, mode_t mode)
+{
+ int ret;
+
+ if (ocall_mkdirat(&ret, dirfd, pathname, mode) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+link(const char *oldpath, const char *newpath)
+{
+ int ret;
+
+ if (ocall_link(&ret, oldpath, newpath) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
+ int flags)
+{
+ int ret;
+
+ if (ocall_linkat(&ret, olddirfd, oldpath, newdirfd, newpath, flags)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+unlinkat(int dirfd, const char *pathname, int flags)
+{
+ int ret;
+
+ if (ocall_unlinkat(&ret, dirfd, pathname, flags) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+ssize_t
+readlink(const char *pathname, char *buf, size_t bufsiz)
+{
+ ssize_t ret;
+
+ if (buf == NULL)
+ return -1;
+
+ if (ocall_readlink(&ret, pathname, buf, bufsiz) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+ssize_t
+readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
+{
+ ssize_t ret;
+
+ if (buf == NULL)
+ return -1;
+
+ if (ocall_readlinkat(&ret, dirfd, pathname, buf, bufsiz) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+symlinkat(const char *target, int newdirfd, const char *linkpath)
+{
+ int ret;
+
+ if (ocall_symlinkat(&ret, target, newdirfd, linkpath) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)
+{
+ int ret;
+
+ if (ocall_renameat(&ret, olddirfd, oldpath, newdirfd, newpath)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+ioctl(int fd, unsigned long request, ...)
+{
+ int ret;
+ va_list args;
+
+ switch (request) {
+ case FIONREAD:
+ va_start(args, request);
+ int *arg = (int *)va_arg(args, int *);
+ if (ocall_ioctl(&ret, fd, request, arg, sizeof(*arg))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ va_end(args);
+ return -1;
+ }
+ va_end(args);
+ break;
+
+ default:
+ os_printf("ioctl failed: unknown request", request);
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+fcntl(int fd, int cmd, ... /* arg */)
+{
+ int ret;
+ va_list args;
+
+ switch (cmd) {
+ case F_GETFD:
+ case F_GETFL:
+ if (ocall_fcntl(&ret, fd, cmd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ break;
+
+ case F_DUPFD:
+ case F_SETFD:
+ case F_SETFL:
+ va_start(args, cmd);
+ long arg_1 = (long)va_arg(args, long);
+ if (ocall_fcntl_long(&ret, fd, cmd, arg_1) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ va_end(args);
+ return -1;
+ }
+ va_end(args);
+ break;
+
+ default:
+ os_printf("fcntl failed: unknown cmd %d.\n", cmd);
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+isatty(int fd)
+{
+ int ret;
+
+ if (ocall_isatty(&ret, fd) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == 0)
+ errno = get_errno();
+ return ret;
+}
+
+char *
+realpath(const char *path, char *resolved_path)
+{
+ int ret;
+ char buf[PATH_MAX] = { 0 };
+
+ if (ocall_realpath(&ret, path, buf, PATH_MAX) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return (char *)NULL;
+ }
+
+ if (ret != 0)
+ return (char *)NULL;
+
+ if (resolved_path) {
+ strcpy(resolved_path, buf);
+ }
+ else {
+ resolved_path = BH_MALLOC(strlen(buf) + 1);
+ if (resolved_path == NULL)
+ return NULL;
+ strcpy(resolved_path, buf);
+ }
+
+ return resolved_path;
+}
+
+int
+posix_fallocate(int fd, off_t offset, off_t len)
+{
+ int ret;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ ret = ipfs_posix_fallocate(fd, offset, len);
+#else
+ if (ocall_posix_fallocate(&ret, fd, offset, len) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+#endif
+
+ return ret;
+}
+
+int
+poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ int ret;
+
+ if (fds == NULL)
+ return -1;
+
+ if (ocall_poll(&ret, fds, nfds, timeout, sizeof(*fds) * nfds)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+getopt(int argc, char *const argv[], const char *optstring)
+{
+ int ret;
+ char **argv1;
+ char *p;
+ int i;
+ uint64 total_size = sizeof(char *) * (uint64)argc;
+
+ for (i = 0; i < argc; i++) {
+ total_size += strlen(argv[i]) + 1;
+ }
+
+ if (total_size >= UINT32_MAX)
+ return -1;
+
+ argv1 = BH_MALLOC((uint32)total_size);
+
+ if (argv1 == NULL)
+ return -1;
+
+ p = (char *)(uintptr_t)(sizeof(char *) * argc);
+
+ for (i = 0; i < argc; i++) {
+ argv1[i] = p;
+ strcpy((char *)argv1 + (uintptr_t)p, argv[i]);
+ p += ((uintptr_t)strlen(argv[i]) + 1);
+ }
+
+ if (ocall_getopt(&ret, argc, (char *)argv1, total_size, optstring)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ BH_FREE(argv1);
+ return -1;
+ }
+
+ BH_FREE(argv1);
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+int
+sched_yield(void)
+{
+ int ret;
+
+ if (ocall_sched_yield(&ret) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ if (ret == -1)
+ errno = get_errno();
+ return ret;
+}
+
+ssize_t
+getrandom(void *buf, size_t buflen, unsigned int flags)
+{
+ sgx_status_t ret;
+
+ if (!buf || buflen > INT32_MAX || flags != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ret = sgx_read_rand(buf, buflen);
+ if (ret != SGX_SUCCESS) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ return (ssize_t)buflen;
+}
+
+#define RDRAND_RETRIES 3
+
+static int
+rdrand64_step(uint64 *seed)
+{
+ uint8 ok;
+ __asm__ volatile("rdseed %0; setc %1" : "=r"(*seed), "=qm"(ok));
+ return (int)ok;
+}
+
+static int
+rdrand64_retry(uint64 *rand, uint32 retries)
+{
+ uint32 count = 0;
+
+ while (count++ <= retries) {
+ if (rdrand64_step(rand)) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static uint32
+rdrand_get_bytes(uint8 *dest, uint32 n)
+{
+ uint8 *head_start = dest, *tail_start = NULL;
+ uint64 *block_start;
+ uint32 count, ltail, lhead, lblock;
+ uint64 i, temp_rand;
+
+ /* Get the address of the first 64-bit aligned block in the
+ destination buffer. */
+ if (((uintptr_t)head_start & (uintptr_t)7) == 0) {
+ /* already 8-byte aligned */
+ block_start = (uint64 *)head_start;
+ lhead = 0;
+ lblock = n & ~7;
+ }
+ else {
+ /* next 8-byte aligned */
+ block_start = (uint64 *)(((uintptr_t)head_start + 7) & ~(uintptr_t)7);
+ lhead = (uint32)((uintptr_t)block_start - (uintptr_t)head_start);
+ lblock = (n - lhead) & ~7;
+ }
+
+ /* Compute the number of 64-bit blocks and the remaining number
+ of bytes (the tail) */
+ ltail = n - lblock - lhead;
+ if (ltail > 0) {
+ tail_start = (uint8 *)block_start + lblock;
+ }
+
+ /* Populate the starting, mis-aligned section (the head) */
+ if (lhead > 0) {
+ if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
+ return 0;
+ }
+ memcpy(head_start, &temp_rand, lhead);
+ }
+
+ /* Populate the central, aligned blocks */
+ count = lblock / 8;
+ for (i = 0; i < count; i++, block_start++) {
+ if (!rdrand64_retry(block_start, RDRAND_RETRIES)) {
+ return i * 8 + lhead;
+ }
+ }
+
+ /* Populate the tail */
+ if (ltail > 0) {
+ if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
+ return count * 8 + lhead;
+ }
+
+ memcpy(tail_start, &temp_rand, ltail);
+ }
+
+ return n;
+}
+
+int
+getentropy(void *buffer, size_t length)
+{
+ uint32 size;
+
+ if (!buffer || length > INT32_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (length == 0) {
+ return 0;
+ }
+
+ size = rdrand_get_bytes(buffer, (uint32)length);
+ if (size != length) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+get_errno(void)
+{
+ int ret;
+
+ if (ocall_get_errno(&ret) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ return ret;
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.h
new file mode 100644
index 000000000..8690e1f69
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_file.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SGX_FILE_H
+#define _SGX_FILE_H
+
+#include "sgx_time.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define F_DUPFD 0
+#define F_GETFD 1
+#define F_SETFD 2
+#define F_GETFL 3
+#define F_SETFL 4
+
+#define FD_CLOEXEC 1
+
+#define O_PATH 010000000
+#define O_SEARCH O_PATH
+#define O_EXEC O_PATH
+
+#define O_ACCMODE (03 | O_SEARCH)
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+
+#define O_CREAT 0100
+#define O_EXCL 0200
+#define O_NOCTTY 0400
+#define O_TRUNC 01000
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_DSYNC 010000
+#define O_SYNC 04010000
+#define O_RSYNC 04010000
+#define O_DIRECTORY 0200000
+#define O_NOFOLLOW 0400000
+#define O_CLOEXEC 02000000
+
+#define O_ASYNC 020000
+#define O_DIRECT 040000
+#define O_LARGEFILE 0
+#define O_NOATIME 01000000
+#define O_PATH 010000000
+#define O_TMPFILE 020200000
+#define O_NDELAY O_NONBLOCK
+
+#define S_IFMT 0170000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFBLK 0060000
+#define S_IFREG 0100000
+#define S_IFIFO 0010000
+#define S_IFLNK 0120000
+#define S_IFSOCK 0140000
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
+#define S_ISCHR(mode) (((mode)&S_IFMT) == S_IFCHR)
+#define S_ISBLK(mode) (((mode)&S_IFMT) == S_IFBLK)
+#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
+#define S_ISFIFO(mode) (((mode)&S_IFMT) == S_IFIFO)
+#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
+#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK)
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+#define AT_SYMLINK_NOFOLLOW 0x100
+#define AT_REMOVEDIR 0x200
+#define AT_SYMLINK_FOLLOW 0x400
+
+#define POLLIN 0x001
+#define POLLPRI 0x002
+#define POLLOUT 0x004
+#define POLLERR 0x008
+#define POLLHUP 0x010
+#define POLLNVAL 0x020
+#define POLLRDNORM 0x040
+#define POLLRDBAND 0x080
+#define POLLWRNORM 0x100
+#define POLLWRBAND 0x200
+
+#define FIONREAD 0x541B
+
+#define PATH_MAX 4096
+
+/* Special value used to indicate openat should use the current
+ working directory. */
+#define AT_FDCWD -100
+
+typedef long __syscall_slong_t;
+
+typedef unsigned long dev_t;
+typedef unsigned long ino_t;
+typedef unsigned mode_t;
+typedef unsigned long nlink_t;
+typedef unsigned socklen_t;
+typedef long blksize_t;
+typedef long blkcnt_t;
+
+typedef int pid_t;
+typedef unsigned gid_t;
+typedef unsigned uid_t;
+
+typedef unsigned long nfds_t;
+
+typedef uintptr_t DIR;
+
+struct dirent {
+ ino_t d_ino;
+ off_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+};
+
+struct stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ nlink_t st_nlink;
+
+ mode_t st_mode;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned int __pad0;
+ dev_t st_rdev;
+ off_t st_size;
+ blksize_t st_blksize;
+ blkcnt_t st_blocks;
+
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+ long __unused[3];
+};
+
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+int
+open(const char *pathname, int flags, ...);
+int
+openat(int dirfd, const char *pathname, int flags, ...);
+int
+close(int fd);
+
+DIR *
+fdopendir(int fd);
+int
+closedir(DIR *dirp);
+void
+rewinddir(DIR *dirp);
+void
+seekdir(DIR *dirp, long loc);
+struct dirent *
+readdir(DIR *dirp);
+long
+telldir(DIR *dirp);
+
+ssize_t
+read(int fd, void *buf, size_t count);
+ssize_t
+readv(int fd, const struct iovec *iov, int iovcnt);
+ssize_t
+writev(int fd, const struct iovec *iov, int iovcnt);
+ssize_t
+preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t
+pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+
+off_t
+lseek(int fd, off_t offset, int whence);
+int
+ftruncate(int fd, off_t length);
+
+int
+stat(const char *pathname, struct stat *statbuf);
+int
+fstat(int fd, struct stat *statbuf);
+int
+fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags);
+
+int
+fsync(int fd);
+int
+fdatasync(int fd);
+
+int
+mkdirat(int dirfd, const char *pathname, mode_t mode);
+int
+link(const char *oldpath, const char *newpath);
+int
+linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
+ int flags);
+int
+unlinkat(int dirfd, const char *pathname, int flags);
+ssize_t
+readlink(const char *pathname, char *buf, size_t bufsiz);
+ssize_t
+readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
+int
+symlinkat(const char *target, int newdirfd, const char *linkpath);
+int
+renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
+
+int
+ioctl(int fd, unsigned long request, ...);
+int
+fcntl(int fd, int cmd, ... /* arg */);
+
+int
+isatty(int fd);
+
+char *
+realpath(const char *path, char *resolved_path);
+
+int
+posix_fallocate(int fd, off_t offset, off_t len);
+
+int
+poll(struct pollfd *fds, nfds_t nfds, int timeout);
+
+int
+getopt(int argc, char *const argv[], const char *optstring);
+
+int
+sched_yield(void);
+
+ssize_t
+getrandom(void *buf, size_t buflen, unsigned int flags);
+
+int
+getentropy(void *buffer, size_t length);
+
+int
+get_errno(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SGX_FILE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.c
new file mode 100644
index 000000000..322688980
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2022 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if WASM_ENABLE_SGX_IPFS != 0
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "sgx_ipfs.h"
+
+#include <errno.h>
+
+#include "sgx_tprotected_fs.h"
+
+#define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
+#define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED
+
+// Internal buffer filled with zeroes and used when extending the size of
+// protected files.
+#define ZEROES_PADDING_LENGTH 32 * 1024
+char zeroes_padding[ZEROES_PADDING_LENGTH] = { 0 };
+
+// The mapping between file descriptors and IPFS file pointers.
+static HashMap *ipfs_file_list;
+
+// Converts an SGX error code to a POSIX error code.
+static __wasi_errno_t
+convert_sgx_errno(int error)
+{
+ if (error >= SGX_ERROR_FILE_LOWEST_ERROR_ID
+ && error <= SGX_ERROR_FILE_HIGHEST_ERROR_ID) {
+ switch (error) {
+ /* The file is in bad status */
+ case SGX_ERROR_FILE_BAD_STATUS:
+ return ENOTRECOVERABLE;
+ /* The Key ID field is all zeros, can't re-generate the encryption
+ * key */
+ case SGX_ERROR_FILE_NO_KEY_ID:
+ return EKEYREJECTED;
+ /* The current file name is different then the original file name
+ * (not allowed, substitution attack) */
+ case SGX_ERROR_FILE_NAME_MISMATCH:
+ return EIO;
+ /* The file is not an SGX file */
+ case SGX_ERROR_FILE_NOT_SGX_FILE:
+ return EEXIST;
+ /* A recovery file can't be opened, so flush operation can't
+ * continue (only used when no EXXX is returned) */
+ case SGX_ERROR_FILE_CANT_OPEN_RECOVERY_FILE:
+ return EIO;
+ /* A recovery file can't be written, so flush operation can't
+ * continue (only used when no EXXX is returned) */
+ case SGX_ERROR_FILE_CANT_WRITE_RECOVERY_FILE:
+ return EIO;
+ /* When openeing the file, recovery is needed, but the recovery
+ * process failed */
+ case SGX_ERROR_FILE_RECOVERY_NEEDED:
+ return EIO;
+ /* fflush operation (to disk) failed (only used when no EXXX is
+ * returned) */
+ case SGX_ERROR_FILE_FLUSH_FAILED:
+ return EIO;
+ /* fclose operation (to disk) failed (only used when no EXXX is
+ * returned) */
+ case SGX_ERROR_FILE_CLOSE_FAILED:
+ return EIO;
+ }
+ }
+
+ return error;
+}
+
+static void *
+fd2file(int fd)
+{
+ return bh_hash_map_find(ipfs_file_list, (void *)(intptr_t)fd);
+}
+
+static void
+ipfs_file_destroy(void *sgx_file)
+{
+ sgx_fclose(sgx_file);
+}
+
+// Writes a given number of zeroes in file at the current offset.
+// The return value is zero if successful; otherwise non-zero.
+static int
+ipfs_write_zeroes(void *sgx_file, size_t len)
+{
+ int min_count;
+
+ while (len > 0) {
+ min_count = len < ZEROES_PADDING_LENGTH ? len : ZEROES_PADDING_LENGTH;
+
+ if (sgx_fwrite(zeroes_padding, 1, min_count, sgx_file) == 0) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ len -= min_count;
+ }
+
+ return 0;
+}
+
+int
+ipfs_init()
+{
+ ipfs_file_list =
+ bh_hash_map_create(32, true, (HashFunc)fd_hash, (KeyEqualFunc)fd_equal,
+ NULL, (ValueDestroyFunc)ipfs_file_destroy);
+
+ return ipfs_file_list != NULL ? BHT_OK : BHT_ERROR;
+}
+
+void
+ipfs_destroy()
+{
+ bh_hash_map_destroy(ipfs_file_list);
+}
+
+int
+ipfs_posix_fallocate(int fd, off_t offset, size_t len)
+{
+ void *sgx_file = fd2file(fd);
+ if (!sgx_file) {
+ return EBADF;
+ }
+
+ // The wrapper for fseek takes care of extending the file if sought beyond
+ // the end
+ if (ipfs_lseek(fd, offset + len, SEEK_SET) == -1) {
+ return errno;
+ }
+
+ // Make sure the file is allocated by flushing it
+ if (sgx_fflush(sgx_file) != 0) {
+ return errno;
+ }
+
+ return 0;
+}
+
+size_t
+ipfs_read(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
+ off_t offset)
+{
+ int i;
+ off_t original_offset = 0;
+ void *sgx_file = fd2file(fd);
+ size_t read_result, number_of_read_bytes = 0;
+
+ if (!sgx_file) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (has_offset) {
+ // Save the current offset, to restore it after the read operation
+ original_offset = (off_t)sgx_ftell(sgx_file);
+
+ if (original_offset == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ // Move to the desired location
+ if (sgx_fseek(sgx_file, offset, SEEK_SET) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+ }
+
+ // For each element in the vector
+ for (i = 0; i < iovcnt; i++) {
+ if (iov[i].iov_len == 0)
+ continue;
+
+ read_result = sgx_fread(iov[i].iov_base, 1, iov[i].iov_len, sgx_file);
+ number_of_read_bytes += read_result;
+
+ if (read_result != iov[i].iov_len) {
+ if (!sgx_feof(sgx_file)) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+ }
+ }
+
+ if (has_offset) {
+ // Restore the position of the cursor
+ if (sgx_fseek(sgx_file, original_offset, SEEK_SET) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+ }
+
+ return number_of_read_bytes;
+}
+
+size_t
+ipfs_write(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
+ off_t offset)
+{
+ int i;
+ off_t original_offset = 0;
+ void *sgx_file = fd2file(fd);
+ size_t write_result, number_of_written_bytes = 0;
+
+ if (!sgx_file) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (has_offset) {
+ // Save the current offset, to restore it after the read operation
+ original_offset = (off_t)sgx_ftell(sgx_file);
+
+ if (original_offset == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ // Move to the desired location
+ if (sgx_fseek(sgx_file, offset, SEEK_SET) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+ }
+
+ // For each element in the vector
+ for (i = 0; i < iovcnt; i++) {
+ if (iov[i].iov_len == 0)
+ continue;
+
+ write_result = sgx_fwrite(iov[i].iov_base, 1, iov[i].iov_len, sgx_file);
+ number_of_written_bytes += write_result;
+
+ if (write_result != iov[i].iov_len) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+ }
+
+ if (has_offset) {
+ // Restore the position of the cursor
+ if (sgx_fseek(sgx_file, original_offset, SEEK_SET) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+ }
+
+ return number_of_written_bytes;
+}
+
+int
+ipfs_close(int fd)
+{
+ void *sgx_file;
+
+ if (!bh_hash_map_remove(ipfs_file_list, (void *)(intptr_t)fd, NULL,
+ &sgx_file)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (sgx_fclose(sgx_file)) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ return 0;
+}
+
+void *
+ipfs_fopen(int fd, int flags)
+{
+ // Mapping back the mode
+ const char *mode;
+
+ bool must_create = (flags & O_CREAT) != 0;
+ bool must_truncate = (flags & O_TRUNC) != 0;
+ bool must_append = (flags & O_APPEND) != 0;
+ bool read_only = (flags & O_ACCMODE) == O_RDONLY;
+ bool write_only = (flags & O_ACCMODE) == O_WRONLY;
+ bool read_write = (flags & O_ACCMODE) == O_RDWR;
+
+ // The mapping of the mode is similar to the table in the official
+ // specifications:
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html
+ // Note that POSIX has obtained a file descriptor beforehand.
+ // If opened with a destructive mode ("w" or "w+"), the truncate operation
+ // already occurred and must not be repeated because this will invalidate
+ // the file descriptor obtained by POSIX. Therefore, we do NOT map to the
+ // modes that truncate the file ("w" and "w+"). Instead, we map to a
+ // non-destructive mode ("r+").
+
+ if (read_only)
+ mode = "r";
+ else if (write_only && must_create && must_truncate)
+ // Rather than "w", we map to a non-destructive mode
+ mode = "r+";
+ else if (write_only && must_create && must_append)
+ mode = "a";
+ else if (read_write && must_create && must_append)
+ mode = "a+";
+ else if (read_write)
+ // Rather than "w+", we map to a non-destructive mode
+ mode = "r+";
+ else
+ mode = NULL;
+
+ // Cannot map the requested access to the SGX IPFS
+ if (mode == NULL) {
+ errno = __WASI_ENOTCAPABLE;
+ return NULL;
+ }
+
+ // Determine the symbolic link of the file descriptor, because IPFS does not
+ // support opening a relative path to a file descriptor (i.e., openat).
+ // Using the symbolic link in /proc/self allows to retrieve the same path as
+ // opened by the initial openat and respects the chroot of WAMR.
+ size_t ret;
+ char symbolic_path[32];
+ ret =
+ snprintf(symbolic_path, sizeof(symbolic_path), "/proc/self/fd/%d", fd);
+ if (ret >= sizeof(symbolic_path)) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+
+ // Resolve the symbolic link to real absolute path, because IPFS can only
+ // open a file with a same file name it was initially created. Otherwise,
+ // IPFS throws SGX_ERROR_FILE_NAME_MISMATCH.
+ char real_path[PATH_MAX] = { 0 };
+ ret = readlink(symbolic_path, real_path, PATH_MAX - 1);
+ if (ret == -1)
+ return NULL;
+
+ // Opening the file using the real path
+ void *sgx_file = sgx_fopen_auto_key(real_path, mode);
+
+ if (sgx_file == NULL) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return NULL;
+ }
+
+ if (!bh_hash_map_insert(ipfs_file_list, (void *)(intptr_t)fd, sgx_file)) {
+ errno = __WASI_ECANCELED;
+ sgx_fclose(sgx_file);
+ os_printf("An error occurred while inserting the IPFS file pointer in "
+ "the map.");
+ return NULL;
+ }
+
+ return sgx_file;
+}
+
+int
+ipfs_fflush(int fd)
+{
+ void *sgx_file = fd2file(fd);
+
+ if (!sgx_file) {
+ errno = EBADF;
+ return EOF;
+ }
+
+ int ret = sgx_fflush(sgx_file);
+
+ if (ret == 1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return EOF;
+ }
+
+ return ret;
+}
+
+off_t
+ipfs_lseek(int fd, off_t offset, int nwhence)
+{
+ off_t cursor_current_location;
+ void *sgx_file = fd2file(fd);
+ if (!sgx_file) {
+ errno = EBADF;
+ return -1;
+ }
+
+ // Optimization: if the offset is 0 and the whence is SEEK_CUR,
+ // this is equivalent of a call to ftell.
+ if (offset == 0 && nwhence == SEEK_CUR) {
+ cursor_current_location = (off_t)sgx_ftell(sgx_file);
+
+ if (cursor_current_location == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ return cursor_current_location;
+ }
+
+ int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
+
+ if (fseek_result == 0) {
+ off_t new_offset = (off_t)sgx_ftell(sgx_file);
+
+ if (new_offset == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ return new_offset;
+ }
+ else {
+ // In the case fseek returned an error
+ int sgx_error = sgx_ferror(sgx_file);
+ if (sgx_error != EINVAL) {
+ errno = convert_sgx_errno(sgx_error);
+ return -1;
+ }
+
+ // We must consider a difference in behavior of sgx_fseek and the POSIX
+ // fseek. If the cursor is moved beyond the end of the file, sgx_fseek
+ // returns an error, whereas POSIX fseek accepts the cursor move and
+ // fill with zeroes the difference for the next write. This
+ // implementation handle zeroes completion and moving the cursor forward
+ // the end of the file, but does it now (during the fseek), which is
+ // different compared to POSIX implementation, that writes zeroes on the
+ // next write. This avoids the runtime to keep track of the cursor
+ // manually.
+
+ // Assume the error is raised because the cursor is moved beyond the end
+ // of the file.
+
+ // If the whence is the current cursor location, retrieve it
+ if (nwhence == SEEK_CUR) {
+ cursor_current_location = (off_t)sgx_ftell(sgx_file);
+ }
+
+ // Move the cursor at the end of the file
+ if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ // Compute the number of zeroes to append.
+ int64_t number_of_zeroes;
+ switch (nwhence) {
+ case SEEK_SET:
+ number_of_zeroes = offset - sgx_ftell(sgx_file);
+ break;
+ case SEEK_END:
+ number_of_zeroes = offset;
+ break;
+ case SEEK_CUR:
+ number_of_zeroes =
+ cursor_current_location + offset - sgx_ftell(sgx_file);
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Write the missing zeroes
+ if (ipfs_write_zeroes(sgx_file, number_of_zeroes) != 0) {
+ return -1;
+ }
+
+ // Move again at the end of the file
+ if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ return offset;
+ }
+}
+
+// The official API does not provide a way to truncate files.
+// Only files extension is supported.
+int
+ipfs_ftruncate(int fd, off_t len)
+{
+ void *sgx_file = fd2file(fd);
+ if (!sgx_file) {
+ errno = EBADF;
+ return -1;
+ }
+
+ off_t original_offset = sgx_ftell(sgx_file);
+
+ // Optimization path: if the length is smaller than the offset,
+ // IPFS does not support truncate to a smaller size.
+ if (len < original_offset) {
+ os_printf(
+ "SGX IPFS does not support truncate files to smaller sizes.\n");
+ return __WASI_ECANCELED;
+ }
+
+ // Move to the end of the file to determine whether this is
+ // a file extension or reduction.
+ if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ off_t file_size = sgx_ftell(sgx_file);
+
+ // Reducing the file space is not supported by IPFS.
+ if (len < file_size) {
+ os_printf(
+ "SGX IPFS does not support truncate files to smaller sizes.\n");
+ return __WASI_ECANCELED;
+ }
+
+ // Increasing the size is equal to writing from the end of the file
+ // with null bytes.
+ if (ipfs_write_zeroes(sgx_file, len - file_size) != 0) {
+ return -1;
+ }
+
+ // Restore the position of the cursor
+ if (sgx_fseek(sgx_file, original_offset, SEEK_SET) == -1) {
+ errno = convert_sgx_errno(sgx_ferror(sgx_file));
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* end of WASM_ENABLE_SGX_IPFS */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.h
new file mode 100644
index 000000000..e4de90274
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_ipfs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _LIBC_WASI_SGX_PFS_H
+#define _LIBC_WASI_SGX_PFS_H
+
+#include "bh_hashmap.h"
+#include "wasmtime_ssp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+ipfs_init();
+void
+ipfs_destroy();
+int
+ipfs_posix_fallocate(int fd, off_t offset, size_t len);
+size_t
+ipfs_read(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
+ off_t offset);
+size_t
+ipfs_write(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
+ off_t offset);
+int
+ipfs_close(int fd);
+void *
+ipfs_fopen(int fd, int flags);
+int
+ipfs_fflush(int fd);
+off_t
+ipfs_lseek(int fd, off_t offset, int nwhence);
+int
+ipfs_ftruncate(int fd, off_t len);
+
+/**
+ * Whether two file descriptors are equal.
+ */
+inline static bool
+fd_equal(int left, int right)
+{
+ return left == right ? true : false;
+}
+
+/**
+ * Returns the file descriptor as a hash value.
+ */
+inline static uint32
+fd_hash(int fd)
+{
+ return (uint32)fd;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _LIBC_WASI_SGX_PFS_H */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_platform.c
new file mode 100644
index 000000000..b40eaf79c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_platform.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+#include "sgx_rsrv_mem_mngr.h"
+
+#if WASM_ENABLE_SGX_IPFS != 0
+#include "sgx_ipfs.h"
+#endif
+
+static os_print_function_t print_function = NULL;
+
+int
+bh_platform_init()
+{
+ int ret = BHT_OK;
+
+#if WASM_ENABLE_SGX_IPFS != 0
+ ret = ipfs_init();
+#endif
+
+ return ret;
+}
+
+void
+bh_platform_destroy()
+{
+#if WASM_ENABLE_SGX_IPFS != 0
+ ipfs_destroy();
+#endif
+}
+
+void *
+os_malloc(unsigned size)
+{
+ return malloc(size);
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return realloc(ptr, size);
+}
+
+void
+os_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
+
+int
+putchar(int c)
+{
+ return 0;
+}
+
+int
+puts(const char *s)
+{
+ return 0;
+}
+
+void
+os_set_print_function(os_print_function_t pf)
+{
+ print_function = pf;
+}
+
+#define FIXED_BUFFER_SIZE 4096
+
+int
+os_printf(const char *message, ...)
+{
+ int bytes_written = 0;
+
+ if (print_function != NULL) {
+ char msg[FIXED_BUFFER_SIZE] = { '\0' };
+ va_list ap;
+ va_start(ap, message);
+ vsnprintf(msg, FIXED_BUFFER_SIZE, message, ap);
+ va_end(ap);
+ bytes_written += print_function(msg);
+ }
+
+ return bytes_written;
+}
+
+int
+os_vprintf(const char *format, va_list arg)
+{
+ int bytes_written = 0;
+
+ if (print_function != NULL) {
+ char msg[FIXED_BUFFER_SIZE] = { '\0' };
+ vsnprintf(msg, FIXED_BUFFER_SIZE, format, arg);
+ bytes_written += print_function(msg);
+ }
+
+ return bytes_written;
+}
+
+char *
+strcpy(char *dest, const char *src)
+{
+ const unsigned char *s = src;
+ unsigned char *d = dest;
+
+ while ((*d++ = *s++)) {
+ }
+ return dest;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ int mprot = 0;
+ uint64 aligned_size, page_size;
+ void *ret = NULL;
+ sgx_status_t st = 0;
+
+ page_size = getpagesize();
+ aligned_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (aligned_size >= UINT32_MAX)
+ return NULL;
+
+ ret = sgx_alloc_rsrv_mem(aligned_size);
+ if (ret == NULL) {
+ os_printf("os_mmap(size=%u, aligned size=%lu, prot=0x%x) failed.", size,
+ aligned_size, prot);
+ return NULL;
+ }
+
+ if (prot & MMAP_PROT_READ)
+ mprot |= SGX_PROT_READ;
+ if (prot & MMAP_PROT_WRITE)
+ mprot |= SGX_PROT_WRITE;
+ if (prot & MMAP_PROT_EXEC)
+ mprot |= SGX_PROT_EXEC;
+
+ st = sgx_tprotect_rsrv_mem(ret, aligned_size, mprot);
+ if (st != SGX_SUCCESS) {
+ os_printf("os_mmap(size=%u, prot=0x%x) failed to set protect.", size,
+ prot);
+ sgx_free_rsrv_mem(ret, aligned_size);
+ return NULL;
+ }
+
+ return ret;
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ uint64 aligned_size, page_size;
+
+ page_size = getpagesize();
+ aligned_size = (size + page_size - 1) & ~(page_size - 1);
+ sgx_free_rsrv_mem(addr, aligned_size);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ int mprot = 0;
+ sgx_status_t st = 0;
+ uint64 aligned_size, page_size;
+
+ page_size = getpagesize();
+ aligned_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (prot & MMAP_PROT_READ)
+ mprot |= SGX_PROT_READ;
+ if (prot & MMAP_PROT_WRITE)
+ mprot |= SGX_PROT_WRITE;
+ if (prot & MMAP_PROT_EXEC)
+ mprot |= SGX_PROT_EXEC;
+ st = sgx_tprotect_rsrv_mem(addr, aligned_size, mprot);
+ if (st != SGX_SUCCESS)
+ os_printf("os_mprotect(addr=0x%" PRIx64 ", size=%u, prot=0x%x) failed.",
+ (uintptr_t)addr, size, prot);
+
+ return (st == SGX_SUCCESS ? 0 : -1);
+}
+
+void
+os_dcache_flush(void)
+{}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.c
new file mode 100644
index 000000000..7801e3534
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "sgx_pthread.h"
+#include "sgx_error.h"
+
+#ifndef SGX_DISABLE_WASI
+
+#define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__)
+#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
+
+#ifndef SGX_THREAD_LOCK_INITIALIZER /* defined since sgxsdk-2.11 */
+/* sgxsdk doesn't support pthread_rwlock related APIs until
+ version 2.11, we implement them by ourselves. */
+int
+ocall_pthread_rwlock_init(int *p_ret, void **rwlock, void *attr);
+
+int
+ocall_pthread_rwlock_destroy(int *p_ret, void **rwlock);
+
+int
+ocall_pthread_rwlock_rdlock(int *p_ret, void **rwlock);
+
+int
+ocall_pthread_rwlock_wrlock(int *p_ret, void **rwlock);
+
+int
+ocall_pthread_rwlock_unlock(int *p_ret, void **rwlock);
+
+int
+pthread_rwlock_init(pthread_rwlock_t *rwlock, void *attr)
+{
+ int ret = -1;
+
+ if (ocall_pthread_rwlock_init(&ret, (void **)rwlock, NULL) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ (void)attr;
+ return ret;
+}
+
+int
+pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
+{
+ int ret = -1;
+
+ if (ocall_pthread_rwlock_destroy(&ret, (void *)*rwlock) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+ return ret;
+}
+
+int
+pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
+{
+ int ret = -1;
+
+ if (ocall_pthread_rwlock_rdlock(&ret, (void *)*rwlock) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+ return ret;
+}
+
+int
+pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
+{
+ int ret = -1;
+
+ if (ocall_pthread_rwlock_wrlock(&ret, (void *)*rwlock) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+ return ret;
+}
+
+int
+pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+{
+ int ret = -1;
+
+ if (ocall_pthread_rwlock_unlock(&ret, (void *)*rwlock) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ }
+ return ret;
+}
+#endif /* end of SGX_THREAD_LOCK_INITIALIZER */
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.h
new file mode 100644
index 000000000..01a3ae044
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_pthread.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SGX_PTHREAD_H
+#define _SGX_PTHREAD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SGX_THREAD_LOCK_INITIALIZER /* defined since sgxsdk-2.11 */
+/* sgxsdk doesn't support pthread_rwlock related APIs until
+ version 2.11, we implement them by ourselves. */
+typedef uintptr_t pthread_rwlock_t;
+
+int
+pthread_rwlock_init(pthread_rwlock_t *rwlock, void *attr);
+int
+pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
+
+int
+pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
+int
+pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
+int
+pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
+#endif /* end of SGX_THREAD_LOCK_INITIALIZER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SGX_PTHREAD_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_rsrv_mem_mngr.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_rsrv_mem_mngr.h
new file mode 100644
index 000000000..5555d4d9f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_rsrv_mem_mngr.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011-2019 Intel Corporation. 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 Intel Corporation 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
+ * OWNER 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 copied from
+ * https://github.com/intel/linux-sgx/blob/4589daddd58bec7367a6a9de3fe301e6de17671a/common/inc/internal/sgx_rsrv_mem_mngr.h
+ * The reason we copied here is that the official SGX SDK release has
+ * not included this header file yet.
+ */
+
+#pragma once
+
+#ifndef _SGX_RSRV_MEM_MNGR_H_
+#define _SGX_RSRV_MEM_MNGR_H_
+
+#include "stdint.h"
+#include "sgx_error.h"
+
+#define SGX_PROT_READ 0x1 /* page can be read */
+#define SGX_PROT_WRITE 0x2 /* page can be written */
+#define SGX_PROT_EXEC 0x4 /* page can be executed */
+#define SGX_PROT_NONE 0x0 /* page can not be accessed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Allocate a range of EPC memory from the reserved memory area with RW
+ * permission
+ *
+ * Parameters:
+ * Inputs: length [in]: Size of region to be allocated in bytes. Page aligned.
+ * Return: Starting address of the new allocated memory area on success;
+ * otherwise NULL
+ */
+void *
+sgx_alloc_rsrv_mem(size_t length);
+
+/* Free a range of EPC memory from the reserved memory area
+ *
+ * Parameters:
+ * Inputs: addr[in]: Starting address of region to be freed. Page aligned.
+ * length[in]: The length of the memory to be freed in bytes.
+ * Page aligned.
+ * Return: 0 on success; otherwise -1
+ */
+int
+sgx_free_rsrv_mem(void *addr, size_t length);
+
+/* Modify the access permissions of the pages in the reserved memory area.
+ *
+ * Parameters:
+ * Inputs: addr[in]: Starting address of region which needs to change access
+ * permission. Page aligned.
+ * length[in]: The length of the memory to be manipulated in bytes.
+ * Page aligned.
+ * prot[in]: The target memory protection.
+ * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h
+ */
+sgx_status_t
+sgx_tprotect_rsrv_mem(void *addr, size_t len, int prot);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.c
new file mode 100644
index 000000000..b52c18821
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+#ifndef SGX_DISABLE_WASI
+
+#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
+
+int
+ocall_raise(int *p_ret, int sig);
+
+int
+raise(int sig)
+{
+ int ret;
+
+ if (ocall_raise(&ret, sig) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.h
new file mode 100644
index 000000000..494342be3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_signal.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SGX_SIGNAL_H
+#define _SGX_SIGNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Signals. */
+#define SIGHUP 1 /* Hangup (POSIX). */
+#define SIGINT 2 /* Interrupt (ANSI). */
+#define SIGQUIT 3 /* Quit (POSIX). */
+#define SIGILL 4 /* Illegal instruction (ANSI). */
+#define SIGTRAP 5 /* Trace trap (POSIX). */
+#define SIGABRT 6 /* Abort (ANSI). */
+#define SIGIOT 6 /* IOT trap (4.2 BSD). */
+#define SIGBUS 7 /* BUS error (4.2 BSD). */
+#define SIGFPE 8 /* Floating-point exception (ANSI). */
+#define SIGKILL 9 /* Kill, unblockable (POSIX). */
+#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
+#define SIGSEGV 11 /* Segmentation violation (ANSI). */
+#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
+#define SIGPIPE 13 /* Broken pipe (POSIX). */
+#define SIGALRM 14 /* Alarm clock (POSIX). */
+#define SIGTERM 15 /* Termination (ANSI). */
+#define SIGSTKFLT 16 /* Stack fault. */
+#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
+#define SIGCHLD 17 /* Child status has changed (POSIX). */
+#define SIGCONT 18 /* Continue (POSIX). */
+#define SIGSTOP 19 /* Stop, unblockable (POSIX). */
+#define SIGTSTP 20 /* Keyboard stop (POSIX). */
+#define SIGTTIN 21 /* Background read from tty (POSIX). */
+#define SIGTTOU 22 /* Background write to tty (POSIX). */
+#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */
+#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */
+#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */
+#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */
+#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */
+#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
+#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
+#define SIGIO 29 /* I/O now possible (4.2 BSD). */
+#define SIGPWR 30 /* Power failure restart (System V). */
+#define SIGSYS 31 /* Bad system call. */
+#define SIGUNUSED 31
+
+int
+raise(int sig);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SGX_SIGNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.c
new file mode 100644
index 000000000..afb6d6014
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.c
@@ -0,0 +1,1222 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#ifndef SGX_DISABLE_WASI
+
+#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
+
+/** OCALLs prototypes **/
+int
+ocall_accept(int *p_ret, int sockfd, void *addr, uint32_t *addrlen,
+ uint32_t addr_size);
+
+int
+ocall_bind(int *p_ret, int sockfd, const void *addr, uint32_t addrlen);
+
+int
+ocall_close(int *p_ret, int fd);
+
+int
+ocall_connect(int *p_ret, int sockfd, void *addr, uint32_t addrlen);
+
+int
+ocall_fcntl_long(int *p_ret, int fd, int cmd, long arg);
+
+int
+ocall_getsockname(int *p_ret, int sockfd, void *addr, uint32_t *addrlen,
+ uint32_t addr_size);
+
+int
+ocall_getpeername(int *p_ret, int sockfd, void *addr, uint32_t *addrlen,
+ uint32_t addr_size);
+
+int
+ocall_getsockopt(int *p_ret, int sockfd, int level, int optname, void *val_buf,
+ unsigned int val_buf_size, void *len_buf);
+
+int
+ocall_listen(int *p_ret, int sockfd, int backlog);
+
+int
+ocall_recv(int *p_ret, int sockfd, void *buf, size_t len, int flags);
+
+int
+ocall_recvfrom(ssize_t *p_ret, int sockfd, void *buf, size_t len, int flags,
+ void *src_addr, uint32_t *addrlen, uint32_t addr_size);
+
+int
+ocall_recvmsg(ssize_t *p_ret, int sockfd, void *msg_buf,
+ unsigned int msg_buf_size, int flags);
+
+int
+ocall_send(int *p_ret, int sockfd, const void *buf, size_t len, int flags);
+
+int
+ocall_sendto(ssize_t *p_ret, int sockfd, const void *buf, size_t len, int flags,
+ void *dest_addr, uint32_t addrlen);
+
+int
+ocall_sendmsg(ssize_t *p_ret, int sockfd, void *msg_buf,
+ unsigned int msg_buf_size, int flags);
+
+int
+ocall_setsockopt(int *p_ret, int sockfd, int level, int optname, void *optval,
+ unsigned int optlen);
+
+int
+ocall_shutdown(int *p_ret, int sockfd, int how);
+
+int
+ocall_socket(int *p_ret, int domain, int type, int protocol);
+/** OCALLs prototypes end **/
+
+/** In-enclave implementation of POSIX functions **/
+static bool
+is_little_endian()
+{
+ long i = 0x01020304;
+ unsigned char *c = (unsigned char *)&i;
+ return (*c == 0x04) ? true : false;
+}
+
+static void
+swap32(uint8 *pData)
+{
+ uint8 value = *pData;
+ *pData = *(pData + 3);
+ *(pData + 3) = value;
+
+ value = *(pData + 1);
+ *(pData + 1) = *(pData + 2);
+ *(pData + 2) = value;
+}
+
+static void
+swap16(uint8 *pData)
+{
+ uint8 value = *pData;
+ *(pData) = *(pData + 1);
+ *(pData + 1) = value;
+}
+
+uint32
+htonl(uint32 value)
+{
+ uint32 ret;
+ if (is_little_endian()) {
+ ret = value;
+ swap32((uint8 *)&ret);
+ return ret;
+ }
+
+ return value;
+}
+
+uint32
+ntohl(uint32 value)
+{
+ return htonl(value);
+}
+
+uint16
+htons(uint16 value)
+{
+ uint16 ret;
+ if (is_little_endian()) {
+ ret = value;
+ swap16((uint8 *)&ret);
+ return ret;
+ }
+
+ return value;
+}
+
+static uint16
+ntohs(uint16 value)
+{
+ return htons(value);
+}
+
+/* Coming from musl, under MIT license */
+static int
+hexval(unsigned c)
+{
+ if (c - '0' < 10)
+ return c - '0';
+ c |= 32;
+ if (c - 'a' < 6)
+ return c - 'a' + 10;
+ return -1;
+}
+
+/* Coming from musl, under MIT license */
+static int
+inet_pton(int af, const char *restrict s, void *restrict a0)
+{
+ uint16_t ip[8];
+ unsigned char *a = a0;
+ int i, j, v, d, brk = -1, need_v4 = 0;
+
+ if (af == AF_INET) {
+ for (i = 0; i < 4; i++) {
+ for (v = j = 0; j < 3 && isdigit(s[j]); j++)
+ v = 10 * v + s[j] - '0';
+ if (j == 0 || (j > 1 && s[0] == '0') || v > 255)
+ return 0;
+ a[i] = v;
+ if (s[j] == 0 && i == 3)
+ return 1;
+ if (s[j] != '.')
+ return 0;
+ s += j + 1;
+ }
+ return 0;
+ }
+ else if (af != AF_INET6) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (*s == ':' && *++s != ':')
+ return 0;
+
+ for (i = 0;; i++) {
+ if (s[0] == ':' && brk < 0) {
+ brk = i;
+ ip[i & 7] = 0;
+ if (!*++s)
+ break;
+ if (i == 7)
+ return 0;
+ continue;
+ }
+ for (v = j = 0; j < 4 && (d = hexval(s[j])) >= 0; j++)
+ v = 16 * v + d;
+ if (j == 0)
+ return 0;
+ ip[i & 7] = v;
+ if (!s[j] && (brk >= 0 || i == 7))
+ break;
+ if (i == 7)
+ return 0;
+ if (s[j] != ':') {
+ if (s[j] != '.' || (i < 6 && brk < 0))
+ return 0;
+ need_v4 = 1;
+ i++;
+ break;
+ }
+ s += j + 1;
+ }
+ if (brk >= 0) {
+ memmove(ip + brk + 7 - i, ip + brk, 2 * (i + 1 - brk));
+ for (j = 0; j < 7 - i; j++)
+ ip[brk + j] = 0;
+ }
+ for (j = 0; j < 8; j++) {
+ *a++ = ip[j] >> 8;
+ *a++ = ip[j];
+ }
+ if (need_v4 && inet_pton(AF_INET, (void *)s, a - 4) <= 0)
+ return 0;
+ return 1;
+}
+
+static int
+inet_addr(const char *p)
+{
+ struct in_addr a;
+ if (!inet_pton(AF_INET, p, &a))
+ return -1;
+ return a.s_addr;
+}
+/** In-enclave implementation of POSIX functions end **/
+
+static int
+textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr_in *out)
+{
+ assert(textual);
+
+ out->sin_family = AF_INET;
+ out->sin_port = htons(port);
+ out->sin_addr.s_addr = inet_addr(textual);
+
+ return BHT_OK;
+}
+
+static int
+sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen,
+ bh_sockaddr_t *bh_sockaddr)
+{
+ switch (sockaddr->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
+
+ assert(socklen >= sizeof(struct sockaddr_in));
+
+ bh_sockaddr->port = ntohs(addr->sin_port);
+ bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
+ bh_sockaddr->is_ipv4 = true;
+ return BHT_OK;
+ }
+ default:
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+ }
+}
+
+static int
+bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
+ struct sockaddr *sockaddr, socklen_t *socklen)
+{
+ if (bh_sockaddr->is_ipv4) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
+ addr->sin_port = htons(bh_sockaddr->port);
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4);
+ *socklen = sizeof(*addr);
+ return BHT_OK;
+ }
+ else {
+ errno = EAFNOSUPPORT;
+ return BHT_ERROR;
+ }
+}
+
+static int
+os_socket_setbooloption(bh_socket_t socket, int level, int optname,
+ bool is_enabled)
+{
+ int option = (int)is_enabled;
+ int ret;
+
+ if (ocall_setsockopt(&ret, socket, level, optname, &option, sizeof(option))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return BHT_ERROR;
+ }
+
+ if (ret != 0) {
+ errno = get_errno();
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+static int
+os_socket_getbooloption(bh_socket_t socket, int level, int optname,
+ bool *is_enabled)
+{
+ assert(is_enabled);
+
+ int optval;
+ socklen_t optval_size = sizeof(optval);
+ int ret;
+ if (ocall_getsockopt(&ret, socket, level, optname, &optval, optval_size,
+ &optval_size)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return BHT_ERROR;
+ }
+
+ if (ret != 0) {
+ errno = get_errno();
+ return BHT_ERROR;
+ }
+
+ *is_enabled = (bool)optval;
+ return BHT_OK;
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ int ret;
+
+ if (ocall_socket(&ret, domain, type, protocol) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
+{
+ int ret;
+ unsigned int val_buf_size = *optlen;
+
+ if (ocall_getsockopt(&ret, sockfd, level, optname, optval, val_buf_size,
+ (void *)optlen)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+setsockopt(int sockfd, int level, int optname, const void *optval,
+ socklen_t optlen)
+{
+ int ret;
+
+ if (ocall_setsockopt(&ret, sockfd, level, optname, (void *)optval, optlen)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+ssize_t
+sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+ ssize_t ret;
+ int i;
+ char *p;
+ struct msghdr *msg1;
+
+ uint64 total_size = sizeof(struct msghdr) + (uint64)msg->msg_namelen
+ + (uint64)msg->msg_controllen;
+
+ total_size += sizeof(struct iovec) * (msg->msg_iovlen);
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ total_size += msg->msg_iov[i].iov_len;
+ }
+
+ if (total_size >= UINT32_MAX)
+ return -1;
+
+ msg1 = BH_MALLOC((uint32)total_size);
+
+ if (msg1 == NULL)
+ return -1;
+
+ p = (char *)(uintptr_t)sizeof(struct msghdr);
+
+ if (msg->msg_name != NULL) {
+ msg1->msg_name = p;
+ memcpy((uintptr_t)p + (char *)msg1, msg->msg_name,
+ (size_t)msg->msg_namelen);
+ p += msg->msg_namelen;
+ }
+
+ if (msg->msg_control != NULL) {
+ msg1->msg_control = p;
+ memcpy((uintptr_t)p + (char *)msg1, msg->msg_control,
+ (size_t)msg->msg_control);
+ p += msg->msg_controllen;
+ }
+
+ if (msg->msg_iov != NULL) {
+ msg1->msg_iov = (struct iovec *)p;
+ p += (uintptr_t)(sizeof(struct iovec) * (msg->msg_iovlen));
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ msg1->msg_iov[i].iov_base = p;
+ msg1->msg_iov[i].iov_len = msg->msg_iov[i].iov_len;
+ memcpy((uintptr_t)p + (char *)msg1, msg->msg_iov[i].iov_base,
+ (size_t)(msg->msg_iov[i].iov_len));
+ p += msg->msg_iov[i].iov_len;
+ }
+ }
+
+ if (ocall_sendmsg(&ret, sockfd, (void *)msg1, (uint32)total_size, flags)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+ssize_t
+recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+ ssize_t ret;
+ int i;
+ char *p;
+ struct msghdr *msg1;
+
+ uint64 total_size = sizeof(struct msghdr) + (uint64)msg->msg_namelen
+ + (uint64)msg->msg_controllen;
+
+ total_size += sizeof(struct iovec) * (msg->msg_iovlen);
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ total_size += msg->msg_iov[i].iov_len;
+ }
+
+ if (total_size >= UINT32_MAX)
+ return -1;
+
+ msg1 = BH_MALLOC((uint32)total_size);
+
+ if (msg1 == NULL)
+ return -1;
+
+ memset(msg1, 0, total_size);
+
+ p = (char *)(uintptr_t)sizeof(struct msghdr);
+
+ if (msg->msg_name != NULL) {
+ msg1->msg_name = p;
+ p += msg->msg_namelen;
+ }
+
+ if (msg->msg_control != NULL) {
+ msg1->msg_control = p;
+ p += msg->msg_controllen;
+ }
+
+ if (msg->msg_iov != NULL) {
+ msg1->msg_iov = (struct iovec *)p;
+ p += (uintptr_t)(sizeof(struct iovec) * (msg->msg_iovlen));
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ msg1->msg_iov[i].iov_base = p;
+ msg1->msg_iov[i].iov_len = msg->msg_iov[i].iov_len;
+ p += msg->msg_iov[i].iov_len;
+ }
+ }
+
+ if (ocall_recvmsg(&ret, sockfd, (void *)msg1, (uint32)total_size, flags)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ p = (char *)(uintptr_t)(sizeof(struct msghdr));
+
+ if (msg1->msg_name != NULL) {
+ memcpy(msg->msg_name, (uintptr_t)p + (char *)msg1,
+ (size_t)msg1->msg_namelen);
+ p += msg1->msg_namelen;
+ }
+
+ if (msg1->msg_control != NULL) {
+ memcpy(msg->msg_control, (uintptr_t)p + (char *)msg1,
+ (size_t)msg1->msg_control);
+ p += msg->msg_controllen;
+ }
+
+ if (msg1->msg_iov != NULL) {
+ p += (uintptr_t)(sizeof(struct iovec) * (msg1->msg_iovlen));
+
+ for (i = 0; i < msg1->msg_iovlen; i++) {
+ memcpy(msg->msg_iov[i].iov_base, (uintptr_t)p + (char *)msg1,
+ (size_t)(msg1->msg_iov[i].iov_len));
+ p += msg1->msg_iov[i].iov_len;
+ }
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+shutdown(int sockfd, int how)
+{
+ int ret;
+
+ if (ocall_shutdown(&ret, sockfd, how) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
+ unsigned int *addrlen)
+
+{
+ struct sockaddr addr_tmp;
+ unsigned int len = sizeof(struct sockaddr);
+
+ if (ocall_accept(sock, server_sock, &addr_tmp, &len, len) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (*sock < 0) {
+ errno = get_errno();
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+int
+os_socket_bind(bh_socket_t socket, const char *host, int *port)
+{
+ struct sockaddr_in addr;
+ struct linger ling;
+ unsigned int socklen;
+ int ret;
+
+ assert(host);
+ assert(port);
+
+ ling.l_onoff = 1;
+ ling.l_linger = 0;
+
+ if (ocall_fcntl_long(&ret, socket, F_SETFD, FD_CLOEXEC) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret < 0) {
+ goto fail;
+ }
+
+ if (ocall_setsockopt(&ret, socket, SOL_SOCKET, SO_LINGER, &ling,
+ sizeof(ling))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret < 0) {
+ goto fail;
+ }
+
+ addr.sin_addr.s_addr = inet_addr(host);
+ addr.sin_port = htons(*port);
+ addr.sin_family = AF_INET;
+
+ if (ocall_bind(&ret, socket, &addr, sizeof(addr)) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret < 0) {
+ goto fail;
+ }
+
+ socklen = sizeof(addr);
+
+ if (ocall_getsockname(&ret, socket, (void *)&addr, &socklen, socklen)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1) {
+ goto fail;
+ }
+
+ *port = ntohs(addr.sin_port);
+
+ return BHT_OK;
+
+fail:
+ errno = get_errno();
+ return BHT_ERROR;
+}
+
+int
+os_socket_close(bh_socket_t socket)
+{
+ int ret;
+
+ if (ocall_close(&ret, socket) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+os_socket_connect(bh_socket_t socket, const char *addr, int port)
+{
+ struct sockaddr_in addr_in = { 0 };
+ socklen_t addr_len = sizeof(struct sockaddr_in);
+ int ret = 0;
+
+ if ((ret = textual_addr_to_sockaddr(addr, port, &addr_in)) < 0) {
+ return ret;
+ }
+
+ if (ocall_connect(&ret, socket, &addr_in, addr_len) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
+{
+ int af;
+
+ if (!sock) {
+ return BHT_ERROR;
+ }
+
+ if (is_ipv4) {
+ af = AF_INET;
+ }
+ else {
+ errno = ENOSYS;
+ return BHT_ERROR;
+ }
+
+ if (is_tcp) {
+ if (ocall_socket(sock, af, SOCK_STREAM, IPPROTO_TCP) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ }
+ else {
+ if (ocall_socket(sock, af, SOCK_DGRAM, 0) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+ }
+
+ if (*sock == -1) {
+ errno = get_errno();
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
+{
+ if (!cp)
+ return BHT_ERROR;
+
+ if (is_ipv4) {
+ if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
+ return BHT_ERROR;
+ }
+ /* Note: ntohl(INADDR_NONE) == INADDR_NONE */
+ out->ipv4 = ntohl(out->ipv4);
+ }
+ else {
+ if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
+ return BHT_ERROR;
+ }
+ for (int i = 0; i < 8; i++) {
+ out->ipv6[i] = ntohs(out->ipv6[i]);
+ }
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_listen(bh_socket_t socket, int max_client)
+{
+ int ret;
+
+ if (ocall_listen(&ret, socket, max_client) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
+{
+ int ret;
+
+ if (ocall_recv(&ret, socket, buf, len, 0) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
+ bh_sockaddr_t *src_addr)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ ssize_t ret;
+
+ if (ocall_recvfrom(&ret, socket, buf, len, flags, &addr, &addr_len,
+ addr_len)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (ret < 0) {
+ errno = get_errno();
+ return ret;
+ }
+
+ if (src_addr && addr_len > 0) {
+ if (sockaddr_to_bh_sockaddr((struct sockaddr *)&addr, addr_len,
+ src_addr)
+ == BHT_ERROR) {
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+int
+os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
+{
+ int ret;
+
+ if (ocall_send(&ret, socket, buf, len, 0) != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
+ int flags, const bh_sockaddr_t *dest_addr)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len;
+ ssize_t ret;
+
+ if (bh_sockaddr_to_sockaddr(dest_addr, (struct sockaddr *)&addr, &addr_len)
+ == BHT_ERROR) {
+ return -1;
+ }
+
+ if (ocall_sendto(&ret, socket, buf, len, flags, (struct sockaddr *)&addr,
+ addr_len)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (ret == -1) {
+ errno = get_errno();
+ }
+
+ return ret;
+}
+
+int
+os_socket_shutdown(bh_socket_t socket)
+{
+ return shutdown(socket, O_RDWR);
+}
+
+int
+os_socket_addr_resolve(const char *host, const char *service,
+ uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
+ bh_addr_info_t *addr_info, size_t addr_info_size,
+ size_t *max_info_size)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ int ret;
+
+ if (ocall_getsockname(&ret, socket, (struct sockaddr *)&addr, &addr_len,
+ addr_len)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return BHT_ERROR;
+ }
+
+ if (ret != BHT_OK) {
+ errno = get_errno();
+ return BHT_ERROR;
+ }
+
+ return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr, addr_len,
+ sockaddr);
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ int ret;
+
+ if (ocall_getpeername(&ret, socket, (void *)&addr, &addr_len, addr_len)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret != BHT_OK) {
+ errno = get_errno();
+ return BHT_ERROR;
+ }
+
+ return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr, addr_len,
+ sockaddr);
+}
+
+int
+os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
+ is_enabled);
+}
+
+int
+os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
+ is_enabled);
+}
+
+int
+os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
+ is_enabled);
+}
+
+int
+os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
+ is_enabled);
+}
+
+int
+os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
+ is_enabled);
+}
+
+int
+os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
+ is_enabled);
+}
+
+int
+os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_NODELAY,
+ is_enabled);
+}
+
+int
+os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_NODELAY,
+ is_enabled);
+}
+
+int
+os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_QUICKACK,
+ is_enabled);
+}
+
+int
+os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_QUICKACK,
+ is_enabled);
+}
+
+int
+os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+ is_enabled);
+}
+
+int
+os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+ is_enabled);
+}
+
+int
+os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled)
+{
+ if (ipv6) {
+ return os_socket_setbooloption(socket, IPPROTO_IPV6,
+ IPV6_MULTICAST_LOOP, is_enabled);
+ }
+ else {
+ return os_socket_setbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
+ is_enabled);
+ }
+}
+
+int
+os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled)
+{
+ if (ipv6) {
+ return os_socket_getbooloption(socket, IPPROTO_IPV6,
+ IPV6_MULTICAST_LOOP, is_enabled);
+ }
+ else {
+ return os_socket_getbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP,
+ is_enabled);
+ }
+}
+
+int
+os_socket_set_ip_add_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_drop_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
+ is_enabled);
+}
+
+int
+os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
+ is_enabled);
+}
+
+int
+os_socket_set_broadcast(bh_socket_t socket, bool is_enabled)
+{
+ return os_socket_setbooloption(socket, SOL_SOCKET, SO_BROADCAST,
+ is_enabled);
+}
+
+int
+os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled)
+{
+ return os_socket_getbooloption(socket, SOL_SOCKET, SO_BROADCAST,
+ is_enabled);
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.h
new file mode 100644
index 000000000..edf977dd6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_socket.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SGX_SOCKET_H
+#define _SGX_SOCKET_H
+
+#include "sgx_file.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For setsockopt(2) */
+#define SOL_SOCKET 1
+
+#define SO_DEBUG 1
+#define SO_REUSEADDR 2
+#define SO_TYPE 3
+#define SO_ERROR 4
+#define SO_DONTROUTE 5
+#define SO_BROADCAST 6
+#define SO_SNDBUF 7
+#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE 9
+#define SO_OOBINLINE 10
+#define SO_NO_CHECK 11
+#define SO_PRIORITY 12
+#define SO_LINGER 13
+#define SO_BSDCOMPAT 14
+#define SO_REUSEPORT 15
+#define SO_PASSCRED 16
+#define SO_PEERCRED 17
+#define SO_RCVLOWAT 18
+#define SO_SNDLOWAT 19
+#define SO_RCVTIMEO_OLD 20
+#define SO_SNDTIMEO_OLD 21
+
+/* User-settable options (used with setsockopt) */
+#define TCP_NODELAY 1 /* Don't delay send to coalesce packets */
+#define TCP_MAXSEG 2 /* Set maximum segment size */
+#define TCP_CORK 3 /* Control sending of partial frames */
+#define TCP_KEEPIDLE 4 /* Start keeplives after this period */
+#define TCP_KEEPINTVL 5 /* Interval between keepalives */
+#define TCP_KEEPCNT 6 /* Number of keepalives before death */
+#define TCP_SYNCNT 7 /* Number of SYN retransmits */
+#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */
+#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */
+#define TCP_INFO 11 /* Information about this connection. */
+#define TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */
+#define TCP_CONGESTION 13 /* Congestion control algorithm. */
+#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */
+#define TCP_COOKIE_TRANSACTIONS 15 /* TCP Cookie Transactions */
+#define TCP_THIN_LINEAR_TIMEOUTS 16 /* Use linear timeouts for thin streams*/
+#define TCP_THIN_DUPACK 17 /* Fast retrans. after 1 dupack */
+#define TCP_USER_TIMEOUT 18 /* How long for loss retry before timeout */
+#define TCP_REPAIR 19 /* TCP sock is under repair right now */
+#define TCP_REPAIR_QUEUE 20 /* Set TCP queue to repair */
+#define TCP_QUEUE_SEQ 21 /* Set sequence number of repaired queue. */
+#define TCP_REPAIR_OPTIONS 22 /* Repair TCP connection options */
+#define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */
+#define TCP_TIMESTAMP 24 /* TCP time stamp */
+#define TCP_NOTSENT_LOWAT \
+ 25 /* Limit number of unsent bytes in write queue. \
+ */
+#define TCP_CC_INFO 26 /* Get Congestion Control (optional) info. */
+#define TCP_SAVE_SYN 27 /* Record SYN headers for new connections. */
+#define TCP_SAVED_SYN 28 /* Get SYN headers recorded for connection. */
+#define TCP_REPAIR_WINDOW 29 /* Get/set window parameters. */
+#define TCP_FASTOPEN_CONNECT 30 /* Attempt FastOpen with connect. */
+#define TCP_ULP 31 /* Attach a ULP to a TCP connection. */
+#define TCP_MD5SIG_EXT 32 /* TCP MD5 Signature with extensions. */
+#define TCP_FASTOPEN_KEY 33 /* Set the key for Fast Open (cookie). */
+#define TCP_FASTOPEN_NO_COOKIE 34 /* Enable TFO without a TFO cookie. */
+#define TCP_ZEROCOPY_RECEIVE 35
+#define TCP_INQ 36 /* Notify bytes available to read as a cmsg on read. */
+#define TCP_CM_INQ TCP_INQ
+#define TCP_TX_DELAY 37 /* Delay outgoing packets by XX usec. */
+
+/* Standard well-defined IP protocols. */
+#define IPPROTO_IP 0 /* Dummy protocol for TCP. */
+#define IPPROTO_ICMP 1 /* Internet Control Message Protocol. */
+#define IPPROTO_IGMP 2 /* Internet Group Management Protocol. */
+#define IPPROTO_IPIP 4 /* IPIP tunnels (older KA9Q tunnels use 94). */
+#define IPPROTO_TCP 6 /* Transmission Control Protocol. */
+#define IPPROTO_EGP 8 /* Exterior Gateway Protocol. */
+#define IPPROTO_PUP 12 /* PUP protocol. */
+#define IPPROTO_UDP 17 /* User Datagram Protocol. */
+#define IPPROTO_IDP 22 /* XNS IDP protocol. */
+#define IPPROTO_TP 29 /* SO Transport Protocol Class 4. */
+#define IPPROTO_DCCP 33 /* Datagram Congestion Control Protocol. */
+#define IPPROTO_IPV6 41 /* IPv6 header. */
+#define IPPROTO_RSVP 46 /* Reservation Protocol. */
+#define IPPROTO_GRE 47 /* General Routing Encapsulation. */
+#define IPPROTO_ESP 50 /* encapsulating security payload. */
+#define IPPROTO_AH 51 /* authentication header. */
+#define IPPROTO_MTP 92 /* Multicast Transport Protocol. */
+#define IPPROTO_BEETPH 94 /* IP option pseudo header for BEET. */
+#define IPPROTO_ENCAP 98 /* Encapsulation Header. */
+#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */
+#define IPPROTO_COMP 108 /* Compression Header Protocol. */
+#define IPPROTO_SCTP 132 /* Stream Control Transmission Protocol. */
+#define IPPROTO_UDPLITE 136 /* UDP-Lite protocol. */
+#define IPPROTO_MPLS 137 /* MPLS in IP. */
+#define IPPROTO_RAW 255 /* Raw IP packets. */
+
+#define IP_ROUTER_ALERT 5 /* bool */
+#define IP_PKTINFO 8 /* bool */
+#define IP_PKTOPTIONS 9
+#define IP_PMTUDISC 10 /* obsolete name? */
+#define IP_MTU_DISCOVER 10 /* int; see below */
+#define IP_RECVERR 11 /* bool */
+#define IP_RECVTTL 12 /* bool */
+#define IP_RECVTOS 13 /* bool */
+#define IP_MTU 14 /* int */
+#define IP_FREEBIND 15
+#define IP_IPSEC_POLICY 16
+#define IP_XFRM_POLICY 17
+#define IP_PASSSEC 18
+#define IP_TRANSPARENT 19
+#define IP_MULTICAST_ALL 49 /* bool */
+
+/* TProxy original addresses */
+#define IP_ORIGDSTADDR 20
+#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR
+#define IP_MINTTL 21
+#define IP_NODEFRAG 22
+#define IP_CHECKSUM 23
+#define IP_BIND_ADDRESS_NO_PORT 24
+#define IP_RECVFRAGSIZE 25
+#define IP_PMTUDISC_DONT 0
+#define IP_PMTUDISC_WANT 1
+#define IP_PMTUDISC_DO 2
+#define IP_PMTUDISC_PROBE 3
+#define IP_PMTUDISC_INTERFACE 4
+#define IP_PMTUDISC_OMIT 5
+#define IP_MULTICAST_IF 32
+#define IP_MULTICAST_TTL 33
+#define IP_MULTICAST_LOOP 34
+#define IP_ADD_MEMBERSHIP 35
+#define IP_DROP_MEMBERSHIP 36
+#define IP_UNBLOCK_SOURCE 37
+#define IP_BLOCK_SOURCE 38
+#define IP_ADD_SOURCE_MEMBERSHIP 39
+#define IP_DROP_SOURCE_MEMBERSHIP 40
+#define IP_MSFILTER 41
+#define IP_MULTICAST_ALL 49
+#define IP_UNICAST_IF 50
+
+#define IPV6_ADDRFORM 1
+#define IPV6_2292PKTINFO 2
+#define IPV6_2292HOPOPTS 3
+#define IPV6_2292DSTOPTS 4
+#define IPV6_2292RTHDR 5
+#define IPV6_2292PKTOPTIONS 6
+#define IPV6_CHECKSUM 7
+#define IPV6_2292HOPLIMIT 8
+
+#define SCM_SRCRT IPV6_RXSRCRT
+
+#define IPV6_NEXTHOP 9
+#define IPV6_AUTHHDR 10
+#define IPV6_UNICAST_HOPS 16
+#define IPV6_MULTICAST_IF 17
+#define IPV6_MULTICAST_HOPS 18
+#define IPV6_MULTICAST_LOOP 19
+#define IPV6_JOIN_GROUP 20
+#define IPV6_LEAVE_GROUP 21
+#define IPV6_ROUTER_ALERT 22
+#define IPV6_MTU_DISCOVER 23
+#define IPV6_MTU 24
+#define IPV6_RECVERR 25
+#define IPV6_V6ONLY 26
+#define IPV6_JOIN_ANYCAST 27
+#define IPV6_LEAVE_ANYCAST 28
+#define IPV6_MULTICAST_ALL 29
+#define IPV6_ROUTER_ALERT_ISOLATE 30
+#define IPV6_IPSEC_POLICY 34
+#define IPV6_XFRM_POLICY 35
+#define IPV6_HDRINCL 36
+
+/* Advanced API (RFC3542) (1). */
+#define IPV6_RECVPKTINFO 49
+#define IPV6_PKTINFO 50
+#define IPV6_RECVHOPLIMIT 51
+#define IPV6_HOPLIMIT 52
+#define IPV6_RECVHOPOPTS 53
+#define IPV6_HOPOPTS 54
+#define IPV6_RTHDRDSTOPTS 55
+#define IPV6_RECVRTHDR 56
+#define IPV6_RTHDR 57
+#define IPV6_RECVDSTOPTS 58
+#define IPV6_DSTOPTS 59
+#define IPV6_RECVPATHMTU 60
+#define IPV6_PATHMTU 61
+#define IPV6_DONTFRAG 62
+
+/* Advanced API (RFC3542) (2). */
+#define IPV6_RECVTCLASS 66
+#define IPV6_TCLASS 67
+
+#define IPV6_AUTOFLOWLABEL 70
+
+/* RFC5014. */
+#define IPV6_ADDR_PREFERENCES 72
+
+/* RFC5082. */
+#define IPV6_MINHOPCOUNT 73
+
+#define IPV6_ORIGDSTADDR 74
+#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
+#define IPV6_TRANSPARENT 75
+#define IPV6_UNICAST_IF 76
+#define IPV6_RECVFRAGSIZE 77
+#define IPV6_FREEBIND 78
+
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+
+#define MSG_OOB 0x0001
+#define MSG_PEEK 0x0002
+#define MSG_DONTROUTE 0x0004
+#define MSG_CTRUNC 0x0008
+#define MSG_PROXY 0x0010
+#define MSG_TRUNC 0x0020
+#define MSG_DONTWAIT 0x0040
+#define MSG_EOR 0x0080
+#define MSG_WAITALL 0x0100
+#define MSG_FIN 0x0200
+#define MSG_SYN 0x0400
+#define MSG_CONFIRM 0x0800
+#define MSG_RST 0x1000
+#define MSG_ERRQUEUE 0x2000
+#define MSG_NOSIGNAL 0x4000
+#define MSG_MORE 0x8000
+#define MSG_WAITFORONE 0x10000
+#define MSG_BATCH 0x40000
+#define MSG_FASTOPEN 0x20000000
+#define MSG_CMSG_CLOEXEC 0x40000000
+
+#define SHUT_RD 0
+#define SHUT_WR 1
+#define SHUT_RDWR 2
+
+/* Address families. */
+#define AF_INET 2 /* IP protocol family. */
+#define AF_INET6 10 /* IP version 6. */
+
+/* Standard well-defined IP protocols. */
+#define IPPROTO_TCP 6 /* Transmission Control Protocol. */
+
+/* Types of sockets. */
+#define SOCK_DGRAM \
+ 2 /* Connectionless, unreliable datagrams of fixed maximum length. */
+
+struct msghdr {
+ void *msg_name;
+ socklen_t msg_namelen;
+ struct iovec *msg_iov;
+ int msg_iovlen;
+ void *msg_control;
+ socklen_t msg_controllen;
+ int msg_flags;
+};
+
+/* Internet address. */
+struct in_addr {
+ uint32_t s_addr;
+};
+typedef struct in_addr in_addr_t;
+
+/* Structure describing an Internet socket address. */
+#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
+struct sockaddr_in {
+ uint16_t sin_family;
+ uint16_t sin_port; /* Port number. */
+ struct in_addr sin_addr; /* Internet address. */
+
+ /* Pad to size of `struct sockaddr'. */
+ unsigned char__pad[__SOCK_SIZE__ - sizeof(uint16_t) - sizeof(uint16_t)
+ - sizeof(struct in_addr)];
+};
+
+/* Structure used to manipulate the SO_LINGER option. */
+struct linger {
+ int l_onoff; /* Nonzero to linger on close. */
+ int l_linger; /* Time to linger. */
+};
+
+/* Structure describing a generic socket address. */
+struct sockaddr {
+ unsigned short int sa_family; /* Common data: address family and length. */
+ char sa_data[14]; /* Address data. */
+};
+
+uint32_t
+ntohl(uint32_t value);
+
+uint32_t
+htonl(uint32_t value);
+
+uint16_t
+htons(uint16_t value);
+
+int
+socket(int domain, int type, int protocol);
+
+int
+getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
+
+int
+setsockopt(int sockfd, int level, int optname, const void *optval,
+ socklen_t optlen);
+
+ssize_t
+sendmsg(int sockfd, const struct msghdr *msg, int flags);
+
+ssize_t
+recvmsg(int sockfd, struct msghdr *msg, int flags);
+
+int
+shutdown(int sockfd, int how);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SGX_SOCKET_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_thread.c
new file mode 100644
index 000000000..1cb2f5d09
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_thread.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#ifndef SGX_DISABLE_PTHREAD
+typedef struct {
+ thread_start_routine_t start;
+ void *arg;
+} thread_wrapper_arg;
+
+static void *
+os_thread_wrapper(void *arg)
+{
+ thread_wrapper_arg *targ = arg;
+ thread_start_routine_t start_func = targ->start;
+ void *thread_arg = targ->arg;
+
+#if 0
+ os_printf("THREAD CREATED %p\n", &targ);
+#endif
+ BH_FREE(targ);
+ start_func(thread_arg);
+ return NULL;
+}
+
+int
+os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ thread_wrapper_arg *targ;
+
+ assert(tid);
+ assert(start);
+
+ targ = (thread_wrapper_arg *)BH_MALLOC(sizeof(*targ));
+ if (!targ) {
+ return BHT_ERROR;
+ }
+
+ targ->start = start;
+ targ->arg = arg;
+
+ if (pthread_create(tid, NULL, os_thread_wrapper, targ) != 0) {
+ BH_FREE(targ);
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+#endif
+
+korp_tid
+os_self_thread()
+{
+#ifndef SGX_DISABLE_PTHREAD
+ return pthread_self();
+#else
+ return 0;
+#endif
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+ *mutex = m;
+#endif
+ return BHT_OK;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ pthread_mutex_destroy(mutex);
+#endif
+ return BHT_OK;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ return pthread_mutex_lock(mutex);
+#else
+ return 0;
+#endif
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ return pthread_mutex_unlock(mutex);
+#else
+ return 0;
+#endif
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+ *cond = c;
+#endif
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ pthread_cond_destroy(cond);
+#endif
+ return BHT_OK;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ assert(cond);
+ assert(mutex);
+
+ if (pthread_cond_wait(cond, mutex) != BHT_OK)
+ return BHT_ERROR;
+
+#endif
+ return BHT_OK;
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ os_printf("warning: SGX pthread_cond_timedwait isn't supported, "
+ "calling pthread_cond_wait instead!\n");
+ return BHT_ERROR;
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ assert(cond);
+
+ if (pthread_cond_signal(cond) != BHT_OK)
+ return BHT_ERROR;
+
+#endif
+ return BHT_OK;
+}
+
+int
+os_cond_broadcast(korp_cond *cond)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ assert(cond);
+
+ if (pthread_cond_broadcast(cond) != BHT_OK)
+ return BHT_ERROR;
+
+#endif
+ return BHT_OK;
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ return pthread_join(thread, value_ptr);
+#else
+ return 0;
+#endif
+}
+
+int
+os_thread_detach(korp_tid thread)
+{
+ /* SGX pthread_detach isn't provided, return directly. */
+ return 0;
+}
+
+void
+os_thread_exit(void *retval)
+{
+#ifndef SGX_DISABLE_PTHREAD
+ pthread_exit(retval);
+#else
+ return;
+#endif
+}
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+ /* TODO: get sgx stack boundary */
+ return NULL;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.c
new file mode 100644
index 000000000..d090083ef
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+#define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__)
+#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
+
+int
+ocall_clock_gettime(int *p_ret, unsigned clock_id, void *tp_buf,
+ unsigned int tp_buf_size);
+int
+ocall_clock_getres(int *p_ret, int clock_id, void *res_buf,
+ unsigned int res_buf_size);
+int
+ocall_utimensat(int *p_ret, int dirfd, const char *pathname,
+ const void *times_buf, unsigned int times_buf_size, int flags);
+int
+ocall_futimens(int *p_ret, int fd, const void *times_buf,
+ unsigned int times_buf_size);
+int
+ocall_clock_nanosleep(int *p_ret, unsigned clock_id, int flags,
+ const void *req_buf, unsigned int req_buf_size,
+ const void *rem_buf, unsigned int rem_buf_size);
+
+uint64
+os_time_get_boot_microsecond()
+{
+#ifndef SGX_DISABLE_WASI
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
+ return 0;
+ }
+
+ return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000;
+#else
+ return 0;
+#endif
+}
+
+#ifndef SGX_DISABLE_WASI
+
+int
+clock_getres(int clock_id, struct timespec *res)
+{
+ int ret;
+
+ if (ocall_clock_getres(&ret, clock_id, (void *)res, sizeof(struct timespec))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+ int ret;
+
+ if (ocall_clock_gettime(&ret, clock_id, (void *)tp, sizeof(struct timespec))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+utimensat(int dirfd, const char *pathname, const struct timespec times[2],
+ int flags)
+{
+ int ret;
+
+ if (ocall_utimensat(&ret, dirfd, pathname, (void *)times,
+ sizeof(struct timespec) * 2, flags)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+futimens(int fd, const struct timespec times[2])
+{
+ int ret;
+
+ if (ocall_futimens(&ret, fd, (void *)times, sizeof(struct timespec) * 2)
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+int
+clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request,
+ struct timespec *remain)
+{
+ int ret;
+
+ if (ocall_clock_nanosleep(&ret, clock_id, flags, (void *)request,
+ sizeof(struct timespec), (void *)remain,
+ sizeof(struct timespec))
+ != SGX_SUCCESS) {
+ TRACE_OCALL_FAIL();
+ return -1;
+ }
+
+ if (ret == -1)
+ errno = get_errno();
+
+ return ret;
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.h
new file mode 100644
index 000000000..8267f1fa5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_time.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _SGX_TIME_H
+#define _SGX_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+#define CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOCK_THREAD_CPUTIME_ID 3
+
+#define UTIME_NOW 0x3fffffff
+#define UTIME_OMIT 0x3ffffffe
+#define TIMER_ABSTIME 1
+
+typedef long int time_t;
+
+typedef int clockid_t;
+
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+
+int
+clock_getres(int clock_id, struct timespec *res);
+
+int
+clock_gettime(clockid_t clock_id, struct timespec *tp);
+
+int
+utimensat(int dirfd, const char *pathname, const struct timespec times[2],
+ int flags);
+int
+futimens(int fd, const struct timespec times[2]);
+int
+clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request,
+ struct timespec *remain);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _SGX_TIME_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_wamr.edl b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_wamr.edl
new file mode 100644
index 000000000..7cb4817fd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/sgx_wamr.edl
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+enclave {
+ include "stdint.h"
+ include "stdbool.h"
+ include "unistd.h"
+
+ untrusted {
+ int ocall_open([in, string]const char *pathname, int flags,
+ bool has_mode, unsigned mode);
+ int ocall_openat(int dirfd,
+ [in, string]const char *pathname, int flags,
+ bool has_mode, unsigned mode);
+ int ocall_close(int fd);
+ ssize_t ocall_read(int fd, [out, size=read_size]void *buf,
+ size_t read_size);
+ off_t ocall_lseek(int fd, off_t offset, int whence);
+ int ocall_ftruncate(int fd, off_t length);
+ int ocall_fsync(int fd);
+ int ocall_fdatasync(int fd);
+ int ocall_isatty(int fd);
+ void ocall_fdopendir(int fd, [out]void **p_dirp);
+ /* implementation related to multiple thread */
+ void *ocall_readdir([user_check]void *dirp);
+ void ocall_rewinddir([user_check]void *dirp);
+ void ocall_seekdir([user_check]void *dirp, long loc);
+ long ocall_telldir([user_check]void *dirp);
+ int ocall_closedir([user_check]void *dirp);
+
+ int ocall_stat([in, string]const char *pathname,
+ [out, size=buf_len]void *buf,
+ unsigned int buf_len);
+ int ocall_fstat(int fd, [out, size=buf_len]void *buf,
+ unsigned int buf_len);
+ int ocall_fstatat(int dirfd, [in, string]const char *pathname,
+ [out, size=buf_len]void *buf,
+ unsigned int buf_len, int flags);
+
+ int ocall_mkdirat(int dirfd, [in, string]const char *pathname,
+ unsigned mode);
+ int ocall_link([in, string] const char *oldpath,
+ [in, string] const char *newpath);
+ int ocall_linkat(int olddirfd, [in, string]const char *oldpath,
+ int newdirfd, [in, string]const char *newpath,
+ int flags);
+ int ocall_unlinkat(int dirfd, [in, string]const char *pathname,
+ int flags);
+ ssize_t ocall_readlink([in, string]const char *pathname,
+ [out, size=bufsiz]char *buf,
+ size_t bufsiz);
+ ssize_t ocall_readlinkat(int dirfd,
+ [in, string]const char *pathname,
+ [out, size=bufsiz]char *buf,
+ size_t bufsiz);
+ int ocall_renameat(int olddirfd,
+ [in, string]const char *oldpath,
+ int newdirfd,
+ [in, string]const char *newpath);
+ int ocall_symlinkat([in ,string]const char *target,
+ int newdirfd,
+ [in, string]const char *linkpath);
+
+ int ocall_ioctl(int fd, unsigned long request,
+ [out, size=arg_len]void *arg,
+ unsigned int arg_len);
+ int ocall_fcntl(int fd, int cmd);
+ int ocall_fcntl_long(int fd, int cmd, long arg);
+
+ int ocall_realpath([in, string]const char *path,
+ [out, size=buf_len]char *buf,
+ unsigned int buf_len);
+ int ocall_posix_fallocate(int fd, off_t offset, off_t len);
+ int ocall_poll([in, out, size=fds_len]void *fds, unsigned nfds,
+ int timeout, unsigned int fds_len);
+
+ int ocall_getopt(int argc,
+ [in, size=argv_buf_len]char *argv_buf,
+ unsigned int argv_buf_len,
+ [in, string]const char *optstring);
+ ssize_t ocall_readv(int fd,
+ [in, out, size=buf_size]char *iov_buf,
+ unsigned int buf_size, int iovcnt,
+ bool has_offset, off_t offset);
+ ssize_t ocall_writev(int fd,
+ [in, size=buf_size]char *iov_buf,
+ unsigned int buf_size, int iovcnt,
+ bool has_offset, off_t offset);
+
+ /* time clock */
+ int ocall_clock_gettime(unsigned clock_id,
+ [out, size=tp_buf_size]void *tp_buf,
+ unsigned int tp_buf_size);
+ int ocall_clock_getres(int clock_id,
+ [out, size=res_buf_size]void *res_buf,
+ unsigned int res_buf_size);
+ int ocall_utimensat(int dirfd, [in, string]const char *pathname,
+ [in, size=times_buf_size]const void *times_buf,
+ unsigned int times_buf_size, int flags);
+ int ocall_futimens(int fd, [in, size=times_buf_size]const void *times_buf,
+ unsigned int times_buf_size);
+ int ocall_clock_nanosleep(unsigned clock_id, int flags,
+ [in, size=req_buf_size]const void *req_buf,
+ unsigned int req_buf_size,
+ [out, size=rem_buf_size]void *rem_buf,
+ unsigned int rem_buf_size);
+
+ int ocall_raise(int sig);
+
+ int ocall_sched_yield();
+
+ int ocall_pthread_rwlock_init([out]void **rwlock, [user_check]void *attr);
+ int ocall_pthread_rwlock_destroy([user_check]void *rwlock);
+ int ocall_pthread_rwlock_rdlock([user_check]void *rwlock);
+ int ocall_pthread_rwlock_wrlock([user_check]void *rwlock);
+ int ocall_pthread_rwlock_unlock([user_check]void *rwlock);
+
+ int ocall_get_errno();
+
+ /* sockets */
+ int ocall_accept(int sockfd, [in, size=addr_size]void *addr,
+ [in, size=4] uint32_t *addrlen, uint32_t addr_size);
+ int ocall_bind(int sockfd, [in, size=addrlen]const void *addr,
+ uint32_t addrlen);
+ int ocall_connect(int sockfd, [in, size=addrlen]void *addr, uint32_t addrlen);
+ int ocall_getsockname(int sockfd, [out, size=addr_size]void *addr,
+ [in, out, size=4]uint32_t *addrlen, uint32_t addr_size);
+ int ocall_getpeername(int sockfd, [out, size=addr_size]void *addr,
+ [in, out, size=4]uint32_t *addrlen, uint32_t addr_size);
+ int ocall_getsockopt(int sockfd, int level, int optname,
+ [out, size=val_buf_size]void *val_buf,
+ unsigned int val_buf_size,
+ [in, out, size=4]void *len_buf);
+ int ocall_listen(int sockfd, int backlog);
+ int ocall_recv(int sockfd, [out, size=len]void *buf, size_t len, int flags);
+ ssize_t ocall_recvfrom(int sockfd, [out, size=len]void *buf, size_t len, int flags,
+ [out, size=addr_size]void *src_addr,
+ [in, out, size=4]uint32_t *addrlen, uint32_t addr_size);
+ ssize_t ocall_recvmsg(int sockfd,
+ [in, out, size=msg_buf_size]void *msg_buf,
+ unsigned int msg_buf_size,
+ int flags);
+ int ocall_send(int sockfd, [in, size=len]const void *buf, size_t len, int flags);
+ ssize_t ocall_sendto(int sockfd, [in, size=len]const void *buf, size_t len, int flags,
+ [in, size=addrlen]void *dest_addr, uint32_t addrlen);
+ ssize_t ocall_sendmsg(int sockfd,
+ [in, size=msg_buf_size]void *msg_buf,
+ unsigned int msg_buf_size,
+ int flags);
+ int ocall_setsockopt(int sockfd, int level, int optname,
+ [in, size=optlen]void *optval,
+ unsigned int optlen);
+ int ocall_shutdown(int sockfd, int how);
+ int ocall_socket(int domain, int type, int protocol);
+ };
+};
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/shared_platform.cmake
new file mode 100644
index 000000000..b2de1ab06
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/shared_platform.cmake
@@ -0,0 +1,38 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_LINUX_SGX)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+if ("$ENV{SGX_SDK}" STREQUAL "")
+ set (SGX_SDK_DIR "/opt/intel/sgxsdk")
+else()
+ set (SGX_SDK_DIR $ENV{SGX_SDK})
+endif()
+
+include_directories (${SGX_SDK_DIR}/include)
+if (NOT BUILD_UNTRUST_PART EQUAL 1)
+ include_directories (${SGX_SDK_DIR}/include/tlibc
+ ${SGX_SDK_DIR}/include/libcxx)
+endif ()
+
+if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1)
+ add_definitions(-DSGX_DISABLE_WASI)
+endif ()
+
+if (NOT WAMR_BUILD_THREAD_MGR EQUAL 1)
+ add_definitions(-DSGX_DISABLE_PTHREAD)
+endif ()
+
+file (GLOB source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+file (GLOB source_all_untrusted ${PLATFORM_SHARED_DIR}/untrusted/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all})
+
+set (PLATFORM_SHARED_SOURCE_UNTRUSTED ${source_all_untrusted})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/file.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/file.c
new file mode 100644
index 000000000..cb9bf6a21
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/file.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sched.h>
+#include <poll.h>
+#include <errno.h>
+
+int
+ocall_open(const char *pathname, int flags, bool has_mode, unsigned mode)
+{
+ if (has_mode) {
+ return open(pathname, flags, (mode_t)mode);
+ }
+ else {
+ return open(pathname, flags);
+ }
+}
+
+int
+ocall_openat(int dirfd, const char *pathname, int flags, bool has_mode,
+ unsigned mode)
+{
+ if (has_mode) {
+ return openat(dirfd, pathname, flags, (mode_t)mode);
+ }
+ else {
+ return openat(dirfd, pathname, flags);
+ }
+}
+
+int
+ocall_close(int fd)
+{
+ return close(fd);
+}
+
+ssize_t
+ocall_read(int fd, void *buf, size_t read_size)
+{
+ if (buf != NULL) {
+ return read(fd, buf, read_size);
+ }
+ else {
+ return -1;
+ }
+}
+
+off_t
+ocall_lseek(int fd, off_t offset, int whence)
+{
+ return lseek(fd, offset, whence);
+}
+
+int
+ocall_ftruncate(int fd, off_t length)
+{
+ return ftruncate(fd, length);
+}
+
+int
+ocall_fsync(int fd)
+{
+ return fsync(fd);
+}
+
+int
+ocall_fdatasync(int fd)
+{
+ return fdatasync(fd);
+}
+
+int
+ocall_isatty(int fd)
+{
+ return isatty(fd);
+}
+
+void
+ocall_fdopendir(int fd, void **dirp)
+{
+ if (dirp) {
+ *(DIR **)dirp = fdopendir(fd);
+ }
+}
+
+void *
+ocall_readdir(void *dirp)
+{
+ DIR *p_dirp = (DIR *)dirp;
+ return readdir(p_dirp);
+}
+
+void
+ocall_rewinddir(void *dirp)
+{
+ DIR *p_dirp = (DIR *)dirp;
+ if (p_dirp) {
+ rewinddir(p_dirp);
+ }
+}
+
+void
+ocall_seekdir(void *dirp, long loc)
+{
+ DIR *p_dirp = (DIR *)dirp;
+
+ if (p_dirp) {
+ seekdir(p_dirp, loc);
+ }
+}
+
+long
+ocall_telldir(void *dirp)
+{
+ DIR *p_dirp = (DIR *)dirp;
+ if (p_dirp) {
+ return telldir(p_dirp);
+ }
+ return -1;
+}
+
+int
+ocall_closedir(void *dirp)
+{
+ DIR *p_dirp = (DIR *)dirp;
+ if (p_dirp) {
+ return closedir(p_dirp);
+ }
+ return -1;
+}
+
+int
+ocall_stat(const char *pathname, void *buf, unsigned int buf_len)
+{
+ return stat(pathname, (struct stat *)buf);
+}
+
+int
+ocall_fstat(int fd, void *buf, unsigned int buf_len)
+{
+ return fstat(fd, (struct stat *)buf);
+}
+
+int
+ocall_fstatat(int dirfd, const char *pathname, void *buf, unsigned int buf_len,
+ int flags)
+{
+ return fstatat(dirfd, pathname, (struct stat *)buf, flags);
+}
+
+int
+ocall_mkdirat(int dirfd, const char *pathname, unsigned mode)
+{
+ return mkdirat(dirfd, pathname, (mode_t)mode);
+}
+
+int
+ocall_link(const char *oldpath, const char *newpath)
+{
+ return link(oldpath, newpath);
+}
+
+int
+ocall_linkat(int olddirfd, const char *oldpath, int newdirfd,
+ const char *newpath, int flags)
+{
+ return linkat(olddirfd, oldpath, newdirfd, newpath, flags);
+}
+
+int
+ocall_unlinkat(int dirfd, const char *pathname, int flags)
+{
+ return unlinkat(dirfd, pathname, flags);
+}
+
+ssize_t
+ocall_readlink(const char *pathname, char *buf, size_t bufsiz)
+{
+ return readlink(pathname, buf, bufsiz);
+}
+
+ssize_t
+ocall_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
+{
+ return readlinkat(dirfd, pathname, buf, bufsiz);
+}
+
+int
+ocall_renameat(int olddirfd, const char *oldpath, int newdirfd,
+ const char *newpath)
+{
+ return renameat(olddirfd, oldpath, newdirfd, newpath);
+}
+
+int
+ocall_symlinkat(const char *target, int newdirfd, const char *linkpath)
+{
+ return symlinkat(target, newdirfd, linkpath);
+}
+
+int
+ocall_ioctl(int fd, unsigned long request, void *arg, unsigned int arg_len)
+{
+ /* support just int *arg temporally */
+ return ioctl(fd, request, (int *)arg);
+}
+
+int
+ocall_fcntl(int fd, int cmd)
+{
+ return fcntl(fd, cmd);
+}
+
+int
+ocall_fcntl_long(int fd, int cmd, long arg)
+{
+ return fcntl(fd, cmd, arg);
+}
+
+ssize_t
+ocall_readv(int fd, char *iov_buf, unsigned int buf_size, int iovcnt,
+ bool has_offset, off_t offset)
+{
+ struct iovec *iov = (struct iovec *)iov_buf;
+ ssize_t ret;
+ int i;
+
+ for (i = 0; i < iovcnt; i++) {
+ iov[i].iov_base = iov_buf + (unsigned)(uintptr_t)iov[i].iov_base;
+ }
+
+ if (has_offset)
+ ret = preadv(fd, iov, iovcnt, offset);
+ else
+ ret = readv(fd, iov, iovcnt);
+
+ return ret;
+}
+
+ssize_t
+ocall_writev(int fd, char *iov_buf, unsigned int buf_size, int iovcnt,
+ bool has_offset, off_t offset)
+{
+ struct iovec *iov = (struct iovec *)iov_buf;
+ int i;
+ ssize_t ret;
+
+ for (i = 0; i < iovcnt; i++) {
+ iov[i].iov_base = iov_buf + (unsigned)(uintptr_t)iov[i].iov_base;
+ }
+
+ if (has_offset)
+ ret = pwritev(fd, iov, iovcnt, offset);
+ else
+ ret = writev(fd, iov, iovcnt);
+
+ return ret;
+}
+
+int
+ocall_realpath(const char *path, char *buf, unsigned int buf_len)
+{
+ char *val = NULL;
+ val = realpath(path, buf);
+ if (val != NULL) {
+ return 0;
+ }
+ return -1;
+}
+
+int
+ocall_posix_fallocate(int fd, off_t offset, off_t len)
+{
+ return posix_fallocate(fd, offset, len);
+}
+
+int
+ocall_poll(void *fds, unsigned nfds, int timeout, unsigned int fds_len)
+{
+ return poll((struct pollfd *)fds, (nfds_t)nfds, timeout);
+}
+
+int
+ocall_getopt(int argc, char *argv_buf, unsigned int argv_buf_len,
+ const char *optstring)
+{
+ int ret;
+ int i;
+ char **argv = (char **)argv_buf;
+
+ for (i = 0; i < argc; i++) {
+ argv[i] = argv_buf + (uintptr_t)argv[i];
+ }
+
+ return getopt(argc, argv, optstring);
+}
+
+int
+ocall_sched_yield()
+{
+ return sched_yield();
+}
+
+int
+ocall_get_errno()
+{
+ return errno;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/pthread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/pthread.c
new file mode 100644
index 000000000..890ef754c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/pthread.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+int
+ocall_pthread_rwlock_init(void **rwlock, void *attr)
+{
+ int ret = 0;
+
+ *rwlock = malloc(sizeof(pthread_rwlock_t));
+ if (*rwlock == NULL)
+ return -1;
+
+ ret = pthread_rwlock_init((pthread_rwlock_t *)*rwlock, NULL);
+ if (ret != 0) {
+ free(*rwlock);
+ *rwlock = NULL;
+ }
+ (void)attr;
+ return ret;
+}
+
+int
+ocall_pthread_rwlock_destroy(void *rwlock)
+{
+ pthread_rwlock_t *lock = (pthread_rwlock_t *)rwlock;
+ int ret;
+
+ ret = pthread_rwlock_destroy(lock);
+ free(lock);
+ return ret;
+}
+
+int
+ocall_pthread_rwlock_rdlock(void *rwlock)
+{
+ return pthread_rwlock_rdlock((pthread_rwlock_t *)rwlock);
+}
+
+int
+ocall_pthread_rwlock_wrlock(void *rwlock)
+{
+ return pthread_rwlock_wrlock((pthread_rwlock_t *)rwlock);
+}
+
+int
+ocall_pthread_rwlock_unlock(void *rwlock)
+{
+ return pthread_rwlock_unlock((pthread_rwlock_t *)rwlock);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/signal.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/signal.c
new file mode 100644
index 000000000..b2eecfb7a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/signal.c
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <signal.h>
+
+int
+ocall_raise(int sig)
+{
+ return raise(sig);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/socket.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/socket.c
new file mode 100644
index 000000000..6f598ab8f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/socket.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int
+ocall_socket(int domain, int type, int protocol)
+{
+ return socket(domain, type, protocol);
+}
+
+int
+ocall_getsockopt(int sockfd, int level, int optname, void *val_buf,
+ unsigned int val_buf_size, void *len_buf)
+{
+ return getsockopt(sockfd, level, optname, val_buf, (socklen_t *)len_buf);
+}
+
+ssize_t
+ocall_sendmsg(int sockfd, void *msg_buf, unsigned int msg_buf_size, int flags)
+{
+ struct msghdr *msg = (struct msghdr *)msg_buf;
+ int i;
+ ssize_t ret;
+
+ if (msg->msg_name != NULL)
+ msg->msg_name = msg_buf + (unsigned)(uintptr_t)msg->msg_name;
+
+ if (msg->msg_control != NULL)
+ msg->msg_control = msg_buf + (unsigned)(uintptr_t)msg->msg_control;
+
+ if (msg->msg_iov != NULL) {
+ msg->msg_iov = msg_buf + (unsigned)(uintptr_t)msg->msg_iov;
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ msg->msg_iov[i].iov_base =
+ msg_buf + (unsigned)(uintptr_t)msg->msg_iov[i].iov_base;
+ }
+ }
+
+ return sendmsg(sockfd, msg, flags);
+}
+
+ssize_t
+ocall_recvmsg(int sockfd, void *msg_buf, unsigned int msg_buf_size, int flags)
+{
+ struct msghdr *msg = (struct msghdr *)msg_buf;
+ int i;
+ ssize_t ret;
+
+ if (msg->msg_name != NULL)
+ msg->msg_name = msg_buf + (unsigned)(uintptr_t)msg->msg_name;
+
+ if (msg->msg_control != NULL)
+ msg->msg_control = msg_buf + (unsigned)(uintptr_t)msg->msg_control;
+
+ if (msg->msg_iov != NULL) {
+ msg->msg_iov = msg_buf + (unsigned)(uintptr_t)msg->msg_iov;
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ msg->msg_iov[i].iov_base =
+ msg_buf + (unsigned)(uintptr_t)msg->msg_iov[i].iov_base;
+ }
+ }
+
+ return recvmsg(sockfd, msg, flags);
+}
+
+int
+ocall_shutdown(int sockfd, int how)
+{
+ return shutdown(sockfd, how);
+}
+
+int
+ocall_setsockopt(int sockfd, int level, int optname, void *optval,
+ unsigned int optlen)
+{
+ return setsockopt(sockfd, level, optname, optval, optlen);
+}
+
+int
+ocall_bind(int sockfd, const void *addr, uint32_t addrlen)
+{
+ return bind(sockfd, (const struct sockaddr *)addr, addrlen);
+}
+
+int
+ocall_getsockname(int sockfd, void *addr, uint32_t *addrlen, uint32_t addr_size)
+{
+ return getsockname(sockfd, (struct sockaddr *)addr, addrlen);
+}
+
+int
+ocall_getpeername(int sockfd, void *addr, uint32_t *addrlen, uint32_t addr_size)
+{
+ return getpeername(sockfd, (struct sockaddr *)addr, addrlen);
+}
+
+int
+ocall_listen(int sockfd, int backlog)
+{
+ return listen(sockfd, backlog);
+}
+
+int
+ocall_accept(int sockfd, void *addr, uint32_t *addrlen, uint32_t addr_size)
+{
+ return accept(sockfd, (struct sockaddr *)addr, addrlen);
+}
+
+int
+ocall_recv(int sockfd, void *buf, size_t len, int flags)
+{
+ return recv(sockfd, buf, len, flags);
+}
+
+ssize_t
+ocall_recvfrom(int sockfd, void *buf, size_t len, int flags, void *src_addr,
+ uint32_t *addrlen, uint32_t addr_size)
+{
+ return recvfrom(sockfd, buf, len, flags, (struct sockaddr *)src_addr,
+ addrlen);
+}
+
+int
+ocall_send(int sockfd, const void *buf, size_t len, int flags)
+{
+ return send(sockfd, buf, len, flags);
+}
+
+ssize_t
+ocall_sendto(int sockfd, const void *buf, size_t len, int flags,
+ void *dest_addr, uint32_t addrlen)
+{
+ return sendto(sockfd, buf, len, flags, (struct sockaddr *)dest_addr,
+ addrlen);
+}
+
+int
+ocall_connect(int sockfd, void *addr, uint32_t addrlen)
+{
+ return connect(sockfd, (const struct sockaddr *)addr, addrlen);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/time.c
new file mode 100644
index 000000000..5fa387b0c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux-sgx/untrusted/time.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <fcntl.h>
+
+/** time clock **/
+int
+ocall_clock_gettime(unsigned clock_id, void *tp_buf, unsigned int tp_buf_size)
+{
+ return clock_gettime((clockid_t)clock_id, (struct timespec *)tp_buf);
+}
+
+int
+ocall_clock_getres(int clock_id, void *res_buf, unsigned int res_buf_size)
+{
+ return clock_getres(clock_id, (struct timespec *)res_buf);
+}
+
+int
+ocall_utimensat(int dirfd, const char *pathname, const void *times_buf,
+ unsigned int times_buf_size, int flags)
+{
+ return utimensat(dirfd, pathname, (struct timespec *)times_buf, flags);
+}
+
+int
+ocall_futimens(int fd, const void *times_buf, unsigned int times_buf_size)
+{
+ return futimens(fd, (struct timespec *)times_buf);
+}
+
+int
+ocall_clock_nanosleep(unsigned clock_id, int flags, const void *req_buf,
+ unsigned int req_buf_size, const void *rem_buf,
+ unsigned int rem_buf_size)
+{
+ return clock_nanosleep((clockid_t)clock_id, flags,
+ (struct timespec *)req_buf,
+ (struct timespec *)rem_buf);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_init.c
new file mode 100644
index 000000000..2aae13fa1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_init.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+#ifndef BH_VPRINTF
+ ret += vprintf(format, ap);
+#else
+ ret += BH_VPRINTF(format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+ return vprintf(format, ap);
+#else
+ return BH_VPRINTF(format, ap);
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_internal.h
new file mode 100644
index 000000000..0ac63cf5e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/platform_internal.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sched.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_LINUX
+#define BH_PLATFORM_LINUX
+#endif
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define os_thread_local_attribute __thread
+
+#define bh_socket_t int
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+ || defined(BUILD_TARGET_RISCV64_LP64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#define os_alloca alloca
+
+#define os_getpagesize getpagesize
+
+typedef void (*os_signal_handler)(void *sig_addr);
+
+int
+os_thread_signal_init(os_signal_handler handler);
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+void
+os_signal_unmask();
+
+void
+os_sigreturn();
+#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/shared_platform.cmake
new file mode 100644
index 000000000..9a8726016
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/linux/shared_platform.cmake
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_LINUX)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/nuttx_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/nuttx_platform.c
new file mode 100644
index 000000000..9cb123e01
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/nuttx_platform.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2020 XiaoMi Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_extension.h"
+#include "platform_api_vmcore.h"
+
+#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+#include <nuttx/arch.h>
+#endif
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+void *
+os_malloc(unsigned size)
+{
+ return malloc(size);
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return realloc(ptr, size);
+}
+
+void
+os_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+ if ((prot & MMAP_PROT_EXEC) != 0) {
+ return up_textheap_memalign(sizeof(void *), size);
+ }
+#endif
+
+ if ((uint64)size >= UINT32_MAX)
+ return NULL;
+ return malloc((uint32)size);
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
+ if (up_textheap_heapmember(addr)) {
+ up_textheap_free(addr);
+ return;
+ }
+#endif
+ return free(addr);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ return 0;
+}
+
+void
+os_dcache_flush()
+{}
+
+/* If AT_FDCWD is provided, maybe we have openat family */
+#if !defined(AT_FDCWD)
+
+int
+openat(int fd, const char *path, int oflags, ...)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+fstatat(int fd, const char *path, struct stat *buf, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+mkdirat(int fd, const char *path, mode_t mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+ssize_t
+readlinkat(int fd, const char *path, char *buf, size_t bufsize)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+renameat(int fromfd, const char *from, int tofd, const char *to)
+{
+ errno = ENOSYS;
+ return -1;
+}
+int
+symlinkat(const char *target, int fd, const char *path)
+{
+ errno = ENOSYS;
+ return -1;
+}
+int
+unlinkat(int fd, const char *path, int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+int
+utimensat(int fd, const char *path, const struct timespec ts[2], int flag)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif /* !defined(AT_FDCWD) */
+
+#ifndef CONFIG_NET
+
+#include <netdb.h>
+
+int
+accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+bind(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+listen(int sockfd, int backlog)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+ssize_t
+recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
+ FAR struct sockaddr *from, FAR socklen_t *fromlen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+ssize_t
+send(int sockfd, FAR const void *buf, size_t len, int flags)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+ssize_t
+sendto(int sockfd, FAR const void *buf, size_t len, int flags,
+ FAR const struct sockaddr *to, socklen_t tolen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+shutdown(int sockfd, int how)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+getaddrinfo(FAR const char *nodename, FAR const char *servname,
+ FAR const struct addrinfo *hints, FAR struct addrinfo **res)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+void
+freeaddrinfo(FAR struct addrinfo *ai)
+{}
+
+int
+setsockopt(int sockfd, int level, int option, FAR const void *value,
+ socklen_t value_len)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+getsockopt(int sockfd, int level, int option, FAR void *value,
+ FAR socklen_t *value_len)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+getpeername(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int
+getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/platform_internal.h
new file mode 100644
index 000000000..b5bbdacd0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/platform_internal.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 XiaoMi Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <semaphore.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_NUTTX
+#define BH_PLATFORM_NUTTX
+#endif
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 100
+
+#define os_printf printf
+#define os_vprintf vprintf
+
+#if defined(CONFIG_LIBC_DLFCN)
+#define BH_HAS_DLFCN 1
+#else
+#define BH_HAS_DLFCN 0
+#endif
+
+/* On NuttX, time_t is uint32_t */
+#define BH_TIME_T_MAX 0xffffffff
+
+/*
+ * NuttX doesn't have O_DIRECTORY or directory open.
+ * REVISIT: maybe this is safer to be disabled at higher level.
+ */
+#if !defined(O_DIRECTORY)
+#define O_DIRECTORY 0
+#endif
+
+#if !defined(O_NOFOLLOW)
+#define O_NOFOLLOW 0
+#endif
+
+#undef CONFIG_HAS_ISATTY
+#ifdef CONFIG_SERIAL_TERMIOS
+#define CONFIG_HAS_ISATTY 1
+#else
+#define CONFIG_HAS_ISATTY 0
+#endif
+
+#define BUILTIN_LIBC_BUFFERED_PRINTF 1
+#define BUILTIN_LIBC_BUFFERED_PRINT_SIZE 128
+#define BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+
+/*
+ * NuttX doesn't have openat family.
+ */
+
+/* If AT_FDCWD is provided, maybe we have openat family */
+#if !defined(AT_FDCWD)
+
+int
+openat(int fd, const char *path, int oflags, ...);
+int
+fstatat(int fd, const char *path, struct stat *buf, int flag);
+int
+mkdirat(int fd, const char *path, mode_t mode);
+ssize_t
+readlinkat(int fd, const char *path, char *buf, size_t bufsize);
+int
+linkat(int fd1, const char *path1, int fd2, const char *path2, int flag);
+int
+renameat(int fromfd, const char *from, int tofd, const char *to);
+int
+symlinkat(const char *target, int fd, const char *path);
+int
+unlinkat(int fd, const char *path, int flag);
+int
+utimensat(int fd, const char *path, const struct timespec ts[2], int flag);
+#define AT_SYMLINK_NOFOLLOW 0
+#define AT_SYMLINK_FOLLOW 0
+#define AT_REMOVEDIR 0
+
+#endif /* !defined(AT_FDCWD) */
+
+/*
+ * NuttX doesn't have fdopendir.
+ */
+
+DIR *
+fdopendir(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _BH_PLATFORM_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/shared_platform.cmake
new file mode 100644
index 000000000..7b29b5f09
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/nuttx/shared_platform.cmake
@@ -0,0 +1,14 @@
+# Copyright (C) 2020 XiaoMi Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_NUTTX)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/platform_internal.h
new file mode 100644
index 000000000..8fec6dd0b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/platform_internal.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Copyright (C) 2020 TU Bergakademie Freiberg Karl Fessel
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+/* Riot includes core */
+#include <sched.h>
+#include <thread.h>
+#include <mutex.h>
+
+/* Riot includes sys */
+#include <sema.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef BH_PLATFORM_RIOT
+#define BH_PLATFORM_RIOT
+#endif
+
+#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 7
+
+typedef thread_t korp_thread;
+typedef kernel_pid_t korp_tid;
+typedef mutex_t korp_mutex;
+typedef unsigned int korp_sem;
+
+/* typedef sema_t korp_sem; */
+
+struct os_thread_wait_node;
+typedef struct os_thread_wait_node *os_thread_wait_list;
+typedef struct korp_cond {
+ mutex_t wait_list_lock;
+ os_thread_wait_list thread_wait_list;
+} korp_cond;
+
+#define os_printf printf
+#define os_vprintf vprintf
+
+#if WA_MATH
+/* clang-format off */
+/* math functions which are not provided by os*/
+double sqrt(double x);
+double floor(double x);
+double ceil(double x);
+double fmin(double x, double y);
+double fmax(double x, double y);
+double rint(double x);
+double fabs(double x);
+double trunc(double x);
+float sqrtf(float 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 fabsf(float x);
+float truncf(float x);
+int signbit(double x);
+int isnan(double x);
+/* clang-format on */
+#endif
+
+#endif /* end of _BH_PLATFORM_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_platform.c
new file mode 100644
index 000000000..a0c38e8c9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_platform.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Copyright (C) 2020 TU Bergakademie Freiberg Karl Fessel
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+int
+os_thread_sys_init(void);
+
+void
+os_thread_sys_destroy(void);
+
+int
+bh_platform_init(void)
+{
+ return os_thread_sys_init();
+}
+
+void
+bh_platform_destroy(void)
+{
+ os_thread_sys_destroy();
+}
+
+void *
+os_malloc(unsigned size)
+{
+ return malloc(size);
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return realloc(ptr, size);
+}
+
+void
+os_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ if (size > ((unsigned)~0))
+ return NULL;
+ return BH_MALLOC((unsigned)size);
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ return BH_FREE(addr);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ return 0;
+}
+
+void
+os_dcache_flush(void)
+{
+#if defined(CONFIG_CPU_CORTEX_M7) && defined(CONFIG_ARM_MPU)
+ uint32 key;
+ key = irq_lock();
+ SCB_CleanDCache();
+ irq_unlock(key);
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_thread.c
new file mode 100644
index 000000000..0ebcf30e0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_thread.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Copyright (C) 2020 TU Bergakademie Freiberg Karl Fessel
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#include <panic.h>
+#include <sema.h>
+#include <ztimer.h>
+
+/* clang-format off */
+#define bh_assert(v) do { \
+ if (!(v)) { \
+ printf("\nASSERTION FAILED: %s, at %s, line %d\n", \
+ #v, __FILE__, __LINE__); \
+ core_panic(0, 0/*expr_string*/); \
+ while (1); \
+ } \
+} while (0)
+/* clang-format on */
+
+struct os_thread_data;
+typedef struct os_thread_wait_node {
+ sema_t sem;
+ void *ret;
+ os_thread_wait_list next;
+} os_thread_wait_node;
+
+// all information for thread to cleanup it self
+typedef struct os_thread_data {
+ /* Next thread data */
+ struct os_thread_data *next;
+ /* thread handle */
+ kernel_pid_t tid;
+ /* Thread start routine */
+ thread_start_routine_t start_routine;
+ /* Thread start routine argument */
+ void *arg;
+ /* thread local root */
+ void *tlr;
+ /* Lock for waiting list */
+ mutex_t wait_list_lock;
+ /* Waiting list of other threads who are joining this thread */
+ os_thread_wait_list thread_wait_list;
+ /* Thread stack size */
+ unsigned stack_size;
+ /* Thread stack */
+ char stack[1];
+} os_thread_data;
+
+typedef struct os_thread_obj {
+ korp_tid thread;
+ /* Whether the thread is terminated and this thread object is to
+ be freed in the future. */
+ bool to_be_freed;
+ struct os_thread_obj *next;
+} os_thread_obj;
+
+static bool is_thread_sys_inited = false;
+
+/* Lock for thread data list */
+static mutex_t thread_data_lock;
+
+/* Thread data list */
+static os_thread_data *thread_data_list = NULL;
+
+static void
+thread_data_list_add(os_thread_data *thread_data)
+{
+ mutex_lock(&thread_data_lock);
+ if (!thread_data_list)
+ thread_data_list = thread_data;
+ else {
+ /* If already in list, just return */
+ os_thread_data *p = thread_data_list;
+ while (p) {
+ if (p == thread_data) {
+ mutex_unlock(&thread_data_lock);
+ return;
+ }
+ p = p->next;
+ }
+
+ /* Set as head of list */
+ thread_data->next = thread_data_list;
+ thread_data_list = thread_data;
+ }
+ mutex_unlock(&thread_data_lock);
+}
+
+static void
+thread_data_list_remove(os_thread_data *thread_data)
+{
+ mutex_lock(&thread_data_lock);
+ if (thread_data_list) {
+ if (thread_data_list == thread_data)
+ thread_data_list = thread_data_list->next;
+ else {
+ /* Search and remove it from list */
+ os_thread_data *p = thread_data_list;
+ while (p && p->next != thread_data)
+ p = p->next;
+ if (p && p->next == thread_data)
+ p->next = p->next->next;
+ }
+ }
+ mutex_unlock(&thread_data_lock);
+}
+
+static os_thread_data *
+thread_data_list_lookup(korp_tid tid)
+{
+ mutex_lock(&thread_data_lock);
+ if (thread_data_list) {
+ os_thread_data *p = thread_data_list;
+ while (p) {
+ if (p->tid == tid) {
+ /* Found */
+ mutex_unlock(&thread_data_lock);
+ return p;
+ }
+ p = p->next;
+ }
+ }
+ mutex_unlock(&thread_data_lock);
+ return NULL;
+}
+
+int
+os_thread_sys_init()
+{
+ if (is_thread_sys_inited)
+ return BHT_OK;
+
+ mutex_init(&thread_data_lock);
+
+ is_thread_sys_inited = true;
+ return BHT_OK;
+}
+
+void
+os_thread_sys_destroy()
+{
+ if (is_thread_sys_inited) {
+ is_thread_sys_inited = false;
+ }
+}
+
+static os_thread_data *
+thread_data_current()
+{
+ kernel_pid_t tid = thread_getpid();
+ return thread_data_list_lookup(tid);
+}
+
+static void
+os_thread_cleanup(void)
+{
+ // TODO Check this (Join sema trigger, cleanup of thread_data)
+ os_thread_data *thread_data = thread_data_current();
+ bh_assert(thread_data != NULL);
+ mutex_lock(&thread_data->wait_list_lock);
+ if (thread_data->thread_wait_list) {
+ /* Signal each joining thread */
+ os_thread_wait_list head = thread_data->thread_wait_list;
+ while (head) {
+ os_thread_wait_list next = head->next;
+ head->ret = thread_data->arg;
+ sema_post(&head->sem);
+ head = next;
+ }
+ thread_data->thread_wait_list = NULL;
+ }
+ mutex_unlock(&thread_data->wait_list_lock);
+
+ thread_data_list_remove(thread_data);
+}
+
+static void *
+os_thread_wrapper(void *thread_data)
+{
+ /* Set thread custom data */
+ os_thread_data *t = (os_thread_data *)thread_data;
+ t->tid = thread_getpid();
+ thread_data_list_add(t);
+
+ // save the return value to arg since it is not need after the call
+ t->arg = (t->start_routine)(t->arg);
+
+ os_thread_cleanup(); // internal structures and joiners
+
+ BH_FREE(thread_data);
+ sched_task_exit(); // stop thread //clean
+ return NULL; // never reached
+}
+
+int
+os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(p_tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+int
+os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ kernel_pid_t tid;
+ os_thread_data *thread_data;
+ unsigned thread_data_size;
+
+ if (!p_tid || !stack_size)
+ return BHT_ERROR;
+
+ /* Create and initialize thread data */
+ thread_data_size = offsetof(os_thread_data, stack) + stack_size;
+ if (!(thread_data = BH_MALLOC(thread_data_size))) {
+ return BHT_ERROR;
+ }
+
+ memset(thread_data, 0, thread_data_size);
+ mutex_init(&thread_data->wait_list_lock);
+ thread_data->stack_size = stack_size;
+ thread_data->start_routine = start;
+ thread_data->arg = arg;
+
+ /* Create the thread &*/
+ if (!((tid = thread_create(thread_data->stack, stack_size, prio, 0,
+ os_thread_wrapper, thread_data, "WASM")))) {
+ BH_FREE(thread_data);
+ return BHT_ERROR;
+ }
+
+ thread_data->tid = tid;
+
+ /* Set thread custom data */
+ thread_data_list_add(thread_data);
+ *p_tid = tid;
+ return BHT_OK;
+}
+
+korp_tid
+os_self_thread()
+{
+ return (korp_tid)thread_getpid();
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+ // will test if thread is still working,
+ // wait if it is
+ os_thread_data *thread_data;
+ os_thread_wait_node node;
+
+ sema_create(&node.sem, 0);
+ node.next = NULL;
+
+ /* Get thread data */
+ thread_data = thread_data_list_lookup(thread);
+ if (thread_data == NULL) {
+ // thread not found
+ sema_destroy(&node.sem);
+ return BHT_ERROR;
+ }
+ bh_assert(thread_data != NULL);
+
+ mutex_lock(&thread_data->wait_list_lock);
+ if (!thread_data->thread_wait_list)
+ thread_data->thread_wait_list = &node;
+ else {
+ /* Add to end of waiting list */
+ os_thread_wait_node *p = thread_data->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = &node;
+ }
+ mutex_unlock(&thread_data->wait_list_lock);
+
+ sema_wait(&node.sem);
+ // get the return value pointer conted may not be availible after return
+ if (value_ptr)
+ (*value_ptr) = node.ret;
+ /* Wait some time for the thread to be actually terminated */
+ // TODO: k_sleep(100);
+
+ // TODO: bump target prio to make it finish and free its resources
+ thread_yield();
+
+ // node has done its job
+ sema_destroy(&node.sem);
+
+ return BHT_OK;
+}
+
+// int vm_mutex_trylock(korp_mutex *mutex)
+// {
+// return mutex_trylock(mutex);
+// }
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ mutex_init(mutex);
+ return BHT_OK;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ (void)mutex;
+ return BHT_OK;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ mutex_lock(mutex);
+ return 0; // Riot mutexes do not return until success
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ mutex_unlock(mutex);
+ return 0; // Riot mutexes do not return until success
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ mutex_init(&cond->wait_list_lock);
+ cond->thread_wait_list = NULL;
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ (void)cond;
+ return BHT_OK;
+}
+
+static int
+os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed,
+ uint64 useconds)
+{
+ os_thread_wait_node *node;
+
+ /* Create wait node and append it to wait list */
+ if (!(node = BH_MALLOC(sizeof(os_thread_wait_node))))
+ return BHT_ERROR;
+
+ sema_create(&node->sem, 0);
+ node->next = NULL;
+
+ mutex_lock(&cond->wait_list_lock);
+ if (!cond->thread_wait_list)
+ cond->thread_wait_list = node;
+ else {
+ /* Add to end of wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = node;
+ }
+ mutex_unlock(&cond->wait_list_lock);
+
+ /* Unlock mutex, wait sem and lock mutex again */
+ mutex_unlock(mutex);
+ if (timed)
+ sema_wait(&node->sem);
+ else
+ sema_wait_timed_ztimer(&node->sem, ZTIMER_USEC, useconds);
+ mutex_lock(mutex);
+
+ /* Remove wait node from wait list */
+ mutex_lock(&cond->wait_list_lock);
+ if (cond->thread_wait_list == node)
+ cond->thread_wait_list = node->next;
+ else {
+ /* Remove from the wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next != node)
+ p = p->next;
+ p->next = node->next;
+ }
+ BH_FREE(node);
+ mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return os_cond_wait_internal(cond, mutex, false, 0);
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ return os_cond_wait_internal(cond, mutex, (useconds != BHT_WAIT_FOREVER),
+ useconds);
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ /* Signal the head wait node of wait list */
+ mutex_lock(&cond->wait_list_lock);
+ if (cond->thread_wait_list)
+ sema_post(&cond->thread_wait_list->sem);
+ mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+#if defined(DEVELHELP) || defined(SCHED_TEST_STACK) \
+ || defined(MODULE_MPU_STACK_GUARD)
+ return (uint8 *)thread_get_active()->stack_start;
+#else
+ return NULL;
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_time.c
new file mode 100644
index 000000000..1503495c1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/riot_time.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Copyright (C) 2020 TU Bergakademie Freiberg Karl Fessel
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include <ztimer64.h>
+#include <kernel_defines.h>
+
+#if IS_USED(MODULE_ZTIMER64_USEC)
+uint64
+os_time_get_boot_microsecond()
+{
+ return ztimer64_now(ZTIMER64_USEC);
+}
+#elif IS_USED(MODULE_ZTIMER64_MSEC)
+uint64
+os_time_get_boot_microsecond()
+{
+ return ztimer64_now(ZTIMER64_MSEC) * 1000;
+}
+#else
+#ifdef __GNUC__
+__attribute__((weak)) uint64
+os_time_get_boot_microsecond();
+#endif
+uint64
+os_time_get_boot_microsecond()
+{
+ static uint64_t times;
+ return ++times;
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/shared_platform.cmake
new file mode 100644
index 000000000..52cf90463
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/riot/shared_platform.cmake
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# Copyright (C) 2020 TU Bergakademie Freiberg Karl Fessel
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_RIOT)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+# include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/SConscript
new file mode 100644
index 000000000..1e93f4755
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/SConscript
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+
+from building import *
+import os
+
+cwd = GetCurrentDir()
+
+src = Split('''
+''')
+
+
+def addSrcFiles(arr, path):
+ for f in os.listdir(path):
+ fpath = os.path.join(path, f);
+ if os.path.isfile(fpath):
+ ext = os.path.splitext(fpath)[-1]
+ if ext == '.c' or ext == '.cpp':
+ arr += [fpath]
+ elif os.path.isdir(fpath):
+ addSrcFiles(arr, fpath)
+
+
+
+addSrcFiles(src, cwd);
+CPPPATH = [cwd, cwd+'/../include']
+
+group = DefineGroup('iwasm_platform_core', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/platform_internal.h
new file mode 100644
index 000000000..5f9cc8bc8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/platform_internal.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef RTTHREAD_PLATFORM_INTERNAL_H
+#define RTTHREAD_PLATFORM_INTERNAL_H
+
+#include <rtthread.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#if defined(WASM_ENABLE_AOT)
+#if defined(RTT_WAMR_BUILD_TARGET_THUMB)
+#define BUILD_TARGET "thumbv4t"
+#elif defined(RTT_WAMR_BUILD_TARGET_ARMV7)
+#define BUILD_TARGET "armv7"
+#elif defined(RTT_WAMR_BUILD_TARGET_ARMV6)
+#define BUILD_TARGET "armv6"
+#elif defined(RTT_WAMR_BUILD_TARGET_ARMV4)
+#define BUILD_TARGET "armv4"
+#elif defined(RTT_WAMR_BUILD_TARGET_X86_32)
+#define BUILD_TARGET "X86_32"
+#else
+#error "unsupported aot platform."
+#endif
+#endif /* WASM_ENABLE_AOT */
+
+typedef rt_thread_t korp_tid;
+typedef struct rt_mutex korp_mutex;
+typedef struct rt_thread korp_cond;
+typedef struct rt_thread korp_thread;
+typedef unsigned int korp_sem;
+
+typedef rt_uint8_t uint8_t;
+typedef rt_int8_t int8_t;
+typedef rt_uint16_t uint16_t;
+typedef rt_int16_t int16_t;
+typedef rt_uint64_t uint64_t;
+typedef rt_int64_t int64_t;
+
+#endif /* RTTHREAD_PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/rtt_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/rtt_platform.c
new file mode 100644
index 000000000..4685e1ea3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/rtt_platform.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <platform_api_vmcore.h>
+#include <platform_api_extension.h>
+
+typedef struct os_malloc_list {
+ void *real;
+ void *used;
+ rt_list_t node;
+} os_malloc_list_t;
+
+int
+bh_platform_init(void)
+{
+ return 0;
+}
+
+void
+bh_platform_destroy(void)
+{}
+
+void *
+os_malloc(unsigned size)
+{
+ void *buf_origin;
+ void *buf_fixed;
+ rt_ubase_t *addr_field;
+
+ buf_origin = rt_malloc(size + 8 + sizeof(rt_ubase_t));
+ buf_fixed = buf_origin + sizeof(void *);
+ if ((rt_ubase_t)buf_fixed & 0x7) {
+ buf_fixed = (void *)((rt_ubase_t)(buf_fixed + 8) & (~7));
+ }
+
+ addr_field = buf_fixed - sizeof(rt_ubase_t);
+ *addr_field = (rt_ubase_t)buf_origin;
+
+ return buf_fixed;
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+
+ void *mem_origin;
+ void *mem_new;
+ void *mem_new_fixed;
+ rt_ubase_t *addr_field;
+
+ if (!ptr) {
+ return RT_NULL;
+ }
+
+ addr_field = ptr - sizeof(rt_ubase_t);
+ mem_origin = (void *)(*addr_field);
+ mem_new = rt_realloc(mem_origin, size + 8 + sizeof(rt_ubase_t));
+
+ if (mem_origin != mem_new) {
+ mem_new_fixed = mem_new + sizeof(rt_ubase_t);
+ if ((rt_ubase_t)mem_new_fixed & 0x7) {
+ mem_new_fixed = (void *)((rt_ubase_t)(mem_new_fixed + 8) & (~7));
+ }
+
+ addr_field = mem_new_fixed - sizeof(rt_ubase_t);
+ *addr_field = (rt_ubase_t)mem_new;
+
+ return mem_new_fixed;
+ }
+
+ return ptr;
+}
+
+void
+os_free(void *ptr)
+{
+ void *mem_origin;
+ rt_ubase_t *addr_field;
+
+ if (ptr) {
+ addr_field = ptr - sizeof(rt_ubase_t);
+ mem_origin = (void *)(*addr_field);
+
+ rt_free(mem_origin);
+ }
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
+
+static char wamr_vprint_buf[RT_CONSOLEBUF_SIZE * 2];
+
+int
+os_printf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ rt_size_t len =
+ vsnprintf(wamr_vprint_buf, sizeof(wamr_vprint_buf) - 1, format, ap);
+ wamr_vprint_buf[len] = 0x00;
+ rt_kputs(wamr_vprint_buf);
+ va_end(ap);
+ return 0;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+ rt_size_t len =
+ vsnprintf(wamr_vprint_buf, sizeof(wamr_vprint_buf) - 1, format, ap);
+ wamr_vprint_buf[len] = 0;
+ rt_kputs(wamr_vprint_buf);
+ return 0;
+}
+
+uint64
+os_time_get_boot_microsecond(void)
+{
+ uint64 ret = rt_tick_get() * 1000;
+ ret /= RT_TICK_PER_SECOND;
+ return ret;
+}
+
+korp_tid
+os_self_thread(void)
+{
+ return rt_thread_self();
+}
+
+uint8 *
+os_thread_get_stack_boundary(void)
+{
+ rt_thread_t tid = rt_thread_self();
+ return tid->stack_addr;
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ return rt_mutex_init(mutex, "wamr0", RT_IPC_FLAG_FIFO);
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ return rt_mutex_detach(mutex);
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ return rt_mutex_take(mutex, RT_WAITING_FOREVER);
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ return rt_mutex_release(mutex);
+}
+
+/*
+ * functions below was not implement
+ */
+
+int
+os_cond_init(korp_cond *cond)
+{
+ return 0;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ return 0;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return 0;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ return rt_malloc(size);
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ rt_free(addr);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ return 0;
+}
+
+void
+os_dcache_flush(void)
+{}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/shared_platform.cmake
new file mode 100644
index 000000000..fce9bff33
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/rt-thread/shared_platform.cmake
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_RTT)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+# include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_init.c
new file mode 100644
index 000000000..2aae13fa1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_init.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+int
+bh_platform_init()
+{
+ return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+#ifndef BH_VPRINTF
+ ret += vprintf(format, ap);
+#else
+ ret += BH_VPRINTF(format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+ return vprintf(format, ap);
+#else
+ return BH_VPRINTF(format, ap);
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_internal.h
new file mode 100644
index 000000000..f72f60322
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/platform_internal.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sched.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_VXWORKS
+#define BH_PLATFORM_VXWORKS
+#endif
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define os_thread_local_attribute __thread
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+ || defined(BUILD_TARGET_AARCH64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#define os_alloca alloca
+
+#define os_getpagesize getpagesize
+
+typedef void (*os_signal_handler)(void *sig_addr);
+
+int
+os_thread_signal_init(os_signal_handler handler);
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+void
+os_signal_unmask();
+
+void
+os_sigreturn();
+#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/shared_platform.cmake
new file mode 100644
index 000000000..6979ce235
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/vxworks/shared_platform.cmake
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_VXWORKS)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c
new file mode 100644
index 000000000..db5885387
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+int
+os_thread_sys_init();
+
+void
+os_thread_sys_destroy();
+
+int
+init_winsock();
+
+void
+deinit_winsock();
+
+int
+bh_platform_init()
+{
+ if (init_winsock() != 0) {
+ return -1;
+ }
+
+ return os_thread_sys_init();
+}
+
+void
+bh_platform_destroy()
+{
+ deinit_winsock();
+
+ os_thread_sys_destroy();
+}
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+#ifndef BH_VPRINTF
+ ret += vprintf(format, ap);
+#else
+ ret += BH_VPRINTF(format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+ return vprintf(format, ap);
+#else
+ return BH_VPRINTF(format, ap);
+#endif
+}
+
+unsigned
+os_getpagesize()
+{
+ SYSTEM_INFO sys_info;
+ GetNativeSystemInfo(&sys_info);
+ return (unsigned)sys_info.dwPageSize;
+}
+
+void
+os_dcache_flush(void)
+{}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h
new file mode 100644
index 000000000..500ab200c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <sys/timeb.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <malloc.h>
+#include <process.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <basetsd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_WINDOWS
+#define BH_PLATFORM_WINDOWS
+#endif
+
+#ifdef _MSC_VER
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+#endif /* #ifdef _MSC_VER */
+
+/* Stack size of applet threads's native part. */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef SSIZE_T ssize_t;
+
+typedef void *korp_thread;
+typedef void *korp_tid;
+typedef void *korp_mutex;
+typedef void *korp_sem;
+
+/**
+ * Create the mutex when os_mutex_lock is called, and no need to
+ * CloseHandle() for the static lock's lifetime, since
+ * "The system closes the handle automatically when the process
+ * terminates. The mutex object is destroyed when its last
+ * handle has been closed."
+ * Refer to:
+ * https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa
+ */
+#define OS_THREAD_MUTEX_INITIALIZER NULL
+
+struct os_thread_wait_node;
+typedef struct os_thread_wait_node *os_thread_wait_list;
+typedef struct korp_cond {
+ korp_mutex wait_list_lock;
+ os_thread_wait_list thread_wait_list;
+ struct os_thread_wait_node *thread_wait_list_end;
+} korp_cond;
+
+#define bh_socket_t SOCKET
+
+unsigned
+os_getpagesize();
+void *
+os_mem_commit(void *ptr, size_t size, int flags);
+void
+os_mem_decommit(void *ptr, size_t size);
+
+#define os_thread_local_attribute __declspec(thread)
+
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+
+int
+os_thread_signal_init();
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+#define os_signal_unmask() (void)0
+#define os_sigreturn() (void)0
+
+#endif /* end of BUILD_TARGET_X86_64/AMD_64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+typedef enum os_memory_order {
+ os_memory_order_relaxed,
+ os_memory_order_consume,
+ os_memory_order_acquire,
+ os_memory_order_release,
+ os_memory_order_acq_rel,
+ os_memory_order_seq_cst,
+} os_memory_order;
+
+void
+bh_atomic_thread_fence(int mem_order);
+
+#define os_atomic_thread_fence bh_atomic_thread_fence
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake
new file mode 100644
index 000000000..a68d63177
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake
@@ -0,0 +1,19 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_WINDOWS)
+add_definitions(-DHAVE_STRUCT_TIMESPEC)
+add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c
+ ${PLATFORM_SHARED_DIR}/*.cpp)
+
+set (PLATFORM_SHARED_SOURCE ${source_all})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp
new file mode 100644
index 000000000..80e8ef518
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+
+#include <atomic>
+
+void
+bh_atomic_thread_fence(int mem_order)
+{
+ std::memory_order order =
+ (std::memory_order)(std::memory_order::memory_order_relaxed + mem_order
+ - os_memory_order_relaxed);
+ std::atomic_thread_fence(order);
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c
new file mode 100644
index 000000000..56aaf9c7b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+void *
+os_malloc(unsigned size)
+{
+ return malloc(size);
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return realloc(ptr, size);
+}
+
+void
+os_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c
new file mode 100644
index 000000000..c4a6b0756
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+#define TRACE_MEMMAP 0
+
+static DWORD
+access_to_win32_flags(int prot)
+{
+ DWORD protect = PAGE_NOACCESS;
+
+ if (prot & MMAP_PROT_EXEC) {
+ if (prot & MMAP_PROT_WRITE)
+ protect = PAGE_EXECUTE_READWRITE;
+ else
+ protect = PAGE_EXECUTE_READ;
+ }
+ else if (prot & MMAP_PROT_WRITE) {
+ protect = PAGE_READWRITE;
+ }
+ else if (prot & MMAP_PROT_READ) {
+ protect = PAGE_READONLY;
+ }
+
+ return protect;
+}
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ DWORD alloc_type = MEM_RESERVE;
+ DWORD protect;
+ size_t request_size, page_size;
+ void *addr;
+
+ page_size = os_getpagesize();
+ request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (request_size < size)
+ /* integer overflow */
+ return NULL;
+
+#if WASM_ENABLE_JIT != 0
+ /**
+ * Allocate memory at the highest possible address if the
+ * request size is large, or LLVM JIT might report error:
+ * IMAGE_REL_AMD64_ADDR32NB relocation requires an ordered
+ * section layout.
+ */
+ if (request_size > 10 * BH_MB)
+ alloc_type |= MEM_TOP_DOWN;
+#endif
+
+ protect = access_to_win32_flags(prot);
+ if (protect != PAGE_NOACCESS) {
+ alloc_type |= MEM_COMMIT;
+ }
+
+ addr = VirtualAlloc((LPVOID)hint, request_size, alloc_type, protect);
+
+#if TRACE_MEMMAP != 0
+ printf("Map memory, request_size: %zu, alloc_type: 0x%x, "
+ "protect: 0x%x, ret: %p\n",
+ request_size, alloc_type, protect, addr);
+#endif
+ return addr;
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ size_t page_size = os_getpagesize();
+ size_t request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (addr) {
+ if (!VirtualFree(addr, request_size, MEM_DECOMMIT)) {
+ printf("warning: os_munmap decommit pages failed, "
+ "addr: %p, request_size: %zu, errno: %d\n",
+ addr, request_size, errno);
+ return;
+ }
+
+ if (!VirtualFree(addr, 0, MEM_RELEASE)) {
+ printf("warning: os_munmap release pages failed, "
+ "addr: %p, size: %zu, errno:%d\n",
+ addr, request_size, errno);
+ }
+ }
+#if TRACE_MEMMAP != 0
+ printf("Unmap memory, addr: %p, request_size: %zu\n", addr, request_size);
+#endif
+}
+
+void *
+os_mem_commit(void *addr, size_t size, int flags)
+{
+ DWORD protect = access_to_win32_flags(flags);
+ size_t page_size = os_getpagesize();
+ size_t request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (!addr)
+ return NULL;
+
+#if TRACE_MEMMAP != 0
+ printf("Commit memory, addr: %p, request_size: %zu, protect: 0x%x\n", addr,
+ request_size, protect);
+#endif
+ return VirtualAlloc((LPVOID)addr, request_size, MEM_COMMIT, protect);
+}
+
+void
+os_mem_decommit(void *addr, size_t size)
+{
+ size_t page_size = os_getpagesize();
+ size_t request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (!addr)
+ return;
+
+#if TRACE_MEMMAP != 0
+ printf("Decommit memory, addr: %p, request_size: %zu\n", addr,
+ request_size);
+#endif
+ VirtualFree((LPVOID)addr, request_size, MEM_DECOMMIT);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ DWORD protect;
+ size_t page_size = os_getpagesize();
+ size_t request_size = (size + page_size - 1) & ~(page_size - 1);
+
+ if (!addr)
+ return 0;
+
+ protect = access_to_win32_flags(prot);
+#if TRACE_MEMMAP != 0
+ printf("Mprotect memory, addr: %p, request_size: %zu, protect: 0x%x\n",
+ addr, request_size, protect);
+#endif
+ return VirtualProtect((LPVOID)addr, request_size, protect, NULL);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c
new file mode 100644
index 000000000..9a1c7a3c9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+/* link with Ws2_32.lib */
+#pragma comment(lib, "ws2_32.lib")
+
+static bool is_winsock_inited = false;
+
+int
+init_winsock()
+{
+ WSADATA wsaData;
+
+ if (!is_winsock_inited) {
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
+ os_printf("winsock init failed");
+ return BHT_ERROR;
+ }
+
+ is_winsock_inited = true;
+ }
+
+ return BHT_OK;
+}
+
+void
+deinit_winsock()
+{
+ if (is_winsock_inited) {
+ WSACleanup();
+ }
+}
+
+int
+os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
+{
+ int af;
+
+ if (!sock) {
+ return BHT_ERROR;
+ }
+
+ if (is_ipv4) {
+ af = AF_INET;
+ }
+ else {
+ errno = ENOSYS;
+ return BHT_ERROR;
+ }
+
+ if (is_tcp) {
+ *sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
+ }
+ else {
+ *sock = socket(af, SOCK_DGRAM, 0);
+ }
+
+ return (*sock == -1) ? BHT_ERROR : BHT_OK;
+}
+
+int
+os_socket_bind(bh_socket_t socket, const char *host, int *port)
+{
+ struct sockaddr_in addr;
+ int socklen, ret;
+
+ assert(host);
+ assert(port);
+
+ addr.sin_addr.s_addr = inet_addr(host);
+ addr.sin_port = htons(*port);
+ addr.sin_family = AF_INET;
+
+ ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret < 0) {
+ goto fail;
+ }
+
+ socklen = sizeof(addr);
+ if (getsockname(socket, (void *)&addr, &socklen) == -1) {
+ os_printf("getsockname failed with error %d\n", WSAGetLastError());
+ goto fail;
+ }
+
+ *port = ntohs(addr.sin_port);
+
+ return BHT_OK;
+
+fail:
+ return BHT_ERROR;
+}
+
+int
+os_socket_settimeout(bh_socket_t socket, uint64 timeout_us)
+{
+ DWORD tv = (DWORD)(timeout_us / 1000UL);
+
+ if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv,
+ sizeof(tv))
+ != 0) {
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_listen(bh_socket_t socket, int max_client)
+{
+ if (listen(socket, max_client) != 0) {
+ os_printf("socket listen failed with error %d\n", WSAGetLastError());
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
+ unsigned int *addrlen)
+{
+ struct sockaddr addr_tmp;
+ unsigned int len = sizeof(struct sockaddr);
+
+ *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
+
+ if (*sock < 0) {
+ os_printf("socket accept failed with error %d\n", WSAGetLastError());
+ return BHT_ERROR;
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
+{
+ return recv(socket, buf, len, 0);
+}
+
+int
+os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
+ bh_sockaddr_t *src_addr)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
+{
+ return send(socket, buf, len, 0);
+}
+
+int
+os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
+ int flags, const bh_sockaddr_t *dest_addr)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_close(bh_socket_t socket)
+{
+ closesocket(socket);
+ return BHT_OK;
+}
+
+int
+os_socket_shutdown(bh_socket_t socket)
+{
+ shutdown(socket, SD_BOTH);
+ return BHT_OK;
+}
+
+int
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
+{
+ if (!cp)
+ return BHT_ERROR;
+
+ if (is_ipv4) {
+ if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
+ return BHT_ERROR;
+ }
+ /* Note: ntohl(INADDR_NONE) == INADDR_NONE */
+ out->ipv4 = ntohl(out->ipv4);
+ }
+ else {
+ if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
+ return BHT_ERROR;
+ }
+ for (int i = 0; i < 8; i++) {
+ out->ipv6[i] = ntohs(out->ipv6[i]);
+ }
+ }
+
+ return BHT_OK;
+}
+
+int
+os_socket_addr_resolve(const char *host, const char *service,
+ uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
+ bh_addr_info_t *addr_info, size_t addr_info_size,
+ size_t *max_info_size)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_add_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_drop_membership(bh_socket_t socket,
+ bh_ip_addr_buffer_t *imr_multiaddr,
+ uint32_t imr_interface, bool is_ipv6)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_ipv6_only(bh_socket_t socket, bool option)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_ipv6_only(bh_socket_t socket, bool *option)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_set_broadcast(bh_socket_t socket, bool is_enabled)
+{
+ errno = ENOSYS;
+
+ return BHT_ERROR;
+}
+
+int
+os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled)
+{
+ errno = ENOSYS;
+ return BHT_ERROR;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c
new file mode 100644
index 000000000..09cf0c63f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c
@@ -0,0 +1,750 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#define bh_assert(v) assert(v)
+
+#define BH_SEM_COUNT_MAX 0xFFFF
+
+struct os_thread_data;
+
+typedef struct os_thread_wait_node {
+ korp_sem sem;
+ void *retval;
+ os_thread_wait_list next;
+} os_thread_wait_node;
+
+typedef struct os_thread_data {
+ /* Next thread data */
+ struct os_thread_data *next;
+ /* Thread data of parent thread */
+ struct os_thread_data *parent;
+ /* Thread Id */
+ DWORD thread_id;
+ /* Thread start routine */
+ thread_start_routine_t start_routine;
+ /* Thread start routine argument */
+ void *arg;
+ /* Wait node of current thread */
+ os_thread_wait_node wait_node;
+ /* Wait cond */
+ korp_cond wait_cond;
+ /* Wait lock */
+ korp_mutex wait_lock;
+ /* Waiting list of other threads who are joining this thread */
+ os_thread_wait_list thread_wait_list;
+ /* End node of the waiting list */
+ os_thread_wait_node *thread_wait_list_end;
+ /* Whether the thread has exited */
+ bool thread_exited;
+ /* Thread return value */
+ void *thread_retval;
+} os_thread_data;
+
+static bool is_thread_sys_inited = false;
+
+/* Thread data of supervisor thread */
+static os_thread_data supervisor_thread_data;
+
+/* Thread data list lock */
+static korp_mutex thread_data_list_lock;
+
+/* Thread data key */
+static DWORD thread_data_key;
+
+/* The GetCurrentThreadStackLimits API from "kernel32" */
+static void(WINAPI *GetCurrentThreadStackLimits_Kernel32)(PULONG_PTR,
+ PULONG_PTR) = NULL;
+
+int
+os_sem_init(korp_sem *sem);
+int
+os_sem_destroy(korp_sem *sem);
+int
+os_sem_wait(korp_sem *sem);
+int
+os_sem_reltimed_wait(korp_sem *sem, uint64 useconds);
+int
+os_sem_signal(korp_sem *sem);
+
+int
+os_thread_sys_init()
+{
+ HMODULE module;
+
+ if (is_thread_sys_inited)
+ return BHT_OK;
+
+ if ((thread_data_key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return BHT_ERROR;
+
+ /* Initialize supervisor thread data */
+ memset(&supervisor_thread_data, 0, sizeof(os_thread_data));
+
+ supervisor_thread_data.thread_id = GetCurrentThreadId();
+
+ if (os_sem_init(&supervisor_thread_data.wait_node.sem) != BHT_OK)
+ goto fail1;
+
+ if (os_mutex_init(&supervisor_thread_data.wait_lock) != BHT_OK)
+ goto fail2;
+
+ if (os_cond_init(&supervisor_thread_data.wait_cond) != BHT_OK)
+ goto fail3;
+
+ if (!TlsSetValue(thread_data_key, &supervisor_thread_data))
+ goto fail4;
+
+ if (os_mutex_init(&thread_data_list_lock) != BHT_OK)
+ goto fail5;
+
+ if ((module = GetModuleHandle((LPCTSTR) "kernel32"))) {
+ *(void **)&GetCurrentThreadStackLimits_Kernel32 =
+ GetProcAddress(module, "GetCurrentThreadStackLimits");
+ }
+
+ is_thread_sys_inited = true;
+ return BHT_OK;
+
+fail5:
+ TlsSetValue(thread_data_key, NULL);
+fail4:
+ os_cond_destroy(&supervisor_thread_data.wait_cond);
+fail3:
+ os_mutex_destroy(&supervisor_thread_data.wait_lock);
+fail2:
+ os_sem_destroy(&supervisor_thread_data.wait_node.sem);
+fail1:
+ TlsFree(thread_data_key);
+ return BHT_ERROR;
+}
+
+void
+os_thread_sys_destroy()
+{
+ if (is_thread_sys_inited) {
+ os_thread_data *thread_data, *thread_data_next;
+
+ thread_data = supervisor_thread_data.next;
+ while (thread_data) {
+ thread_data_next = thread_data->next;
+
+ /* Destroy resources of thread data */
+ os_cond_destroy(&thread_data->wait_cond);
+ os_sem_destroy(&thread_data->wait_node.sem);
+ os_mutex_destroy(&thread_data->wait_lock);
+ BH_FREE(thread_data);
+
+ thread_data = thread_data_next;
+ }
+
+ os_mutex_destroy(&thread_data_list_lock);
+ os_cond_destroy(&supervisor_thread_data.wait_cond);
+ os_mutex_destroy(&supervisor_thread_data.wait_lock);
+ os_sem_destroy(&supervisor_thread_data.wait_node.sem);
+ memset(&supervisor_thread_data, 0, sizeof(os_thread_data));
+ TlsFree(thread_data_key);
+ thread_data_key = 0;
+ is_thread_sys_inited = false;
+ }
+}
+
+static os_thread_data *
+thread_data_current()
+{
+ return (os_thread_data *)TlsGetValue(thread_data_key);
+}
+
+static void
+os_thread_cleanup(void *retval)
+{
+ os_thread_data *thread_data = thread_data_current();
+
+ bh_assert(thread_data != NULL);
+
+ os_mutex_lock(&thread_data->wait_lock);
+ if (thread_data->thread_wait_list) {
+ /* Signal each joining thread */
+ os_thread_wait_list head = thread_data->thread_wait_list;
+ while (head) {
+ os_thread_wait_list next = head->next;
+ head->retval = retval;
+ os_sem_signal(&head->sem);
+ head = next;
+ }
+ thread_data->thread_wait_list = thread_data->thread_wait_list_end =
+ NULL;
+ }
+ /* Set thread status and thread return value */
+ thread_data->thread_exited = true;
+ thread_data->thread_retval = retval;
+ os_mutex_unlock(&thread_data->wait_lock);
+}
+
+static unsigned __stdcall os_thread_wrapper(void *arg)
+{
+ os_thread_data *thread_data = arg;
+ os_thread_data *parent = thread_data->parent;
+ void *retval;
+ bool result;
+
+#if 0
+ os_printf("THREAD CREATED %p\n", thread_data);
+#endif
+
+ os_mutex_lock(&parent->wait_lock);
+ thread_data->thread_id = GetCurrentThreadId();
+ result = TlsSetValue(thread_data_key, thread_data);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (result)
+ result = os_thread_signal_init() == 0 ? true : false;
+#endif
+ /* Notify parent thread */
+ os_cond_signal(&parent->wait_cond);
+ os_mutex_unlock(&parent->wait_lock);
+
+ if (!result)
+ return -1;
+
+ retval = thread_data->start_routine(thread_data->arg);
+
+ os_thread_cleanup(retval);
+ return 0;
+}
+
+int
+os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ os_thread_data *parent = thread_data_current();
+ os_thread_data *thread_data;
+
+ if (!p_tid || !start)
+ return BHT_ERROR;
+
+ if (stack_size < BH_APPLET_PRESERVED_STACK_SIZE)
+ stack_size = BH_APPLET_PRESERVED_STACK_SIZE;
+
+ if (!(thread_data = BH_MALLOC(sizeof(os_thread_data))))
+ return BHT_ERROR;
+
+ memset(thread_data, 0, sizeof(os_thread_data));
+ thread_data->parent = parent;
+ thread_data->start_routine = start;
+ thread_data->arg = arg;
+
+ if (os_sem_init(&thread_data->wait_node.sem) != BHT_OK)
+ goto fail1;
+
+ if (os_mutex_init(&thread_data->wait_lock) != BHT_OK)
+ goto fail2;
+
+ if (os_cond_init(&thread_data->wait_cond) != BHT_OK)
+ goto fail3;
+
+ os_mutex_lock(&parent->wait_lock);
+ if (!_beginthreadex(NULL, stack_size, os_thread_wrapper, thread_data, 0,
+ NULL)) {
+ os_mutex_unlock(&parent->wait_lock);
+ goto fail4;
+ }
+
+ /* Add thread data into thread data list */
+ os_mutex_lock(&thread_data_list_lock);
+ thread_data->next = supervisor_thread_data.next;
+ supervisor_thread_data.next = thread_data;
+ os_mutex_unlock(&thread_data_list_lock);
+
+ /* Wait for the thread routine to set thread_data's tid
+ and add thread_data to thread data list */
+ os_cond_wait(&parent->wait_cond, &parent->wait_lock);
+ os_mutex_unlock(&parent->wait_lock);
+
+ *p_tid = (korp_tid)thread_data;
+ return BHT_OK;
+
+fail4:
+ os_cond_destroy(&thread_data->wait_cond);
+fail3:
+ os_mutex_destroy(&thread_data->wait_lock);
+fail2:
+ os_sem_destroy(&thread_data->wait_node.sem);
+fail1:
+ BH_FREE(thread_data);
+ return BHT_ERROR;
+}
+
+int
+os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+korp_tid
+os_self_thread()
+{
+ return (korp_tid)TlsGetValue(thread_data_key);
+}
+
+int
+os_thread_join(korp_tid thread, void **p_retval)
+{
+ os_thread_data *thread_data, *curr_thread_data;
+
+ /* Get thread data of current thread */
+ curr_thread_data = thread_data_current();
+ curr_thread_data->wait_node.next = NULL;
+
+ /* Get thread data of thread to join */
+ thread_data = (os_thread_data *)thread;
+ bh_assert(thread_data);
+
+ os_mutex_lock(&thread_data->wait_lock);
+
+ if (thread_data->thread_exited) {
+ /* Thread has exited */
+ if (p_retval)
+ *p_retval = thread_data->thread_retval;
+ os_mutex_unlock(&thread_data->wait_lock);
+ return BHT_OK;
+ }
+
+ /* Thread is running */
+ if (!thread_data->thread_wait_list) { /* Waiting list is empty */
+ thread_data->thread_wait_list = thread_data->thread_wait_list_end =
+ &curr_thread_data->wait_node;
+ }
+ else { /* Waiting list isn't empty */
+ /* Add to end of waiting list */
+ thread_data->thread_wait_list_end->next = &curr_thread_data->wait_node;
+ thread_data->thread_wait_list_end = &curr_thread_data->wait_node;
+ }
+
+ os_mutex_unlock(&thread_data->wait_lock);
+
+ /* Wait the sem */
+ os_sem_wait(&curr_thread_data->wait_node.sem);
+ if (p_retval)
+ *p_retval = curr_thread_data->wait_node.retval;
+ return BHT_OK;
+}
+
+int
+os_thread_detach(korp_tid thread)
+{
+ /* Do nothing */
+ return BHT_OK;
+ (void)thread;
+}
+
+void
+os_thread_exit(void *retval)
+{
+ os_thread_cleanup(retval);
+ _endthreadex(0);
+}
+
+int
+os_thread_env_init()
+{
+ os_thread_data *thread_data = TlsGetValue(thread_data_key);
+
+ if (thread_data)
+ /* Already created */
+ return BHT_OK;
+
+ if (!(thread_data = BH_MALLOC(sizeof(os_thread_data))))
+ return BHT_ERROR;
+
+ memset(thread_data, 0, sizeof(os_thread_data));
+ thread_data->thread_id = GetCurrentThreadId();
+
+ if (os_sem_init(&thread_data->wait_node.sem) != BHT_OK)
+ goto fail1;
+
+ if (os_mutex_init(&thread_data->wait_lock) != BHT_OK)
+ goto fail2;
+
+ if (os_cond_init(&thread_data->wait_cond) != BHT_OK)
+ goto fail3;
+
+ if (!TlsSetValue(thread_data_key, thread_data))
+ goto fail4;
+
+ return BHT_OK;
+
+fail4:
+ os_cond_destroy(&thread_data->wait_cond);
+fail3:
+ os_mutex_destroy(&thread_data->wait_lock);
+fail2:
+ os_sem_destroy(&thread_data->wait_node.sem);
+fail1:
+ BH_FREE(thread_data);
+ return BHT_ERROR;
+}
+
+void
+os_thread_env_destroy()
+{
+ os_thread_data *thread_data = TlsGetValue(thread_data_key);
+
+ /* Note that supervisor_thread_data's resources will be destroyed
+ by os_thread_sys_destroy() */
+ if (thread_data && thread_data != &supervisor_thread_data) {
+ TlsSetValue(thread_data_key, NULL);
+ os_cond_destroy(&thread_data->wait_cond);
+ os_mutex_destroy(&thread_data->wait_lock);
+ os_sem_destroy(&thread_data->wait_node.sem);
+ BH_FREE(thread_data);
+ }
+}
+
+bool
+os_thread_env_inited()
+{
+ os_thread_data *thread_data = TlsGetValue(thread_data_key);
+ return thread_data ? true : false;
+}
+
+int
+os_sem_init(korp_sem *sem)
+{
+ bh_assert(sem);
+ *sem = CreateSemaphore(NULL, 0, BH_SEM_COUNT_MAX, NULL);
+ return (*sem != NULL) ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_sem_destroy(korp_sem *sem)
+{
+ bh_assert(sem);
+ CloseHandle(*sem);
+ return BHT_OK;
+}
+
+int
+os_sem_wait(korp_sem *sem)
+{
+ DWORD ret;
+
+ bh_assert(sem);
+
+ ret = WaitForSingleObject(*sem, INFINITE);
+
+ if (ret == WAIT_OBJECT_0)
+ return BHT_OK;
+ else if (ret == WAIT_TIMEOUT)
+ return (int)WAIT_TIMEOUT;
+ else /* WAIT_FAILED or others */
+ return BHT_ERROR;
+}
+
+int
+os_sem_reltimed_wait(korp_sem *sem, uint64 useconds)
+{
+ uint64 mseconds_64;
+ DWORD ret, mseconds;
+
+ bh_assert(sem);
+
+ if (useconds == BHT_WAIT_FOREVER)
+ mseconds = INFINITE;
+ else {
+ mseconds_64 = useconds / 1000;
+
+ if (mseconds_64 < (uint64)(UINT32_MAX - 1)) {
+ mseconds = (uint32)mseconds_64;
+ }
+ else {
+ mseconds = UINT32_MAX - 1;
+ os_printf("Warning: os_sem_reltimed_wait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+ }
+
+ ret = WaitForSingleObject(*sem, mseconds);
+
+ if (ret == WAIT_OBJECT_0)
+ return BHT_OK;
+ else if (ret == WAIT_TIMEOUT)
+ return (int)WAIT_TIMEOUT;
+ else /* WAIT_FAILED or others */
+ return BHT_ERROR;
+}
+
+int
+os_sem_signal(korp_sem *sem)
+{
+ bh_assert(sem);
+ return ReleaseSemaphore(*sem, 1, NULL) != FALSE ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ bh_assert(mutex);
+ *mutex = CreateMutex(NULL, FALSE, NULL);
+ return (*mutex != NULL) ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_recursive_mutex_init(korp_mutex *mutex)
+{
+ bh_assert(mutex);
+ *mutex = CreateMutex(NULL, FALSE, NULL);
+ return (*mutex != NULL) ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ assert(mutex);
+ return CloseHandle(*mutex) ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ int ret;
+
+ assert(mutex);
+
+ if (*mutex == NULL) { /* static initializer? */
+ HANDLE p = CreateMutex(NULL, FALSE, NULL);
+
+ if (!p) {
+ return BHT_ERROR;
+ }
+
+ if (InterlockedCompareExchangePointer((PVOID *)mutex, (PVOID)p, NULL)
+ != NULL) {
+ /* lock has been created by other threads */
+ CloseHandle(p);
+ }
+ }
+
+ ret = WaitForSingleObject(*mutex, INFINITE);
+ return ret != WAIT_FAILED ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+ bh_assert(mutex);
+ return ReleaseMutex(*mutex) ? BHT_OK : BHT_ERROR;
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ bh_assert(cond);
+ if (os_mutex_init(&cond->wait_list_lock) != BHT_OK)
+ return BHT_ERROR;
+
+ cond->thread_wait_list = cond->thread_wait_list_end = NULL;
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ bh_assert(cond);
+ os_mutex_destroy(&cond->wait_list_lock);
+ return BHT_OK;
+}
+
+static int
+os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed,
+ uint64 useconds)
+{
+ os_thread_wait_node *node = &thread_data_current()->wait_node;
+
+ node->next = NULL;
+
+ bh_assert(cond);
+ bh_assert(mutex);
+ os_mutex_lock(&cond->wait_list_lock);
+ if (!cond->thread_wait_list) { /* Waiting list is empty */
+ cond->thread_wait_list = cond->thread_wait_list_end = node;
+ }
+ else { /* Waiting list isn't empty */
+ /* Add to end of wait list */
+ cond->thread_wait_list_end->next = node;
+ cond->thread_wait_list_end = node;
+ }
+ os_mutex_unlock(&cond->wait_list_lock);
+
+ /* Unlock mutex, wait sem and lock mutex again */
+ os_mutex_unlock(mutex);
+ int wait_result;
+ if (timed)
+ wait_result = os_sem_reltimed_wait(&node->sem, useconds);
+ else
+ wait_result = os_sem_wait(&node->sem);
+ os_mutex_lock(mutex);
+
+ /* Remove wait node from wait list */
+ os_mutex_lock(&cond->wait_list_lock);
+ if (cond->thread_wait_list == node) {
+ cond->thread_wait_list = node->next;
+
+ if (cond->thread_wait_list_end == node) {
+ bh_assert(node->next == NULL);
+ cond->thread_wait_list_end = NULL;
+ }
+ }
+ else {
+ /* Remove from the wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next != node)
+ p = p->next;
+ p->next = node->next;
+
+ if (cond->thread_wait_list_end == node) {
+ cond->thread_wait_list_end = p;
+ }
+ }
+ os_mutex_unlock(&cond->wait_list_lock);
+
+ return wait_result;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return os_cond_wait_internal(cond, mutex, false, 0);
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+ if (useconds == BHT_WAIT_FOREVER) {
+ return os_cond_wait_internal(cond, mutex, false, 0);
+ }
+ else {
+ return os_cond_wait_internal(cond, mutex, true, useconds);
+ }
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ /* Signal the head wait node of wait list */
+ os_mutex_lock(&cond->wait_list_lock);
+ if (cond->thread_wait_list)
+ os_sem_signal(&cond->thread_wait_list->sem);
+ os_mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+int
+os_cond_broadcast(korp_cond *cond)
+{
+ /* Signal all of the wait node of wait list */
+ os_mutex_lock(&cond->wait_list_lock);
+ if (cond->thread_wait_list) {
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p) {
+ os_sem_signal(&p->sem);
+ p = p->next;
+ }
+ }
+
+ os_mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
+
+static ULONG
+GetCurrentThreadStackLimits_Win7(PULONG_PTR p_low_limit,
+ PULONG_PTR p_high_limit)
+{
+ MEMORY_BASIC_INFORMATION mbi;
+ NT_TIB *tib = (NT_TIB *)NtCurrentTeb();
+
+ if (!tib) {
+ os_printf("warning: NtCurrentTeb() failed\n");
+ return -1;
+ }
+
+ *p_high_limit = (ULONG_PTR)tib->StackBase;
+
+ if (VirtualQuery(tib->StackLimit, &mbi, sizeof(mbi))) {
+ *p_low_limit = (ULONG_PTR)mbi.AllocationBase;
+ return 0;
+ }
+
+ os_printf("warning: VirtualQuery() failed\n");
+ return GetLastError();
+}
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+ ULONG_PTR low_limit = 0, high_limit = 0;
+ uint32 page_size;
+
+ if (thread_stack_boundary)
+ return thread_stack_boundary;
+
+ page_size = os_getpagesize();
+ if (GetCurrentThreadStackLimits_Kernel32) {
+ GetCurrentThreadStackLimits_Kernel32(&low_limit, &high_limit);
+ }
+ else {
+ if (0 != GetCurrentThreadStackLimits_Win7(&low_limit, &high_limit))
+ return NULL;
+ }
+
+ /* 4 pages are set unaccessible by system, we reserved
+ one more page at least for safety */
+ thread_stack_boundary = (uint8 *)(uintptr_t)low_limit + page_size * 5;
+ return thread_stack_boundary;
+}
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+static os_thread_local_attribute bool thread_signal_inited = false;
+
+int
+os_thread_signal_init()
+{
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ ULONG StackSizeInBytes = 16 * 1024;
+#endif
+ bool ret;
+
+ if (thread_signal_inited)
+ return 0;
+
+#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
+ ret = SetThreadStackGuarantee(&StackSizeInBytes);
+#else
+ ret = true;
+#endif
+ if (ret)
+ thread_signal_inited = true;
+ return ret ? 0 : -1;
+}
+
+void
+os_thread_signal_destroy()
+{
+ /* Do nothing */
+}
+
+bool
+os_thread_signal_inited()
+{
+ return thread_signal_inited;
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c
new file mode 100644
index 000000000..20e90d5eb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+uint64
+os_time_get_boot_microsecond()
+{
+ struct timespec ts;
+#if defined(__MINGW32__)
+ // https://www.mail-archive.com/mingw-w64-public@lists.sourceforge.net/msg18361.html
+ clock_gettime(CLOCK_REALTIME, &ts);
+#else
+ timespec_get(&ts, TIME_UTC);
+#endif
+
+ return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/platform_internal.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/platform_internal.h
new file mode 100644
index 000000000..d2a94e4ad
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/platform_internal.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <autoconf.h>
+#include <version.h>
+
+#if KERNEL_VERSION_NUMBER < 0x030200 /* version 3.2.0 */
+#include <zephyr.h>
+#include <kernel.h>
+#if KERNEL_VERSION_NUMBER >= 0x020200 /* version 2.2.0 */
+#include <sys/printk.h>
+#else
+#include <misc/printk.h>
+#endif
+#else /* else of KERNEL_VERSION_NUMBER < 0x030200 */
+#include <zephyr/kernel.h>
+#include <zephyr/sys/printk.h>
+#endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#ifndef CONFIG_NET_BUF_USER_DATA_SIZE
+#define CONFIG_NET_BUF_USER_DATA_SIZE 0
+#endif
+
+#if KERNEL_VERSION_NUMBER < 0x030200 /* version 3.2.0 */
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_ip.h>
+#include <net/net_core.h>
+#include <net/net_context.h>
+
+#ifdef CONFIG_ARM_MPU
+#include <arch/arm/aarch32/cortex_m/cmsis.h>
+#endif
+#else /* else of KERNEL_VERSION_NUMBER < 0x030200 */
+#include <zephyr/net/net_pkt.h>
+#include <zephyr/net/net_if.h>
+#include <zephyr/net/net_ip.h>
+#include <zephyr/net/net_core.h>
+#include <zephyr/net/net_context.h>
+
+#ifdef CONFIG_ARM_MPU
+#include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
+#endif
+#endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */
+
+#ifndef BH_PLATFORM_ZEPHYR
+#define BH_PLATFORM_ZEPHYR
+#endif
+
+#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 7
+
+typedef struct k_thread korp_thread;
+typedef korp_thread *korp_tid;
+typedef struct k_mutex korp_mutex;
+typedef unsigned int korp_sem;
+
+struct os_thread_wait_node;
+typedef struct os_thread_wait_node *os_thread_wait_list;
+typedef struct korp_cond {
+ struct k_mutex wait_list_lock;
+ os_thread_wait_list thread_wait_list;
+} korp_cond;
+
+#ifndef Z_TIMEOUT_MS
+#define Z_TIMEOUT_MS(ms) ms
+#endif
+
+/* clang-format off */
+void abort(void);
+size_t strspn(const char *s, const char *accept);
+size_t strcspn(const char *s, const char *reject);
+
+/* math functions which are not provided by os */
+double atan(double x);
+double atan2(double y, double x);
+double sqrt(double x);
+double floor(double x);
+double ceil(double x);
+double fmin(double x, double y);
+double fmax(double x, double y);
+double rint(double x);
+double fabs(double x);
+double trunc(double x);
+float sqrtf(float 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 fabsf(float x);
+float truncf(float x);
+int signbit(double x);
+int isnan(double x);
+double pow(double x, double y);
+double scalbn(double x, int n);
+
+unsigned long long int strtoull(const char *nptr, char **endptr, int base);
+double strtod(const char *nptr, char **endptr);
+float strtof(const char *nptr, char **endptr);
+/* clang-format on */
+
+#if KERNEL_VERSION_NUMBER >= 0x030100 /* version 3.1.0 */
+#define BH_HAS_SQRT
+#define BH_HAS_SQRTF
+#endif
+
+/**
+ * @brief Allocate executable memroy
+ *
+ * @param size size of the memory to be allocated
+ *
+ * @return the address of the allocated memory if not NULL
+ */
+typedef void *(*exec_mem_alloc_func_t)(unsigned int size);
+
+/**
+ * @brief Release executable memroy
+ *
+ * @param the address of the executable memory to be released
+ */
+typedef void (*exec_mem_free_func_t)(void *addr);
+
+/* Below function are called by external project to set related function
+ * pointers that will be used to malloc/free executable memory. Otherwise
+ * default mechanise will be used.
+ */
+void
+set_exec_mem_alloc_func(exec_mem_alloc_func_t alloc_func,
+ exec_mem_free_func_t free_func);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/shared_platform.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/shared_platform.cmake
new file mode 100644
index 000000000..9b043b52f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/shared_platform.cmake
@@ -0,0 +1,16 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_ZEPHYR)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_platform.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_platform.c
new file mode 100644
index 000000000..b4f2e5ec7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_platform.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+/* function pointers for executable memory management */
+static exec_mem_alloc_func_t exec_mem_alloc_func = NULL;
+static exec_mem_free_func_t exec_mem_free_func = NULL;
+
+#if WASM_ENABLE_AOT != 0
+#ifdef CONFIG_ARM_MPU
+/**
+ * This function will allow execute from sram region.
+ * This is needed for AOT code because by default all soc will
+ * disable the execute from SRAM.
+ */
+static void
+disable_mpu_rasr_xn(void)
+{
+ uint32 index;
+ /* Kept the max index as 8 (irrespective of soc) because the sram
+ would most likely be set at index 2. */
+ for (index = 0U; index < 8; index++) {
+ MPU->RNR = index;
+ if (MPU->RASR & MPU_RASR_XN_Msk) {
+ MPU->RASR |= ~MPU_RASR_XN_Msk;
+ }
+ }
+}
+#endif /* end of CONFIG_ARM_MPU */
+#endif
+
+static int
+_stdout_hook_iwasm(int c)
+{
+ printk("%c", (char)c);
+ return 1;
+}
+
+int
+os_thread_sys_init();
+
+void
+os_thread_sys_destroy();
+
+int
+bh_platform_init()
+{
+ extern void __stdout_hook_install(int (*hook)(int));
+ /* Enable printf() in Zephyr */
+ __stdout_hook_install(_stdout_hook_iwasm);
+
+#if WASM_ENABLE_AOT != 0
+#ifdef CONFIG_ARM_MPU
+ /* Enable executable memory support */
+ disable_mpu_rasr_xn();
+#endif
+#endif
+
+ return os_thread_sys_init();
+}
+
+void
+bh_platform_destroy()
+{
+ os_thread_sys_destroy();
+}
+
+void *
+os_malloc(unsigned size)
+{
+ return NULL;
+}
+
+void *
+os_realloc(void *ptr, unsigned size)
+{
+ return NULL;
+}
+
+void
+os_free(void *ptr)
+{}
+
+int
+os_dumps_proc_mem_info(char *out, unsigned int size)
+{
+ return -1;
+}
+
+#if 0
+struct out_context {
+ int count;
+};
+
+typedef int (*out_func_t)(int c, void *ctx);
+
+static int
+char_out(int c, void *ctx)
+{
+ struct out_context *out_ctx = (struct out_context*)ctx;
+ out_ctx->count++;
+ return _stdout_hook_iwasm(c);
+}
+
+int
+os_vprintf(const char *fmt, va_list ap)
+{
+#if 0
+ struct out_context ctx = { 0 };
+ cbvprintf(char_out, &ctx, fmt, ap);
+ return ctx.count;
+#else
+ vprintk(fmt, ap);
+ return 0;
+#endif
+}
+#endif
+
+int
+os_printf(const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start(ap, format);
+#ifndef BH_VPRINTF
+ ret += vprintf(format, ap);
+#else
+ ret += BH_VPRINTF(format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+ return vprintf(format, ap);
+#else
+ return BH_VPRINTF(format, ap);
+#endif
+}
+
+#if KERNEL_VERSION_NUMBER <= 0x020400 /* version 2.4.0 */
+void
+abort(void)
+{
+ int i = 0;
+ os_printf("%d\n", 1 / i);
+}
+#endif
+
+#if KERNEL_VERSION_NUMBER <= 0x010E01 /* version 1.14.1 */
+size_t
+strspn(const char *s, const char *accept)
+{
+ os_printf("## unimplemented function %s called", __FUNCTION__);
+ return 0;
+}
+
+size_t
+strcspn(const char *s, const char *reject)
+{
+ os_printf("## unimplemented function %s called", __FUNCTION__);
+ return 0;
+}
+#endif
+
+void *
+os_mmap(void *hint, size_t size, int prot, int flags)
+{
+ if ((uint64)size >= UINT32_MAX)
+ return NULL;
+ if (exec_mem_alloc_func)
+ return exec_mem_alloc_func((uint32)size);
+ else
+ return BH_MALLOC(size);
+}
+
+void
+os_munmap(void *addr, size_t size)
+{
+ if (exec_mem_free_func)
+ exec_mem_free_func(addr);
+ else
+ BH_FREE(addr);
+}
+
+int
+os_mprotect(void *addr, size_t size, int prot)
+{
+ return 0;
+}
+
+void
+os_dcache_flush()
+{
+#if defined(CONFIG_CPU_CORTEX_M7) && defined(CONFIG_ARM_MPU)
+ uint32 key;
+ key = irq_lock();
+ SCB_CleanDCache();
+ irq_unlock(key);
+#elif defined(CONFIG_SOC_CVF_EM7D) && defined(CONFIG_ARC_MPU) \
+ && defined(CONFIG_CACHE_FLUSHING)
+ __asm__ __volatile__("sync");
+ z_arc_v2_aux_reg_write(_ARC_V2_DC_FLSH, BIT(0));
+ __asm__ __volatile__("sync");
+#endif
+}
+
+void
+set_exec_mem_alloc_func(exec_mem_alloc_func_t alloc_func,
+ exec_mem_free_func_t free_func)
+{
+ exec_mem_alloc_func = alloc_func;
+ exec_mem_free_func = free_func;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_thread.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_thread.c
new file mode 100644
index 000000000..1ee2c5cef
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_thread.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+/* clang-format off */
+#define bh_assert(v) do { \
+ if (!(v)) { \
+ printf("\nASSERTION FAILED: %s, at %s, line %d\n", \
+ #v, __FILE__, __LINE__); \
+ abort(); \
+ } \
+} while (0)
+/* clang-format on */
+
+#if defined(CONFIG_ARM_MPU) || defined(CONFIG_ARC_MPU) \
+ || KERNEL_VERSION_NUMBER > 0x020300 /* version 2.3.0 */
+#define BH_ENABLE_ZEPHYR_MPU_STACK 1
+#elif !defined(BH_ENABLE_ZEPHYR_MPU_STACK)
+#define BH_ENABLE_ZEPHYR_MPU_STACK 0
+#endif
+#if !defined(BH_ZEPHYR_MPU_STACK_SIZE)
+#define BH_ZEPHYR_MPU_STACK_SIZE APP_THREAD_STACK_SIZE_MIN
+#endif
+#if !defined(BH_ZEPHYR_MPU_STACK_COUNT)
+#define BH_ZEPHYR_MPU_STACK_COUNT 4
+#endif
+
+#if BH_ENABLE_ZEPHYR_MPU_STACK != 0
+static K_THREAD_STACK_ARRAY_DEFINE(mpu_stacks, BH_ZEPHYR_MPU_STACK_COUNT,
+ BH_ZEPHYR_MPU_STACK_SIZE);
+static bool mpu_stack_allocated[BH_ZEPHYR_MPU_STACK_COUNT];
+static struct k_mutex mpu_stack_lock;
+
+static char *
+mpu_stack_alloc()
+{
+ int i;
+
+ k_mutex_lock(&mpu_stack_lock, K_FOREVER);
+ for (i = 0; i < BH_ZEPHYR_MPU_STACK_COUNT; i++) {
+ if (!mpu_stack_allocated[i]) {
+ mpu_stack_allocated[i] = true;
+ k_mutex_unlock(&mpu_stack_lock);
+ return (char *)mpu_stacks[i];
+ }
+ }
+ k_mutex_unlock(&mpu_stack_lock);
+ return NULL;
+}
+
+static void
+mpu_stack_free(char *stack)
+{
+ int i;
+
+ k_mutex_lock(&mpu_stack_lock, K_FOREVER);
+ for (i = 0; i < BH_ZEPHYR_MPU_STACK_COUNT; i++) {
+ if ((char *)mpu_stacks[i] == stack)
+ mpu_stack_allocated[i] = false;
+ }
+ k_mutex_unlock(&mpu_stack_lock);
+}
+#endif
+
+typedef struct os_thread_wait_node {
+ struct k_sem sem;
+ os_thread_wait_list next;
+} os_thread_wait_node;
+
+typedef struct os_thread_data {
+ /* Next thread data */
+ struct os_thread_data *next;
+ /* Zephyr thread handle */
+ korp_tid tid;
+ /* Jeff thread local root */
+ void *tlr;
+ /* Lock for waiting list */
+ struct k_mutex wait_list_lock;
+ /* Waiting list of other threads who are joining this thread */
+ os_thread_wait_list thread_wait_list;
+ /* Thread stack size */
+ unsigned stack_size;
+#if BH_ENABLE_ZEPHYR_MPU_STACK == 0
+ /* Thread stack */
+ char stack[1];
+#else
+ char *stack;
+#endif
+} os_thread_data;
+
+typedef struct os_thread_obj {
+ struct k_thread thread;
+ /* Whether the thread is terminated and this thread object is to
+ be freed in the future. */
+ bool to_be_freed;
+ struct os_thread_obj *next;
+} os_thread_obj;
+
+static bool is_thread_sys_inited = false;
+
+/* Thread data of supervisor thread */
+static os_thread_data supervisor_thread_data;
+
+/* Lock for thread data list */
+static struct k_mutex thread_data_lock;
+
+/* Thread data list */
+static os_thread_data *thread_data_list = NULL;
+
+/* Lock for thread object list */
+static struct k_mutex thread_obj_lock;
+
+/* Thread object list */
+static os_thread_obj *thread_obj_list = NULL;
+
+static void
+thread_data_list_add(os_thread_data *thread_data)
+{
+ k_mutex_lock(&thread_data_lock, K_FOREVER);
+ if (!thread_data_list)
+ thread_data_list = thread_data;
+ else {
+ /* If already in list, just return */
+ os_thread_data *p = thread_data_list;
+ while (p) {
+ if (p == thread_data) {
+ k_mutex_unlock(&thread_data_lock);
+ return;
+ }
+ p = p->next;
+ }
+
+ /* Set as head of list */
+ thread_data->next = thread_data_list;
+ thread_data_list = thread_data;
+ }
+ k_mutex_unlock(&thread_data_lock);
+}
+
+static void
+thread_data_list_remove(os_thread_data *thread_data)
+{
+ k_mutex_lock(&thread_data_lock, K_FOREVER);
+ if (thread_data_list) {
+ if (thread_data_list == thread_data)
+ thread_data_list = thread_data_list->next;
+ else {
+ /* Search and remove it from list */
+ os_thread_data *p = thread_data_list;
+ while (p && p->next != thread_data)
+ p = p->next;
+ if (p && p->next == thread_data)
+ p->next = p->next->next;
+ }
+ }
+ k_mutex_unlock(&thread_data_lock);
+}
+
+static os_thread_data *
+thread_data_list_lookup(k_tid_t tid)
+{
+ k_mutex_lock(&thread_data_lock, K_FOREVER);
+ if (thread_data_list) {
+ os_thread_data *p = thread_data_list;
+ while (p) {
+ if (p->tid == tid) {
+ /* Found */
+ k_mutex_unlock(&thread_data_lock);
+ return p;
+ }
+ p = p->next;
+ }
+ }
+ k_mutex_unlock(&thread_data_lock);
+ return NULL;
+}
+
+static void
+thread_obj_list_add(os_thread_obj *thread_obj)
+{
+ k_mutex_lock(&thread_obj_lock, K_FOREVER);
+ if (!thread_obj_list)
+ thread_obj_list = thread_obj;
+ else {
+ /* Set as head of list */
+ thread_obj->next = thread_obj_list;
+ thread_obj_list = thread_obj;
+ }
+ k_mutex_unlock(&thread_obj_lock);
+}
+
+static void
+thread_obj_list_reclaim()
+{
+ os_thread_obj *p, *p_prev;
+ k_mutex_lock(&thread_obj_lock, K_FOREVER);
+ p_prev = NULL;
+ p = thread_obj_list;
+ while (p) {
+ if (p->to_be_freed) {
+ if (p_prev == NULL) { /* p is the head of list */
+ thread_obj_list = p->next;
+ BH_FREE(p);
+ p = thread_obj_list;
+ }
+ else { /* p is not the head of list */
+ p_prev->next = p->next;
+ BH_FREE(p);
+ p = p_prev->next;
+ }
+ }
+ else {
+ p_prev = p;
+ p = p->next;
+ }
+ }
+ k_mutex_unlock(&thread_obj_lock);
+}
+
+int
+os_thread_sys_init()
+{
+ if (is_thread_sys_inited)
+ return BHT_OK;
+
+#if BH_ENABLE_ZEPHYR_MPU_STACK != 0
+ k_mutex_init(&mpu_stack_lock);
+#endif
+ k_mutex_init(&thread_data_lock);
+ k_mutex_init(&thread_obj_lock);
+
+ /* Initialize supervisor thread data */
+ memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
+ supervisor_thread_data.tid = k_current_get();
+ /* Set as head of thread data list */
+ thread_data_list = &supervisor_thread_data;
+
+ is_thread_sys_inited = true;
+ return BHT_OK;
+}
+
+void
+os_thread_sys_destroy(void)
+{
+ if (is_thread_sys_inited) {
+ is_thread_sys_inited = false;
+ }
+}
+
+static os_thread_data *
+thread_data_current()
+{
+ k_tid_t tid = k_current_get();
+ return thread_data_list_lookup(tid);
+}
+
+static void
+os_thread_cleanup(void)
+{
+ os_thread_data *thread_data = thread_data_current();
+
+ bh_assert(thread_data != NULL);
+ k_mutex_lock(&thread_data->wait_list_lock, K_FOREVER);
+ if (thread_data->thread_wait_list) {
+ /* Signal each joining thread */
+ os_thread_wait_list head = thread_data->thread_wait_list;
+ while (head) {
+ os_thread_wait_list next = head->next;
+ k_sem_give(&head->sem);
+ /* head will be freed by joining thread */
+ head = next;
+ }
+ thread_data->thread_wait_list = NULL;
+ }
+ k_mutex_unlock(&thread_data->wait_list_lock);
+
+ thread_data_list_remove(thread_data);
+ /* Set flag to true for the next thread creating to
+ free the thread object */
+ ((os_thread_obj *)thread_data->tid)->to_be_freed = true;
+#if BH_ENABLE_ZEPHYR_MPU_STACK != 0
+ mpu_stack_free(thread_data->stack);
+#endif
+ BH_FREE(thread_data);
+}
+
+static void
+os_thread_wrapper(void *start, void *arg, void *thread_data)
+{
+ /* Set thread custom data */
+ ((os_thread_data *)thread_data)->tid = k_current_get();
+ thread_data_list_add(thread_data);
+
+ ((thread_start_routine_t)start)(arg);
+ os_thread_cleanup();
+}
+
+int
+os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg,
+ unsigned int stack_size)
+{
+ return os_thread_create_with_prio(p_tid, start, arg, stack_size,
+ BH_THREAD_DEFAULT_PRIORITY);
+}
+
+int
+os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
+ void *arg, unsigned int stack_size, int prio)
+{
+ korp_tid tid;
+ os_thread_data *thread_data;
+ unsigned thread_data_size;
+
+ if (!p_tid || !stack_size)
+ return BHT_ERROR;
+
+ /* Free the thread objects of terminated threads */
+ thread_obj_list_reclaim();
+
+ /* Create and initialize thread object */
+ if (!(tid = BH_MALLOC(sizeof(os_thread_obj))))
+ return BHT_ERROR;
+
+ memset(tid, 0, sizeof(os_thread_obj));
+
+ /* Create and initialize thread data */
+#if BH_ENABLE_ZEPHYR_MPU_STACK == 0
+ if (stack_size < APP_THREAD_STACK_SIZE_MIN)
+ stack_size = APP_THREAD_STACK_SIZE_MIN;
+ thread_data_size = offsetof(os_thread_data, stack) + stack_size;
+#else
+ stack_size = BH_ZEPHYR_MPU_STACK_SIZE;
+ thread_data_size = sizeof(os_thread_data);
+#endif
+ if (!(thread_data = BH_MALLOC(thread_data_size))) {
+ goto fail1;
+ }
+
+ memset(thread_data, 0, thread_data_size);
+ k_mutex_init(&thread_data->wait_list_lock);
+ thread_data->stack_size = stack_size;
+ thread_data->tid = tid;
+
+#if BH_ENABLE_ZEPHYR_MPU_STACK != 0
+ if (!(thread_data->stack = mpu_stack_alloc())) {
+ goto fail2;
+ }
+#endif
+
+ /* Create the thread */
+ if (!((tid = k_thread_create(tid, (k_thread_stack_t *)thread_data->stack,
+ stack_size, os_thread_wrapper, start, arg,
+ thread_data, prio, 0, K_NO_WAIT)))) {
+ goto fail3;
+ }
+
+ bh_assert(tid == thread_data->tid);
+
+ /* Set thread custom data */
+ thread_data_list_add(thread_data);
+ thread_obj_list_add((os_thread_obj *)tid);
+ *p_tid = tid;
+ return BHT_OK;
+
+fail3:
+#if BH_ENABLE_ZEPHYR_MPU_STACK != 0
+ mpu_stack_free(thread_data->stack);
+fail2:
+#endif
+ BH_FREE(thread_data);
+fail1:
+ BH_FREE(tid);
+ return BHT_ERROR;
+}
+
+korp_tid
+os_self_thread()
+{
+ return (korp_tid)k_current_get();
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+ (void)value_ptr;
+ os_thread_data *thread_data;
+ os_thread_wait_node *node;
+
+ /* Create wait node and append it to wait list */
+ if (!(node = BH_MALLOC(sizeof(os_thread_wait_node))))
+ return BHT_ERROR;
+
+ k_sem_init(&node->sem, 0, 1);
+ node->next = NULL;
+
+ /* Get thread data */
+ thread_data = thread_data_list_lookup(thread);
+ bh_assert(thread_data != NULL);
+
+ k_mutex_lock(&thread_data->wait_list_lock, K_FOREVER);
+ if (!thread_data->thread_wait_list)
+ thread_data->thread_wait_list = node;
+ else {
+ /* Add to end of waiting list */
+ os_thread_wait_node *p = thread_data->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = node;
+ }
+ k_mutex_unlock(&thread_data->wait_list_lock);
+
+ /* Wait the sem */
+ k_sem_take(&node->sem, K_FOREVER);
+
+ /* Wait some time for the thread to be actually terminated */
+ k_sleep(Z_TIMEOUT_MS(100));
+
+ /* Destroy resource */
+ BH_FREE(node);
+ return BHT_OK;
+}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+ k_mutex_init(mutex);
+ return BHT_OK;
+}
+
+int
+os_recursive_mutex_init(korp_mutex *mutex)
+{
+ k_mutex_init(mutex);
+ return BHT_OK;
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+ (void)mutex;
+ return BHT_OK;
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+ return k_mutex_lock(mutex, K_FOREVER);
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+#if KERNEL_VERSION_NUMBER >= 0x020200 /* version 2.2.0 */
+ return k_mutex_unlock(mutex);
+#else
+ k_mutex_unlock(mutex);
+ return 0;
+#endif
+}
+
+int
+os_cond_init(korp_cond *cond)
+{
+ k_mutex_init(&cond->wait_list_lock);
+ cond->thread_wait_list = NULL;
+ return BHT_OK;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+ (void)cond;
+ return BHT_OK;
+}
+
+static int
+os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed, int mills)
+{
+ os_thread_wait_node *node;
+
+ /* Create wait node and append it to wait list */
+ if (!(node = BH_MALLOC(sizeof(os_thread_wait_node))))
+ return BHT_ERROR;
+
+ k_sem_init(&node->sem, 0, 1);
+ node->next = NULL;
+
+ k_mutex_lock(&cond->wait_list_lock, K_FOREVER);
+ if (!cond->thread_wait_list)
+ cond->thread_wait_list = node;
+ else {
+ /* Add to end of wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next)
+ p = p->next;
+ p->next = node;
+ }
+ k_mutex_unlock(&cond->wait_list_lock);
+
+ /* Unlock mutex, wait sem and lock mutex again */
+ k_mutex_unlock(mutex);
+ k_sem_take(&node->sem, timed ? Z_TIMEOUT_MS(mills) : K_FOREVER);
+ k_mutex_lock(mutex, K_FOREVER);
+
+ /* Remove wait node from wait list */
+ k_mutex_lock(&cond->wait_list_lock, K_FOREVER);
+ if (cond->thread_wait_list == node)
+ cond->thread_wait_list = node->next;
+ else {
+ /* Remove from the wait list */
+ os_thread_wait_node *p = cond->thread_wait_list;
+ while (p->next != node)
+ p = p->next;
+ p->next = node->next;
+ }
+ BH_FREE(node);
+ k_mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+ return os_cond_wait_internal(cond, mutex, false, 0);
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+
+ if (useconds == BHT_WAIT_FOREVER) {
+ return os_cond_wait_internal(cond, mutex, false, 0);
+ }
+ else {
+ uint64 mills_64 = useconds / 1000;
+ int32 mills;
+
+ if (mills_64 < (uint64)INT32_MAX) {
+ mills = (int32)mills_64;
+ }
+ else {
+ mills = INT32_MAX;
+ os_printf("Warning: os_cond_reltimedwait exceeds limit, "
+ "set to max timeout instead\n");
+ }
+ return os_cond_wait_internal(cond, mutex, true, mills);
+ }
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+ /* Signal the head wait node of wait list */
+ k_mutex_lock(&cond->wait_list_lock, K_FOREVER);
+ if (cond->thread_wait_list)
+ k_sem_give(&cond->thread_wait_list->sem);
+ k_mutex_unlock(&cond->wait_list_lock);
+
+ return BHT_OK;
+}
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+#if defined(CONFIG_THREAD_STACK_INFO)
+ korp_tid thread = k_current_get();
+ return (uint8 *)thread->stack_info.start;
+#else
+ return NULL;
+#endif
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_time.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_time.c
new file mode 100644
index 000000000..99eb3b354
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/zephyr/zephyr_time.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+uint64
+os_time_get_boot_microsecond()
+{
+ return k_uptime_get() * 1000;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/SConscript
new file mode 100644
index 000000000..358f2ffca
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/SConscript
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import os
+
+cwd = GetCurrentDir()
+
+src = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_shared_utils', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.c
new file mode 100644
index 000000000..246c55d1b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_assert.h"
+
+void
+bh_assert_internal(int64 v, const char *file_name, int line_number,
+ const char *expr_string)
+{
+ if (v)
+ return;
+
+ if (!file_name)
+ file_name = "NULL FILENAME";
+
+ if (!expr_string)
+ expr_string = "NULL EXPR_STRING";
+
+ os_printf("\nASSERTION FAILED: %s, at file %s, line %d\n", expr_string,
+ file_name, line_number);
+
+ abort();
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.h
new file mode 100644
index 000000000..b7c995af8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_assert.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _BH_ASSERT_H
+#define _BH_ASSERT_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if BH_DEBUG != 0
+void
+bh_assert_internal(int64 v, const char *file_name, int line_number,
+ const char *expr_string);
+#define bh_assert(expr) \
+ bh_assert_internal((int64)(uintptr_t)(expr), __FILE__, __LINE__, #expr)
+#else
+#define bh_assert(expr) (void)0
+#endif /* end of BH_DEBUG */
+
+#if !defined(__has_extension)
+#define __has_extension(a) 0
+#endif
+
+#if __STDC_VERSION__ >= 201112L \
+ || (defined(__GNUC__) && __GNUC__ * 0x100 + __GNUC_MINOR__ >= 0x406) \
+ || __has_extension(c_static_assert)
+
+#define bh_static_assert(expr) _Static_assert(expr, #expr)
+#else
+#define bh_static_assert(expr) /* nothing */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _BH_ASSERT_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.c
new file mode 100644
index 000000000..aeeab26bd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_common.h"
+
+static char *
+align_ptr(char *src, unsigned int b)
+{
+ uintptr_t v = (uintptr_t)src;
+ uintptr_t m = b - 1;
+ return (char *)((v + m) & ~m);
+}
+
+/*
+Memory copy, with word alignment
+*/
+int
+b_memcpy_wa(void *s1, unsigned int s1max, const void *s2, unsigned int n)
+{
+ char *dest = (char *)s1;
+ char *src = (char *)s2;
+
+ char *pa = align_ptr(src, 4);
+ char *pb = align_ptr((src + n), 4);
+
+ unsigned int buff;
+ const char *p_byte_read;
+
+ unsigned int *p;
+ char *ps;
+
+ if (pa > src) {
+ pa -= 4;
+ }
+
+ for (p = (unsigned int *)pa; p < (unsigned int *)pb; p++) {
+ buff = *(p);
+ p_byte_read = ((char *)&buff);
+
+ /* read leading word */
+ if ((char *)p <= src) {
+ for (ps = src; ps < ((char *)p + 4); ps++) {
+ if (ps >= src + n) {
+ break;
+ }
+ p_byte_read = ((char *)&buff) + (ps - (char *)p);
+ *dest++ = *p_byte_read;
+ }
+ }
+ /* read trailing word */
+ else if ((char *)p >= pb - 4) {
+ for (ps = (char *)p; ps < src + n; ps++) {
+ *dest++ = *p_byte_read++;
+ }
+ }
+ /* read meaning word(s) */
+ else {
+ if ((char *)p + 4 >= src + n) {
+ for (ps = (char *)p; ps < src + n; ps++) {
+ *dest++ = *p_byte_read++;
+ }
+ }
+ else {
+ *(unsigned int *)dest = buff;
+ dest += 4;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+b_memcpy_s(void *s1, unsigned int s1max, const void *s2, unsigned int n)
+{
+ char *dest = (char *)s1;
+ char *src = (char *)s2;
+ if (n == 0) {
+ return 0;
+ }
+
+ if (s1 == NULL) {
+ return -1;
+ }
+ if (s2 == NULL || n > s1max) {
+ memset(dest, 0, s1max);
+ return -1;
+ }
+ memcpy(dest, src, n);
+ return 0;
+}
+
+int
+b_memmove_s(void *s1, unsigned int s1max, const void *s2, unsigned int n)
+{
+ char *dest = (char *)s1;
+ char *src = (char *)s2;
+ if (n == 0) {
+ return 0;
+ }
+
+ if (s1 == NULL) {
+ return -1;
+ }
+ if (s2 == NULL || n > s1max) {
+ memset(dest, 0, s1max);
+ return -1;
+ }
+ memmove(dest, src, n);
+ return 0;
+}
+
+int
+b_strcat_s(char *s1, unsigned int s1max, const char *s2)
+{
+ if (NULL == s1 || NULL == s2 || s1max < (strlen(s1) + strlen(s2) + 1)) {
+ return -1;
+ }
+
+ memcpy(s1 + strlen(s1), s2, strlen(s2) + 1);
+ return 0;
+}
+
+int
+b_strcpy_s(char *s1, unsigned int s1max, const char *s2)
+{
+ if (NULL == s1 || NULL == s2 || s1max < (strlen(s2) + 1)) {
+ return -1;
+ }
+
+ memcpy(s1, s2, strlen(s2) + 1);
+ return 0;
+}
+
+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;
+}
+
+char *
+wa_strdup(const char *s)
+{
+ uint32 size;
+ char *s1 = NULL;
+
+ if (s) {
+ size = (uint32)(strlen(s) + 1);
+ if ((s1 = WA_MALLOC(size)))
+ bh_memcpy_s(s1, size, s, size);
+ }
+ return s1;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.h
new file mode 100644
index 000000000..edb962eb1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_common.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _BH_COMMON_H
+#define _BH_COMMON_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define bh_memcpy_s(dest, dlen, src, slen) \
+ do { \
+ int _ret = slen == 0 ? 0 : b_memcpy_s(dest, dlen, src, slen); \
+ (void)_ret; \
+ bh_assert(_ret == 0); \
+ } while (0)
+
+#define bh_memcpy_wa(dest, dlen, src, slen) \
+ do { \
+ int _ret = slen == 0 ? 0 : b_memcpy_wa(dest, dlen, src, slen); \
+ (void)_ret; \
+ bh_assert(_ret == 0); \
+ } while (0)
+
+#define bh_memmove_s(dest, dlen, src, slen) \
+ do { \
+ int _ret = slen == 0 ? 0 : b_memmove_s(dest, dlen, src, slen); \
+ (void)_ret; \
+ bh_assert(_ret == 0); \
+ } while (0)
+
+#define bh_strcat_s(dest, dlen, src) \
+ do { \
+ int _ret = b_strcat_s(dest, dlen, src); \
+ (void)_ret; \
+ bh_assert(_ret == 0); \
+ } while (0)
+
+#define bh_strcpy_s(dest, dlen, src) \
+ do { \
+ int _ret = b_strcpy_s(dest, dlen, src); \
+ (void)_ret; \
+ bh_assert(_ret == 0); \
+ } while (0)
+
+int
+b_memcpy_s(void *s1, unsigned int s1max, const void *s2, unsigned int n);
+int
+b_memcpy_wa(void *s1, unsigned int s1max, const void *s2, unsigned int n);
+int
+b_memmove_s(void *s1, unsigned int s1max, const void *s2, unsigned int n);
+int
+b_strcat_s(char *s1, unsigned int s1max, const char *s2);
+int
+b_strcpy_s(char *s1, unsigned int s1max, const char *s2);
+
+/* strdup with string allocated by BH_MALLOC */
+char *
+bh_strdup(const char *s);
+
+/* strdup with string allocated by WA_MALLOC */
+char *
+wa_strdup(const char *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.c
new file mode 100644
index 000000000..3502239ad
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_hashmap.h"
+
+typedef struct HashMapElem {
+ void *key;
+ void *value;
+ struct HashMapElem *next;
+} HashMapElem;
+
+struct HashMap {
+ /* size of element array */
+ uint32 size;
+ /* lock for elements */
+ korp_mutex *lock;
+ /* hash function of key */
+ HashFunc hash_func;
+ /* key equal function */
+ KeyEqualFunc key_equal_func;
+ KeyDestroyFunc key_destroy_func;
+ ValueDestroyFunc value_destroy_func;
+ HashMapElem *elements[1];
+};
+
+HashMap *
+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;
+
+ if (size < HASH_MAP_MIN_SIZE)
+ size = HASH_MAP_MIN_SIZE;
+
+ if (size > HASH_MAP_MAX_SIZE) {
+ LOG_ERROR("HashMap create failed: size is too large.\n");
+ return NULL;
+ }
+
+ if (!hash_func || !key_equal_func) {
+ LOG_ERROR("HashMap create failed: hash function or key equal function "
+ " is NULL.\n");
+ return NULL;
+ }
+
+ total_size = offsetof(HashMap, elements)
+ + sizeof(HashMapElem *) * (uint64)size
+ + (use_lock ? sizeof(korp_mutex) : 0);
+
+ if (total_size >= UINT32_MAX || !(map = BH_MALLOC((uint32)total_size))) {
+ LOG_ERROR("HashMap create failed: alloc memory failed.\n");
+ return NULL;
+ }
+
+ memset(map, 0, (uint32)total_size);
+
+ if (use_lock) {
+ map->lock = (korp_mutex *)((uint8 *)map + offsetof(HashMap, elements)
+ + sizeof(HashMapElem *) * size);
+ if (os_mutex_init(map->lock)) {
+ LOG_ERROR("HashMap create failed: init map lock failed.\n");
+ BH_FREE(map);
+ return NULL;
+ }
+ }
+
+ map->size = size;
+ map->hash_func = hash_func;
+ map->key_equal_func = key_equal_func;
+ map->key_destroy_func = key_destroy_func;
+ map->value_destroy_func = value_destroy_func;
+ return map;
+}
+
+bool
+bh_hash_map_insert(HashMap *map, void *key, void *value)
+{
+ uint32 index;
+ HashMapElem *elem;
+
+ if (!map || !key) {
+ LOG_ERROR("HashMap insert elem failed: map or key is NULL.\n");
+ return false;
+ }
+
+ if (map->lock) {
+ os_mutex_lock(map->lock);
+ }
+
+ index = map->hash_func(key) % map->size;
+ elem = map->elements[index];
+ while (elem) {
+ if (map->key_equal_func(elem->key, key)) {
+ LOG_ERROR("HashMap insert elem failed: duplicated key found.\n");
+ goto fail;
+ }
+ elem = elem->next;
+ }
+
+ if (!(elem = BH_MALLOC(sizeof(HashMapElem)))) {
+ LOG_ERROR("HashMap insert elem failed: alloc memory failed.\n");
+ goto fail;
+ }
+
+ elem->key = key;
+ elem->value = value;
+ elem->next = map->elements[index];
+ map->elements[index] = elem;
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return true;
+
+fail:
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return false;
+}
+
+void *
+bh_hash_map_find(HashMap *map, void *key)
+{
+ uint32 index;
+ HashMapElem *elem;
+ void *value;
+
+ if (!map || !key) {
+ LOG_ERROR("HashMap find elem failed: map or key is NULL.\n");
+ return NULL;
+ }
+
+ if (map->lock) {
+ os_mutex_lock(map->lock);
+ }
+
+ index = map->hash_func(key) % map->size;
+ elem = map->elements[index];
+
+ while (elem) {
+ if (map->key_equal_func(elem->key, key)) {
+ value = elem->value;
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return value;
+ }
+ elem = elem->next;
+ }
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return NULL;
+}
+
+bool
+bh_hash_map_update(HashMap *map, void *key, void *value, void **p_old_value)
+{
+ uint32 index;
+ HashMapElem *elem;
+
+ if (!map || !key) {
+ LOG_ERROR("HashMap update elem failed: map or key is NULL.\n");
+ return false;
+ }
+
+ if (map->lock) {
+ os_mutex_lock(map->lock);
+ }
+
+ index = map->hash_func(key) % map->size;
+ elem = map->elements[index];
+
+ while (elem) {
+ if (map->key_equal_func(elem->key, key)) {
+ if (p_old_value)
+ *p_old_value = elem->value;
+ elem->value = value;
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return true;
+ }
+ elem = elem->next;
+ }
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return false;
+}
+
+bool
+bh_hash_map_remove(HashMap *map, void *key, void **p_old_key,
+ void **p_old_value)
+{
+ uint32 index;
+ HashMapElem *elem, *prev;
+
+ if (!map || !key) {
+ LOG_ERROR("HashMap remove elem failed: map or key is NULL.\n");
+ return false;
+ }
+
+ if (map->lock) {
+ os_mutex_lock(map->lock);
+ }
+
+ index = map->hash_func(key) % map->size;
+ prev = elem = map->elements[index];
+
+ while (elem) {
+ if (map->key_equal_func(elem->key, key)) {
+ if (p_old_key)
+ *p_old_key = elem->key;
+ if (p_old_value)
+ *p_old_value = elem->value;
+
+ if (elem == map->elements[index])
+ map->elements[index] = elem->next;
+ else
+ prev->next = elem->next;
+
+ BH_FREE(elem);
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return true;
+ }
+
+ prev = elem;
+ elem = elem->next;
+ }
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+ return false;
+}
+
+bool
+bh_hash_map_destroy(HashMap *map)
+{
+ uint32 index;
+ HashMapElem *elem, *next;
+
+ if (!map) {
+ LOG_ERROR("HashMap destroy failed: map is NULL.\n");
+ return false;
+ }
+
+ if (map->lock) {
+ os_mutex_lock(map->lock);
+ }
+
+ for (index = 0; index < map->size; index++) {
+ elem = map->elements[index];
+ while (elem) {
+ next = elem->next;
+
+ if (map->key_destroy_func) {
+ map->key_destroy_func(elem->key);
+ }
+ if (map->value_destroy_func) {
+ map->value_destroy_func(elem->value);
+ }
+ BH_FREE(elem);
+
+ elem = next;
+ }
+ }
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ os_mutex_destroy(map->lock);
+ }
+ BH_FREE(map);
+ return true;
+}
+
+uint32
+bh_hash_map_get_struct_size(HashMap *hashmap)
+{
+ uint32 size = (uint32)(uintptr_t)offsetof(HashMap, elements)
+ + (uint32)sizeof(HashMapElem *) * hashmap->size;
+
+ if (hashmap->lock) {
+ size += (uint32)sizeof(korp_mutex);
+ }
+
+ return size;
+}
+
+uint32
+bh_hash_map_get_elem_struct_size()
+{
+ return (uint32)sizeof(HashMapElem);
+}
+
+bool
+bh_hash_map_traverse(HashMap *map, TraverseCallbackFunc callback,
+ void *user_data)
+{
+ uint32 index;
+ HashMapElem *elem, *next;
+
+ if (!map || !callback) {
+ LOG_ERROR("HashMap traverse failed: map or callback is NULL.\n");
+ return false;
+ }
+
+ if (map->lock) {
+ os_mutex_lock(map->lock);
+ }
+
+ for (index = 0; index < map->size; index++) {
+ elem = map->elements[index];
+ while (elem) {
+ next = elem->next;
+ callback(elem->key, elem->value, user_data);
+ elem = next;
+ }
+ }
+
+ if (map->lock) {
+ os_mutex_unlock(map->lock);
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.h
new file mode 100644
index 000000000..38aa2c668
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_hashmap.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASM_HASHMAP_H
+#define WASM_HASHMAP_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Minimum initial size of hash map */
+#define HASH_MAP_MIN_SIZE 4
+
+/* Maximum initial size of hash map */
+#define HASH_MAP_MAX_SIZE 65536
+
+struct HashMap;
+typedef struct HashMap HashMap;
+
+/* Hash function: to get the hash value of key. */
+typedef uint32 (*HashFunc)(const void *key);
+
+/* Key equal function: to check whether two keys are equal. */
+typedef bool (*KeyEqualFunc)(void *key1, void *key2);
+
+/* Key destroy function: to destroy the key, auto called
+ for each key when the hash map is destroyed. */
+typedef void (*KeyDestroyFunc)(void *key);
+
+/* Value destroy function: to destroy the value, auto called
+ for each value when the hash map is destroyed. */
+typedef void (*ValueDestroyFunc)(void *value);
+
+/* traverse callback function:
+ auto called when traverse every hash element */
+typedef void (*TraverseCallbackFunc)(void *key, void *value, void *user_data);
+
+/**
+ * Create a hash map.
+ *
+ * @param size: the initial size of the hash map
+ * @param use_lock whether to lock the hash map when operating on it
+ * @param hash_func hash function of the key, must be specified
+ * @param key_equal_func key equal function, check whether two keys
+ * are equal, must be specified
+ * @param key_destroy_func key destroy function, called for each key if not NULL
+ * when the hash map is destroyed
+ * @param value_destroy_func value destroy function, called for each value if
+ * not NULL when the hash map is destroyed
+ *
+ * @return the hash map created, NULL if failed
+ */
+HashMap *
+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
+ *
+ * @param map the hash map to insert element
+ * @key the key of the element
+ * @value the value of the element
+ *
+ * @return true if success, false otherwise
+ * Note: fail if key is NULL or duplicated key exists in the hash map,
+ */
+bool
+bh_hash_map_insert(HashMap *map, void *key, void *value);
+
+/**
+ * Find an element in the hash map
+ *
+ * @param map the hash map to find element
+ * @key the key of the element
+ *
+ * @return the value of the found element if success, NULL otherwise
+ */
+void *
+bh_hash_map_find(HashMap *map, void *key);
+
+/**
+ * Update an element in the hash map with new value
+ *
+ * @param map the hash map to update element
+ * @key the key of the element
+ * @value the new value of the element
+ * @p_old_value if not NULL, copies the old value to it
+ *
+ * @return true if success, false otherwise
+ * Note: the old value won't be destroyed by value destroy function,
+ * it will be copied to p_old_value for user to process.
+ */
+bool
+bh_hash_map_update(HashMap *map, void *key, void *value, void **p_old_value);
+
+/**
+ * Remove an element from the hash map
+ *
+ * @param map the hash map to remove element
+ * @key the key of the element
+ * @p_old_key if not NULL, copies the old key to it
+ * @p_old_value if not NULL, copies the old value to it
+ *
+ * @return true if success, false otherwise
+ * Note: the old key and old value won't be destroyed by key destroy
+ * function and value destroy function, they will be copied to
+ * p_old_key and p_old_value for user to process.
+ */
+bool
+bh_hash_map_remove(HashMap *map, void *key, void **p_old_key,
+ void **p_old_value);
+
+/**
+ * Destroy the hashmap
+ *
+ * @param map the hash map to destroy
+ *
+ * @return true if success, false otherwise
+ * Note: the key destroy function and value destroy function will be
+ * called to destroy each element's key and value if they are
+ * not NULL.
+ */
+bool
+bh_hash_map_destroy(HashMap *map);
+
+/**
+ * Get the structure size of HashMap
+ *
+ * @param map the hash map to calculate
+ *
+ * @return the memory space occupied by HashMap structure
+ */
+uint32
+bh_hash_map_get_struct_size(HashMap *hashmap);
+
+/**
+ * Get the structure size of HashMap Element
+ *
+ * @return the memory space occupied by HashMapElem structure
+ */
+uint32
+bh_hash_map_get_elem_struct_size(void);
+
+/**
+ * Traverse the hash map and call the callback function
+ *
+ * @param map the hash map to traverse
+ * @param callback the function to be called for every element
+ * @param user_data the argument to be passed to the callback function
+ *
+ * @return true if success, false otherwise
+ * Note: if the hash map has lock, the map will be locked during traverse,
+ * keep the callback function as simple as possible.
+ */
+bool
+bh_hash_map_traverse(HashMap *map, TraverseCallbackFunc callback,
+ void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* endof WASM_HASHMAP_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.c
new file mode 100644
index 000000000..7102d42a1
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_list.h"
+
+#if BH_DEBUG != 0
+/**
+ * Test whehter a pointer value has exist in given list.
+ *
+ * @param list pointer to list.
+ * @param elem pointer to elem that will be inserted into list.
+ * @return <code>true</code> if the pointer has been in the list;
+ * <code>false</code> otherwise.
+ */
+static bool
+bh_list_is_elem_exist(bh_list *list, void *elem);
+#endif
+
+bh_list_status
+bh_list_init(bh_list *list)
+{
+ if (!list)
+ return BH_LIST_ERROR;
+
+ (list->head).next = NULL;
+ list->len = 0;
+ return BH_LIST_SUCCESS;
+}
+
+bh_list_status
+bh_list_insert(bh_list *list, void *elem)
+{
+ bh_list_link *p = NULL;
+
+ if (!list || !elem)
+ return BH_LIST_ERROR;
+#if BH_DEBUG != 0
+ bh_assert(!bh_list_is_elem_exist(list, elem));
+#endif
+ p = (bh_list_link *)elem;
+ p->next = (list->head).next;
+ (list->head).next = p;
+ list->len++;
+ return BH_LIST_SUCCESS;
+}
+
+bh_list_status
+bh_list_remove(bh_list *list, void *elem)
+{
+ bh_list_link *cur = NULL;
+ bh_list_link *prev = NULL;
+
+ if (!list || !elem)
+ return BH_LIST_ERROR;
+
+ cur = (list->head).next;
+
+ while (cur) {
+ if (cur == elem) {
+ if (prev)
+ prev->next = cur->next;
+ else
+ (list->head).next = cur->next;
+
+ list->len--;
+ return BH_LIST_SUCCESS;
+ }
+
+ prev = cur;
+ cur = cur->next;
+ }
+
+ return BH_LIST_ERROR;
+}
+
+uint32
+bh_list_length(bh_list *list)
+{
+ return (list ? list->len : 0);
+}
+
+void *
+bh_list_first_elem(bh_list *list)
+{
+ return (list ? (list->head).next : NULL);
+}
+
+void *
+bh_list_elem_next(void *node)
+{
+ return (node ? ((bh_list_link *)node)->next : NULL);
+}
+
+#if BH_DEBUG != 0
+static bool
+bh_list_is_elem_exist(bh_list *list, void *elem)
+{
+ bh_list_link *p = NULL;
+
+ if (!list || !elem)
+ return false;
+
+ p = (list->head).next;
+ while (p && p != elem)
+ p = p->next;
+
+ return (p != NULL);
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.h
new file mode 100644
index 000000000..f10215324
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_list.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _BH_LIST_H
+#define _BH_LIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bh_platform.h"
+
+/* List user should embedded bh_list_link into list elem data structure
+ * definition. And bh_list_link data field should be the first field.
+ * For example, if we would like to use bh_list for our own data type A,
+ * A must be defined as a structure like below:
+ * struct A {
+ * bh_list_link l;
+ * ...
+ * };
+ *
+ * bh_list_link is defined as a structure (not typedef void*).
+ * It will make extend list into bi-direction easy.
+ */
+typedef struct bh_list_link {
+ struct bh_list_link *next;
+} bh_list_link;
+
+typedef struct bh_list {
+ bh_list_link head;
+ uint32 len;
+} bh_list;
+
+/* list operation return value */
+typedef enum bh_list_status {
+ BH_LIST_SUCCESS = 0,
+ BH_LIST_ERROR = -1
+} bh_list_status;
+
+/**
+ * Initialize a list.
+ *
+ * @param list pointer to list.
+ * @return <code>BH_LIST_ERROR</code> if OK;
+ * <code>BH_LIST_ERROR</code> if list pointer is NULL.
+ */
+bh_list_status
+bh_list_init(bh_list *list);
+
+/**
+ * Insert an elem pointer into list. The list node memory is maintained by list
+ * while elem memory is the responsibility of list user.
+ *
+ * @param list pointer to list.
+ * @param elem pointer to elem that will be inserted into list.
+ * @return <code>BH_LIST_ERROR</code> if OK;
+ * <code>BH_LIST_ERROR</code> if input is invalid or no memory
+ * available.
+ */
+bh_list_status
+bh_list_insert(bh_list *list, void *elem);
+
+/**
+ * Remove an elem pointer from list. The list node memory is maintained by list
+ * while elem memory is the responsibility of list user.
+ *
+ * @param list pointer to list.
+ * @param elem pointer to elem that will be inserted into list.
+ * @return <code>BH_LIST_ERROR</code> if OK;
+ * <code>BH_LIST_ERROR</code> if element does not exist in given
+ * list.
+ */
+bh_list_status
+bh_list_remove(bh_list *list, void *elem);
+
+/**
+ * Get the list length.
+ *
+ * @param list pointer to list.
+ * @return the length of the list.
+ */
+uint32
+bh_list_length(bh_list *list);
+
+/**
+ * Get the first elem in the list.
+ *
+ * @param list pointer to list.
+ * @return pointer to the first node.
+ */
+void *
+bh_list_first_elem(bh_list *list);
+
+/**
+ * Get the next elem of given list input elem.
+ *
+ * @param node pointer to list node.
+ * @return pointer to next list node.
+ */
+void *
+bh_list_elem_next(void *node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef _BH_LIST_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.c
new file mode 100644
index 000000000..78c058065
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.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 uint32 log_verbose_level = BH_LOG_LEVEL_WARNING;
+
+void
+bh_log_set_verbose_level(uint32 level)
+{
+ log_verbose_level = level;
+}
+
+void
+bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...)
+{
+ va_list ap;
+ korp_tid self;
+ char buf[32] = { 0 };
+ uint64 usec;
+ uint32 t, h, m, s, mills;
+
+ if ((uint32)log_level > log_verbose_level)
+ return;
+
+ self = os_self_thread();
+
+ usec = os_time_get_boot_microsecond();
+ t = (uint32)(usec / 1000000) % (24 * 60 * 60);
+ h = t / (60 * 60);
+ t = t % (60 * 60);
+ m = t / 60;
+ s = t % 60;
+ mills = (uint32)(usec % 1000);
+
+ snprintf(buf, sizeof(buf),
+ "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ":%03" PRIu32, h, m, s,
+ mills);
+
+ os_printf("[%s - %" PRIXPTR "]: ", buf, (uintptr_t)self);
+
+ if (file)
+ os_printf("%s, line %d, ", file, line);
+
+ va_start(ap, fmt);
+ os_vprintf(fmt, ap);
+ va_end(ap);
+
+ os_printf("\n");
+}
+
+static uint32 last_time_ms = 0;
+static uint32 total_time_ms = 0;
+
+void
+bh_print_time(const char *prompt)
+{
+ uint32 curr_time_ms;
+
+ if (log_verbose_level < 3)
+ return;
+
+ curr_time_ms = (uint32)bh_get_tick_ms();
+
+ if (last_time_ms == 0)
+ last_time_ms = curr_time_ms;
+
+ total_time_ms += curr_time_ms - last_time_ms;
+
+ os_printf("%-48s time of last stage: %" PRIu32 " ms, total time: %" PRIu32
+ " ms\n",
+ prompt, curr_time_ms - last_time_ms, total_time_ms);
+
+ last_time_ms = curr_time_ms;
+}
+
+void
+bh_print_proc_mem(const char *prompt)
+{
+ char buf[1024] = { 0 };
+
+ if (log_verbose_level < BH_LOG_LEVEL_DEBUG)
+ return;
+
+ if (os_dumps_proc_mem_info(buf, sizeof(buf)) != 0)
+ return;
+
+ os_printf("%s\n", prompt);
+ os_printf("===== memory usage =====\n");
+ os_printf("%s", buf);
+ os_printf("==========\n");
+ return;
+}
+
+void
+bh_log_proc_mem(const char *function, uint32 line)
+{
+ char prompt[128] = { 0 };
+ snprintf(prompt, sizeof(prompt), "[MEM] %s(...) L%" PRIu32, function, line);
+ bh_print_proc_mem(prompt);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.h
new file mode 100644
index 000000000..e0bc61da2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_log.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+/**
+ * @file bh_log.h
+ * @date Tue Nov 8 18:19:10 2011
+ *
+ * @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 _BH_LOG_H
+#define _BH_LOG_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ BH_LOG_LEVEL_FATAL = 0,
+ BH_LOG_LEVEL_ERROR = 1,
+ BH_LOG_LEVEL_WARNING = 2,
+ BH_LOG_LEVEL_DEBUG = 3,
+ BH_LOG_LEVEL_VERBOSE = 4
+} LogLevel;
+
+void
+bh_log_set_verbose_level(uint32 level);
+
+void
+bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...);
+
+#ifdef BH_PLATFORM_NUTTX
+
+#undef LOG_FATAL
+#undef LOG_ERROR
+#undef LOG_WARNING
+#undef LOG_VERBOSE
+#undef LOG_DEBUG
+
+#endif
+
+#if BH_DEBUG != 0
+#define LOG_FATAL(...) \
+ bh_log(BH_LOG_LEVEL_FATAL, __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define LOG_FATAL(...) \
+ bh_log(BH_LOG_LEVEL_FATAL, __FUNCTION__, __LINE__, __VA_ARGS__)
+#endif
+
+#define LOG_ERROR(...) bh_log(BH_LOG_LEVEL_ERROR, NULL, 0, __VA_ARGS__)
+#define LOG_WARNING(...) bh_log(BH_LOG_LEVEL_WARNING, NULL, 0, __VA_ARGS__)
+#define LOG_VERBOSE(...) bh_log(BH_LOG_LEVEL_VERBOSE, NULL, 0, __VA_ARGS__)
+
+#if BH_DEBUG != 0
+#define LOG_DEBUG(...) \
+ bh_log(BH_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define LOG_DEBUG(...) (void)0
+#endif
+
+void
+bh_print_time(const char *prompt);
+
+void
+bh_print_proc_mem(const char *prompt);
+
+void
+bh_log_proc_mem(const char *function, uint32 line);
+
+#define LOG_PROC_MEM(...) bh_log_proc_mem(__FUNCTION__, __LINE__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BH_LOG_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_platform.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_platform.h
new file mode 100644
index 000000000..86aef839d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_platform.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _BH_PLATFORM_H
+#define _BH_PLATFORM_H
+
+#include "../platform/include/platform_common.h"
+#include "../platform/include/platform_api_vmcore.h"
+#include "../platform/include/platform_api_extension.h"
+#include "bh_assert.h"
+#include "bh_common.h"
+#include "bh_hashmap.h"
+#include "bh_list.h"
+#include "bh_log.h"
+#include "bh_queue.h"
+#include "bh_vector.h"
+#include "runtime_timer.h"
+
+/**
+ * WA_MALLOC/WA_FREE need to be redefined for both
+ * runtime native and WASM app respectively.
+ *
+ * Some source files are shared for building native and WASM,
+ * and this the mem allocator API for these files.
+ *
+ * Here we define it for the native world
+ */
+#ifndef WA_MALLOC
+#define WA_MALLOC wasm_runtime_malloc
+#endif
+
+#ifndef WA_FREE
+#define WA_FREE wasm_runtime_free
+#endif
+
+#endif /* #ifndef _BH_PLATFORM_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.c
new file mode 100644
index 000000000..7c860d11a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_queue.h"
+
+typedef struct bh_queue_node {
+ struct bh_queue_node *next;
+ struct bh_queue_node *prev;
+ unsigned short tag;
+ unsigned int len;
+ void *body;
+ bh_msg_cleaner msg_cleaner;
+} bh_queue_node;
+
+struct bh_queue {
+ bh_queue_mutex queue_lock;
+ bh_queue_cond queue_wait_cond;
+ unsigned int cnt;
+ unsigned int max;
+ unsigned int drops;
+ bh_queue_node *head;
+ bh_queue_node *tail;
+
+ bool exit_loop_run;
+};
+
+char *
+bh_message_payload(bh_message_t message)
+{
+ return message->body;
+}
+
+uint32
+bh_message_payload_len(bh_message_t message)
+{
+ return message->len;
+}
+
+int
+bh_message_type(bh_message_t message)
+{
+ return message->tag;
+}
+
+bh_queue *
+bh_queue_create()
+{
+ int ret;
+ bh_queue *queue = bh_queue_malloc(sizeof(bh_queue));
+
+ if (queue) {
+ memset(queue, 0, sizeof(bh_queue));
+ queue->max = DEFAULT_QUEUE_LENGTH;
+
+ ret = bh_queue_mutex_init(&queue->queue_lock);
+ if (ret != 0) {
+ bh_queue_free(queue);
+ return NULL;
+ }
+
+ ret = bh_queue_cond_init(&queue->queue_wait_cond);
+ if (ret != 0) {
+ bh_queue_mutex_destroy(&queue->queue_lock);
+ bh_queue_free(queue);
+ return NULL;
+ }
+ }
+
+ return queue;
+}
+
+void
+bh_queue_destroy(bh_queue *queue)
+{
+ bh_queue_node *node;
+
+ if (!queue)
+ return;
+
+ bh_queue_mutex_lock(&queue->queue_lock);
+ while (queue->head) {
+ node = queue->head;
+ queue->head = node->next;
+
+ bh_free_msg(node);
+ }
+ bh_queue_mutex_unlock(&queue->queue_lock);
+
+ bh_queue_cond_destroy(&queue->queue_wait_cond);
+ bh_queue_mutex_destroy(&queue->queue_lock);
+ bh_queue_free(queue);
+}
+
+bool
+bh_post_msg2(bh_queue *queue, bh_queue_node *msg)
+{
+ if (queue->cnt >= queue->max) {
+ queue->drops++;
+ bh_free_msg(msg);
+ return false;
+ }
+
+ bh_queue_mutex_lock(&queue->queue_lock);
+
+ if (queue->cnt == 0) {
+ bh_assert(queue->head == NULL);
+ bh_assert(queue->tail == NULL);
+ queue->head = queue->tail = msg;
+ msg->next = msg->prev = NULL;
+ queue->cnt = 1;
+
+ bh_queue_cond_signal(&queue->queue_wait_cond);
+ }
+ else {
+ msg->next = NULL;
+ msg->prev = queue->tail;
+ queue->tail->next = msg;
+ queue->tail = msg;
+ queue->cnt++;
+ }
+
+ bh_queue_mutex_unlock(&queue->queue_lock);
+
+ return true;
+}
+
+bool
+bh_post_msg(bh_queue *queue, unsigned short tag, void *body, unsigned int len)
+{
+ bh_queue_node *msg = bh_new_msg(tag, body, len, NULL);
+ if (msg == NULL) {
+ queue->drops++;
+ if (len != 0 && body)
+ BH_FREE(body);
+ return false;
+ }
+
+ if (!bh_post_msg2(queue, msg)) {
+ // bh_post_msg2 already freed the msg for failure
+ return false;
+ }
+
+ return true;
+}
+
+bh_queue_node *
+bh_new_msg(unsigned short tag, void *body, unsigned int len, void *handler)
+{
+ bh_queue_node *msg =
+ (bh_queue_node *)bh_queue_malloc(sizeof(bh_queue_node));
+ if (msg == NULL)
+ return NULL;
+ memset(msg, 0, sizeof(bh_queue_node));
+ msg->len = len;
+ msg->body = body;
+ msg->tag = tag;
+ msg->msg_cleaner = (bh_msg_cleaner)handler;
+
+ return msg;
+}
+
+void
+bh_free_msg(bh_queue_node *msg)
+{
+ if (msg->msg_cleaner) {
+ msg->msg_cleaner(msg->body);
+ bh_queue_free(msg);
+ return;
+ }
+
+ // note: sometime we just use the payload pointer for a integer value
+ // len!=0 is the only indicator about the body is an allocated buffer.
+ if (msg->body && msg->len)
+ bh_queue_free(msg->body);
+
+ bh_queue_free(msg);
+}
+
+bh_message_t
+bh_get_msg(bh_queue *queue, uint64 timeout_us)
+{
+ bh_queue_node *msg = NULL;
+ bh_queue_mutex_lock(&queue->queue_lock);
+
+ if (queue->cnt == 0) {
+ bh_assert(queue->head == NULL);
+ bh_assert(queue->tail == NULL);
+
+ if (timeout_us == 0) {
+ bh_queue_mutex_unlock(&queue->queue_lock);
+ return NULL;
+ }
+
+ bh_queue_cond_timedwait(&queue->queue_wait_cond, &queue->queue_lock,
+ timeout_us);
+ }
+
+ if (queue->cnt == 0) {
+ bh_assert(queue->head == NULL);
+ bh_assert(queue->tail == NULL);
+ }
+ else if (queue->cnt == 1) {
+ bh_assert(queue->head == queue->tail);
+
+ msg = queue->head;
+ queue->head = queue->tail = NULL;
+ queue->cnt = 0;
+ }
+ else {
+ msg = queue->head;
+ queue->head = queue->head->next;
+ queue->head->prev = NULL;
+ queue->cnt--;
+ }
+
+ bh_queue_mutex_unlock(&queue->queue_lock);
+
+ return msg;
+}
+
+unsigned
+bh_queue_get_message_count(bh_queue *queue)
+{
+ if (!queue)
+ return 0;
+
+ return queue->cnt;
+}
+
+void
+bh_queue_enter_loop_run(bh_queue *queue, bh_queue_handle_msg_callback handle_cb,
+ void *arg)
+{
+ if (!queue)
+ return;
+
+ while (!queue->exit_loop_run) {
+ bh_queue_node *message = bh_get_msg(queue, BHT_WAIT_FOREVER);
+
+ if (message) {
+ handle_cb(message, arg);
+ bh_free_msg(message);
+ }
+ }
+}
+
+void
+bh_queue_exit_loop_run(bh_queue *queue)
+{
+ if (queue) {
+ queue->exit_loop_run = true;
+ bh_queue_cond_signal(&queue->queue_wait_cond);
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.h
new file mode 100644
index 000000000..c15f43526
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_queue.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _BH_QUEUE_H
+#define _BH_QUEUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bh_platform.h"
+
+struct bh_queue_node;
+typedef struct bh_queue_node *bh_message_t;
+struct bh_queue;
+typedef struct bh_queue bh_queue;
+
+typedef void (*bh_queue_handle_msg_callback)(void *message, void *arg);
+
+#define bh_queue_malloc BH_MALLOC
+#define bh_queue_free BH_FREE
+
+#define bh_queue_mutex korp_mutex
+#define bh_queue_cond korp_cond
+
+#define bh_queue_mutex_init os_mutex_init
+#define bh_queue_mutex_destroy os_mutex_destroy
+#define bh_queue_mutex_lock os_mutex_lock
+#define bh_queue_mutex_unlock os_mutex_unlock
+
+#define bh_queue_cond_init os_cond_init
+#define bh_queue_cond_destroy os_cond_destroy
+#define bh_queue_cond_wait os_cond_wait
+#define bh_queue_cond_timedwait os_cond_reltimedwait
+#define bh_queue_cond_signal os_cond_signal
+#define bh_queue_cond_broadcast os_cond_broadcast
+
+typedef void (*bh_msg_cleaner)(void *msg);
+
+bh_queue *
+bh_queue_create(void);
+
+void
+bh_queue_destroy(bh_queue *queue);
+
+char *
+bh_message_payload(bh_message_t message);
+uint32
+bh_message_payload_len(bh_message_t message);
+int
+bh_message_type(bh_message_t message);
+
+bh_message_t
+bh_new_msg(unsigned short tag, void *body, unsigned int len, void *handler);
+void
+bh_free_msg(bh_message_t msg);
+bool
+bh_post_msg(bh_queue *queue, unsigned short tag, void *body, unsigned int len);
+bool
+bh_post_msg2(bh_queue *queue, bh_message_t msg);
+
+bh_message_t
+bh_get_msg(bh_queue *queue, uint64 timeout_us);
+
+unsigned
+bh_queue_get_message_count(bh_queue *queue);
+
+void
+bh_queue_enter_loop_run(bh_queue *queue, bh_queue_handle_msg_callback handle_cb,
+ void *arg);
+void
+bh_queue_exit_loop_run(bh_queue *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef _BH_QUEUE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.c
new file mode 100644
index 000000000..352ce7192
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_vector.h"
+
+static uint8 *
+alloc_vector_data(size_t length, size_t size_elem)
+{
+ uint64 total_size = ((uint64)size_elem) * length;
+ uint8 *data;
+
+ if (length > UINT32_MAX || size_elem > UINT32_MAX
+ || total_size > UINT32_MAX) {
+ return NULL;
+ }
+
+ if ((data = BH_MALLOC((uint32)total_size))) {
+ memset(data, 0, (uint32)total_size);
+ }
+
+ return data;
+}
+
+/**
+ * every caller of `extend_vector` must provide
+ * a thread-safe environment.
+ */
+static bool
+extend_vector(Vector *vector, size_t length)
+{
+ uint8 *data;
+
+ if (length <= vector->max_elems)
+ return true;
+
+ if (length < vector->size_elem * 3 / 2)
+ length = vector->size_elem * 3 / 2;
+
+ if (!(data = alloc_vector_data(length, vector->size_elem))) {
+ return false;
+ }
+
+ bh_memcpy_s(data, (uint32)(vector->size_elem * length), vector->data,
+ (uint32)(vector->size_elem * vector->max_elems));
+ BH_FREE(vector->data);
+
+ vector->data = data;
+ vector->max_elems = length;
+ return true;
+}
+
+bool
+bh_vector_init(Vector *vector, size_t init_length, size_t size_elem,
+ bool use_lock)
+{
+ if (!vector) {
+ LOG_ERROR("Init vector failed: vector is NULL.\n");
+ return false;
+ }
+
+ if (init_length == 0) {
+ init_length = 4;
+ }
+
+ if (!(vector->data = alloc_vector_data(init_length, size_elem))) {
+ LOG_ERROR("Init vector failed: alloc memory failed.\n");
+ return false;
+ }
+
+ vector->size_elem = size_elem;
+ vector->max_elems = init_length;
+ vector->num_elems = 0;
+ vector->lock = NULL;
+
+ if (use_lock) {
+ if (!(vector->lock = BH_MALLOC(sizeof(korp_mutex)))) {
+ LOG_ERROR("Init vector failed: alloc locker failed.\n");
+ bh_vector_destroy(vector);
+ return false;
+ }
+
+ if (BHT_OK != os_mutex_init(vector->lock)) {
+ LOG_ERROR("Init vector failed: init locker failed.\n");
+
+ BH_FREE(vector->lock);
+ vector->lock = NULL;
+
+ bh_vector_destroy(vector);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+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");
+ return false;
+ }
+
+ if (index >= vector->num_elems) {
+ LOG_ERROR("Set vector elem failed: invalid elem index.\n");
+ return false;
+ }
+
+ if (vector->lock)
+ os_mutex_lock(vector->lock);
+ bh_memcpy_s(vector->data + vector->size_elem * index,
+ (uint32)vector->size_elem, elem_buf, (uint32)vector->size_elem);
+ if (vector->lock)
+ os_mutex_unlock(vector->lock);
+ return true;
+}
+
+bool
+bh_vector_get(Vector *vector, uint32 index, void *elem_buf)
+{
+ if (!vector || !elem_buf) {
+ LOG_ERROR("Get vector elem failed: vector or elem buf is NULL.\n");
+ return false;
+ }
+
+ if (index >= vector->num_elems) {
+ LOG_ERROR("Get vector elem failed: invalid elem index.\n");
+ return false;
+ }
+
+ if (vector->lock)
+ os_mutex_lock(vector->lock);
+ bh_memcpy_s(elem_buf, (uint32)vector->size_elem,
+ vector->data + vector->size_elem * index,
+ (uint32)vector->size_elem);
+ if (vector->lock)
+ os_mutex_unlock(vector->lock);
+ return true;
+}
+
+bool
+bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf)
+{
+ size_t i;
+ uint8 *p;
+ bool ret = false;
+
+ if (!vector || !elem_buf) {
+ LOG_ERROR("Insert vector elem failed: vector or elem buf is NULL.\n");
+ goto just_return;
+ }
+
+ if (index >= vector->num_elems) {
+ LOG_ERROR("Insert vector elem failed: invalid elem index.\n");
+ goto just_return;
+ }
+
+ if (vector->lock)
+ os_mutex_lock(vector->lock);
+
+ if (!extend_vector(vector, vector->num_elems + 1)) {
+ LOG_ERROR("Insert vector elem failed: extend vector failed.\n");
+ goto unlock_return;
+ }
+
+ p = vector->data + vector->size_elem * vector->num_elems;
+ for (i = vector->num_elems - 1; i > index; i--) {
+ bh_memcpy_s(p, (uint32)vector->size_elem, p - vector->size_elem,
+ (uint32)vector->size_elem);
+ p -= vector->size_elem;
+ }
+
+ bh_memcpy_s(p, (uint32)vector->size_elem, elem_buf,
+ (uint32)vector->size_elem);
+ vector->num_elems++;
+ ret = true;
+
+unlock_return:
+ if (vector->lock)
+ os_mutex_unlock(vector->lock);
+just_return:
+ return ret;
+}
+
+bool
+bh_vector_append(Vector *vector, const void *elem_buf)
+{
+ bool ret = false;
+
+ if (!vector || !elem_buf) {
+ LOG_ERROR("Append vector elem failed: vector or elem buf is NULL.\n");
+ goto just_return;
+ }
+
+ /* make sure one more slot is used by the thread who allocas it */
+ if (vector->lock)
+ os_mutex_lock(vector->lock);
+
+ if (!extend_vector(vector, vector->num_elems + 1)) {
+ LOG_ERROR("Append ector elem failed: extend vector failed.\n");
+ goto unlock_return;
+ }
+
+ bh_memcpy_s(vector->data + vector->size_elem * vector->num_elems,
+ (uint32)vector->size_elem, elem_buf, (uint32)vector->size_elem);
+ vector->num_elems++;
+ ret = true;
+
+unlock_return:
+ if (vector->lock)
+ os_mutex_unlock(vector->lock);
+just_return:
+ return ret;
+}
+
+bool
+bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
+{
+ uint32 i;
+ uint8 *p;
+
+ if (!vector) {
+ LOG_ERROR("Remove vector elem failed: vector is NULL.\n");
+ return false;
+ }
+
+ if (index >= vector->num_elems) {
+ LOG_ERROR("Remove vector elem failed: invalid elem index.\n");
+ return false;
+ }
+
+ if (vector->lock)
+ os_mutex_lock(vector->lock);
+ p = vector->data + vector->size_elem * index;
+
+ if (old_elem_buf) {
+ bh_memcpy_s(old_elem_buf, (uint32)vector->size_elem, p,
+ (uint32)vector->size_elem);
+ }
+
+ for (i = index; i < vector->num_elems - 1; i++) {
+ bh_memcpy_s(p, (uint32)vector->size_elem, p + vector->size_elem,
+ (uint32)vector->size_elem);
+ p += vector->size_elem;
+ }
+
+ vector->num_elems--;
+ if (vector->lock)
+ os_mutex_unlock(vector->lock);
+ return true;
+}
+
+size_t
+bh_vector_size(const Vector *vector)
+{
+ return vector ? vector->num_elems : 0;
+}
+
+bool
+bh_vector_destroy(Vector *vector)
+{
+ if (!vector) {
+ LOG_ERROR("Destroy vector elem failed: vector is NULL.\n");
+ return false;
+ }
+
+ if (vector->data)
+ BH_FREE(vector->data);
+
+ if (vector->lock) {
+ os_mutex_destroy(vector->lock);
+ BH_FREE(vector->lock);
+ }
+
+ memset(vector, 0, sizeof(Vector));
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.h
new file mode 100644
index 000000000..d0aaaf19b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/bh_vector.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_VECTOR_H
+#define _WASM_VECTOR_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEFAULT_VECTOR_INIT_SIZE 8
+
+typedef struct Vector {
+ /* max element number */
+ size_t max_elems;
+ /* vector data allocated */
+ uint8 *data;
+ /* current element num */
+ size_t num_elems;
+ /* size of each element */
+ size_t size_elem;
+ void *lock;
+} Vector;
+
+/**
+ * Initialize vector
+ *
+ * @param vector the vector to init
+ * @param init_length the initial length of the vector
+ * @param size_elem size of each element
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_init(Vector *vector, size_t init_length, size_t size_elem,
+ bool use_lock);
+
+/**
+ * Set element of vector
+ *
+ * @param vector the vector to set
+ * @param index the index of the element to set
+ * @param elem_buf the element buffer which stores the element data
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_set(Vector *vector, uint32 index, const void *elem_buf);
+
+/**
+ * Get element of vector
+ *
+ * @param vector the vector to get
+ * @param index the index of the element to get
+ * @param elem_buf the element buffer to store the element data,
+ * whose length must be no less than element size
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_get(Vector *vector, uint32 index, void *elem_buf);
+
+/**
+ * Insert element of vector
+ *
+ * @param vector the vector to insert
+ * @param index the index of the element to insert
+ * @param elem_buf the element buffer which stores the element data
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf);
+
+/**
+ * Append element to the end of vector
+ *
+ * @param vector the vector to append
+ * @param elem_buf the element buffer which stores the element data
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_append(Vector *vector, const void *elem_buf);
+
+/**
+ * Remove element from vector
+ *
+ * @param vector the vector to remove element
+ * @param index the index of the element to remove
+ * @param old_elem_buf if not NULL, copies the element data to the buffer
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf);
+
+/**
+ * Return the size of the vector
+ *
+ * @param vector the vector to get size
+ *
+ * @return return the size of the vector
+ */
+size_t
+bh_vector_size(const Vector *vector);
+
+/**
+ * Destroy the vector
+ *
+ * @param vector the vector to destroy
+ *
+ * @return true if success, false otherwise
+ */
+bool
+bh_vector_destroy(Vector *vector);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* endof _WASM_VECTOR_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.c
new file mode 100644
index 000000000..8fccf4c2f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "runtime_timer.h"
+
+#if 1
+#define PRINT(...) (void)0
+#else
+#define PRINT printf
+#endif
+
+typedef struct _app_timer {
+ struct _app_timer *next;
+ uint32 id;
+ uint32 interval;
+ uint64 expiry;
+ bool is_periodic;
+} app_timer_t;
+
+struct _timer_ctx {
+ app_timer_t *app_timers;
+ app_timer_t *idle_timers;
+ app_timer_t *free_timers;
+ uint32 max_timer_id;
+ int pre_allocated;
+ uint32 owner;
+
+ /* mutex and condition */
+ korp_cond cond;
+ korp_mutex mutex;
+
+ timer_callback_f timer_callback;
+ check_timer_expiry_f refresh_checker;
+};
+
+uint64
+bh_get_tick_ms()
+{
+ return os_time_get_boot_microsecond() / 1000;
+}
+
+uint32
+bh_get_elpased_ms(uint32 *last_system_clock)
+{
+ uint32 elpased_ms;
+ /* attention: the bh_get_tick_ms() return 64 bits integer, but
+ the bh_get_elpased_ms() is designed to use 32 bits clock count */
+ uint32 now = (uint32)bh_get_tick_ms();
+
+ /* system clock overrun */
+ if (now < *last_system_clock) {
+ PRINT("system clock overrun!\n");
+ elpased_ms = now + (UINT32_MAX - *last_system_clock) + 1;
+ }
+ else {
+ elpased_ms = now - *last_system_clock;
+ }
+
+ *last_system_clock = now;
+ return elpased_ms;
+}
+
+static app_timer_t *
+remove_timer_from(timer_ctx_t ctx, uint32 timer_id, bool active_list)
+{
+ app_timer_t **head, *prev, *t;
+
+ os_mutex_lock(&ctx->mutex);
+
+ if (active_list)
+ head = &ctx->app_timers;
+ else
+ head = &ctx->idle_timers;
+
+ t = *head;
+ prev = NULL;
+
+ while (t) {
+ if (t->id == timer_id) {
+ if (prev == NULL) {
+ *head = t->next;
+ PRINT("removed timer [%d] at head from list %d\n", t->id,
+ active_list);
+ }
+ else {
+ prev->next = t->next;
+ PRINT("removed timer [%d] after [%d] from list %d\n", t->id,
+ prev->id, active_list);
+ }
+ os_mutex_unlock(&ctx->mutex);
+
+ if (active_list && prev == NULL && ctx->refresh_checker)
+ ctx->refresh_checker(ctx);
+ return t;
+ }
+ else {
+ prev = t;
+ t = t->next;
+ }
+ }
+
+ os_mutex_unlock(&ctx->mutex);
+ return NULL;
+}
+
+static app_timer_t *
+remove_timer(timer_ctx_t ctx, uint32 timer_id, bool *active)
+{
+ app_timer_t *t = remove_timer_from(ctx, timer_id, true);
+
+ if (t) {
+ if (active)
+ *active = true;
+ return t;
+ }
+
+ if (active)
+ *active = false;
+ return remove_timer_from(ctx, timer_id, false);
+}
+
+static void
+reschedule_timer(timer_ctx_t ctx, app_timer_t *timer)
+{
+ app_timer_t *t;
+ app_timer_t *prev = NULL;
+
+ os_mutex_lock(&ctx->mutex);
+
+ t = ctx->app_timers;
+ timer->next = NULL;
+ timer->expiry = bh_get_tick_ms() + timer->interval;
+
+ while (t) {
+ if (timer->expiry < t->expiry) {
+ if (prev == NULL) {
+ timer->next = ctx->app_timers;
+ ctx->app_timers = timer;
+ PRINT("rescheduled timer [%d] at head\n", timer->id);
+ }
+ else {
+ timer->next = t;
+ prev->next = timer;
+ PRINT("rescheduled timer [%d] after [%d]\n", timer->id,
+ prev->id);
+ }
+
+ goto out;
+ }
+ else {
+ prev = t;
+ t = t->next;
+ }
+ }
+
+ if (prev) {
+ /* insert to the list end */
+ prev->next = timer;
+ PRINT("rescheduled timer [%d] at end, after [%d]\n", timer->id,
+ prev->id);
+ }
+ else {
+ /* insert at the begin */
+ bh_assert(ctx->app_timers == NULL);
+ ctx->app_timers = timer;
+ PRINT("rescheduled timer [%d] as first\n", timer->id);
+ }
+
+out:
+ os_mutex_unlock(&ctx->mutex);
+
+ /* ensure the refresh_checker() is called out of the lock */
+ if (prev == NULL && ctx->refresh_checker)
+ ctx->refresh_checker(ctx);
+}
+
+static void
+release_timer(timer_ctx_t ctx, app_timer_t *t)
+{
+ if (ctx->pre_allocated) {
+ os_mutex_lock(&ctx->mutex);
+ t->next = ctx->free_timers;
+ ctx->free_timers = t;
+ PRINT("recycle timer :%d\n", t->id);
+ os_mutex_unlock(&ctx->mutex);
+ }
+ else {
+ PRINT("destroy timer :%d\n", t->id);
+ BH_FREE(t);
+ }
+}
+
+void
+release_timer_list(app_timer_t **p_list)
+{
+ app_timer_t *t = *p_list;
+
+ while (t) {
+ app_timer_t *next = t->next;
+ PRINT("destroy timer list:%d\n", t->id);
+ BH_FREE(t);
+ t = next;
+ }
+
+ *p_list = NULL;
+}
+
+/*
+ * API exposed
+ */
+
+timer_ctx_t
+create_timer_ctx(timer_callback_f timer_handler,
+ check_timer_expiry_f expiery_checker, int prealloc_num,
+ unsigned int owner)
+{
+ timer_ctx_t ctx = (timer_ctx_t)BH_MALLOC(sizeof(struct _timer_ctx));
+
+ if (ctx == NULL)
+ return NULL;
+
+ memset(ctx, 0, sizeof(struct _timer_ctx));
+
+ ctx->timer_callback = timer_handler;
+ ctx->pre_allocated = prealloc_num;
+ ctx->refresh_checker = expiery_checker;
+ ctx->owner = owner;
+
+ while (prealloc_num > 0) {
+ app_timer_t *timer = (app_timer_t *)BH_MALLOC(sizeof(app_timer_t));
+
+ if (timer == NULL)
+ goto cleanup;
+
+ memset(timer, 0, sizeof(*timer));
+ timer->next = ctx->free_timers;
+ ctx->free_timers = timer;
+ prealloc_num--;
+ }
+
+ if (os_cond_init(&ctx->cond) != 0)
+ goto cleanup;
+
+ if (os_mutex_init(&ctx->mutex) != 0) {
+ os_cond_destroy(&ctx->cond);
+ goto cleanup;
+ }
+
+ PRINT("timer ctx created. pre-alloc: %d\n", ctx->pre_allocated);
+ return ctx;
+
+cleanup:
+ if (ctx) {
+ release_timer_list(&ctx->free_timers);
+ BH_FREE(ctx);
+ }
+ PRINT("timer ctx create failed\n");
+ return NULL;
+}
+
+void
+destroy_timer_ctx(timer_ctx_t ctx)
+{
+ while (ctx->free_timers) {
+ void *tmp = ctx->free_timers;
+ ctx->free_timers = ctx->free_timers->next;
+ BH_FREE(tmp);
+ }
+
+ cleanup_app_timers(ctx);
+
+ os_cond_destroy(&ctx->cond);
+ os_mutex_destroy(&ctx->mutex);
+ BH_FREE(ctx);
+}
+
+unsigned int
+timer_ctx_get_owner(timer_ctx_t ctx)
+{
+ return ctx->owner;
+}
+
+void
+add_idle_timer(timer_ctx_t ctx, app_timer_t *timer)
+{
+ os_mutex_lock(&ctx->mutex);
+ timer->next = ctx->idle_timers;
+ ctx->idle_timers = timer;
+ os_mutex_unlock(&ctx->mutex);
+}
+
+uint32
+sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, bool auto_start)
+{
+ app_timer_t *timer;
+
+ if (ctx->pre_allocated) {
+ if (ctx->free_timers == NULL) {
+ return (uint32)-1;
+ }
+ else {
+ timer = ctx->free_timers;
+ ctx->free_timers = timer->next;
+ }
+ }
+ else {
+ timer = (app_timer_t *)BH_MALLOC(sizeof(app_timer_t));
+ if (timer == NULL)
+ return (uint32)-1;
+ }
+
+ memset(timer, 0, sizeof(*timer));
+
+ ctx->max_timer_id++;
+ if (ctx->max_timer_id == (uint32)-1)
+ ctx->max_timer_id++;
+ timer->id = ctx->max_timer_id;
+ timer->interval = (uint32)interval;
+ timer->is_periodic = is_period;
+
+ if (auto_start)
+ reschedule_timer(ctx, timer);
+ else
+ add_idle_timer(ctx, timer);
+
+ return timer->id;
+}
+
+bool
+sys_timer_cancel(timer_ctx_t ctx, uint32 timer_id)
+{
+ bool from_active;
+ app_timer_t *t = remove_timer(ctx, timer_id, &from_active);
+
+ if (t == NULL)
+ return false;
+
+ add_idle_timer(ctx, t);
+
+ PRINT("sys_timer_stop called\n");
+ return from_active;
+}
+
+bool
+sys_timer_destroy(timer_ctx_t ctx, uint32 timer_id)
+{
+ bool from_active;
+ app_timer_t *t = remove_timer(ctx, timer_id, &from_active);
+
+ if (t == NULL)
+ return false;
+
+ release_timer(ctx, t);
+
+ PRINT("sys_timer_destroy called\n");
+ return true;
+}
+
+bool
+sys_timer_restart(timer_ctx_t ctx, uint32 timer_id, int interval)
+{
+ app_timer_t *t = remove_timer(ctx, timer_id, NULL);
+
+ if (t == NULL)
+ return false;
+
+ t->interval = (uint32)interval;
+
+ reschedule_timer(ctx, t);
+
+ PRINT("sys_timer_restart called\n");
+ return true;
+}
+
+/*
+ * API called by the timer manager from another thread or the kernel timer
+ * handler
+ */
+
+/**
+ * lookup the app queue by the module name
+ * post a timeout message to the app queue
+ */
+static void
+handle_expired_timers(timer_ctx_t ctx, app_timer_t *expired)
+{
+ while (expired) {
+ app_timer_t *t = expired;
+ ctx->timer_callback(t->id, ctx->owner);
+
+ /* get next expired timer first, since the following
+ operation may change expired->next */
+ expired = expired->next;
+ if (t->is_periodic) {
+ /* if it is repeating, then reschedule it; */
+ reschedule_timer(ctx, t);
+ }
+ else {
+ /* else move it to idle list */
+ add_idle_timer(ctx, t);
+ }
+ }
+}
+
+uint32
+get_expiry_ms(timer_ctx_t ctx)
+{
+ uint32 ms_to_next_expiry;
+ uint64 now = bh_get_tick_ms();
+
+ os_mutex_lock(&ctx->mutex);
+ if (ctx->app_timers == NULL)
+ ms_to_next_expiry = (uint32)-1;
+ else if (ctx->app_timers->expiry >= now)
+ ms_to_next_expiry = (uint32)(ctx->app_timers->expiry - now);
+ else
+ ms_to_next_expiry = 0;
+ os_mutex_unlock(&ctx->mutex);
+
+ return ms_to_next_expiry;
+}
+
+uint32
+check_app_timers(timer_ctx_t ctx)
+{
+ app_timer_t *t, *expired = NULL, *expired_end = NULL;
+ uint64 now = bh_get_tick_ms();
+
+ os_mutex_lock(&ctx->mutex);
+
+ t = ctx->app_timers;
+ while (t) {
+ if (now >= t->expiry) {
+ ctx->app_timers = t->next;
+
+ /* append t to the end of expired list */
+ t->next = NULL;
+ if (!expired_end) {
+ expired = expired_end = t;
+ }
+ else {
+ expired_end->next = t;
+ expired_end = t;
+ }
+
+ t = ctx->app_timers;
+ }
+ else {
+ break;
+ }
+ }
+ os_mutex_unlock(&ctx->mutex);
+
+ handle_expired_timers(ctx, expired);
+ return get_expiry_ms(ctx);
+}
+
+void
+cleanup_app_timers(timer_ctx_t ctx)
+{
+ os_mutex_lock(&ctx->mutex);
+
+ release_timer_list(&ctx->app_timers);
+ release_timer_list(&ctx->idle_timers);
+
+ os_mutex_unlock(&ctx->mutex);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.h
new file mode 100644
index 000000000..b8d90c5ff
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/runtime_timer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef LIB_BASE_RUNTIME_TIMER_H_
+#define LIB_BASE_RUNTIME_TIMER_H_
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint64
+bh_get_tick_ms(void);
+uint32
+bh_get_elpased_ms(uint32 *last_system_clock);
+
+struct _timer_ctx;
+typedef struct _timer_ctx *timer_ctx_t;
+typedef void (*timer_callback_f)(unsigned int id, unsigned int owner);
+typedef void (*check_timer_expiry_f)(timer_ctx_t ctx);
+
+timer_ctx_t
+create_timer_ctx(timer_callback_f timer_handler, check_timer_expiry_f,
+ int prealloc_num, unsigned int owner);
+void destroy_timer_ctx(timer_ctx_t);
+unsigned int
+timer_ctx_get_owner(timer_ctx_t ctx);
+
+uint32
+sys_create_timer(timer_ctx_t ctx, int interval, bool is_period,
+ bool auto_start);
+bool
+sys_timer_destroy(timer_ctx_t ctx, uint32 timer_id);
+bool
+sys_timer_cancel(timer_ctx_t ctx, uint32 timer_id);
+bool
+sys_timer_restart(timer_ctx_t ctx, uint32 timer_id, int interval);
+void
+cleanup_app_timers(timer_ctx_t ctx);
+uint32
+check_app_timers(timer_ctx_t ctx);
+uint32
+get_expiry_ms(timer_ctx_t ctx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LIB_BASE_RUNTIME_TIMER_H_ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/shared_utils.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/shared_utils.cmake
new file mode 100644
index 000000000..5b7d02dde
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/shared_utils.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (UTILS_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${UTILS_SHARED_DIR})
+
+file (GLOB 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/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/SConscript
new file mode 100644
index 000000000..f608645fe
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/SConscript
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import os
+
+cwd = GetCurrentDir()
+
+# src = Split('''
+# ''')
+
+
+def addSrcFiles(arr, path):
+ for f in os.listdir(path):
+ fpath = os.path.join(path, f);
+ if os.path.isfile(fpath):
+ ext = os.path.splitext(fpath)[-1]
+ if ext == '.c' or ext == '.cpp':
+ arr += [fpath]
+ #elif os.path.isdir(fpath):
+ # addSrcFiles(arr, fpath)
+
+src = Glob('*.c')
+src += Glob('*.cpp')
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_shared_utils_uncommon', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.c
new file mode 100644
index 000000000..19e23a7b5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 Ant Financial Services Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __GNUC__
+
+#include "bh_getopt.h"
+#include <stdio.h>
+#include <string.h>
+
+char *optarg = NULL;
+int optind = 1;
+
+int
+getopt(int argc, char *const argv[], const char *optstring)
+{
+ static int sp = 1;
+ int opt;
+ char *p;
+
+ if (sp == 1) {
+ if ((optind >= argc) || (argv[optind][0] != '-')
+ || (argv[optind][1] == 0)) {
+ return -1;
+ }
+ else if (!strcmp(argv[optind], "--")) {
+ optind++;
+ return -1;
+ }
+ }
+
+ opt = argv[optind][sp];
+ p = strchr(optstring, opt);
+ if (opt == ':' || p == NULL) {
+ printf("illegal option : '-%c'\n", opt);
+ if (argv[optind][++sp] == '\0') {
+ optind++;
+ sp = 1;
+ }
+ return ('?');
+ }
+ if (p[1] == ':') {
+ if (argv[optind][sp + 1] != '\0')
+ optarg = &argv[optind++][sp + 1];
+ else if (++optind >= argc) {
+ printf("option '-%c' requires an argument :\n", opt);
+ sp = 1;
+ return ('?');
+ }
+ else {
+ optarg = argv[optind++];
+ }
+ sp = 1;
+ }
+ else {
+ if (argv[optind][++sp] == '\0') {
+ sp = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+ return (opt);
+}
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.h
new file mode 100644
index 000000000..efd3ab403
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_getopt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 Ant Financial Services Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifdef __GNUC__
+#include <getopt.h>
+#endif
+#ifndef __GNUC__
+#ifndef GETOPT_H__
+#define GETOPT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *optarg;
+extern int optind;
+
+int
+getopt(int argc, char *const argv[], const char *optstring);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of GETOPT_H__ */
+#endif /* end of __GNUC__ */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.c
new file mode 100644
index 000000000..5ddf1b601
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.c
@@ -0,0 +1,117 @@
+#include "bh_read_file.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined(_WIN32) || defined(_WIN32_)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#if defined(_WIN32) || defined(_WIN32_)
+
+#if defined(__MINGW32__) && !defined(_SH_DENYNO)
+#define _SH_DENYNO 0x40
+#endif
+
+char *
+bh_read_file_to_buffer(const char *filename, uint32 *ret_size)
+{
+ char *buffer;
+ int file;
+ uint32 file_size, buf_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 (_sopen_s(&file, filename, _O_RDONLY | _O_BINARY, _SH_DENYNO, 0)) {
+ 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;
+
+ /* At lease alloc 1 byte to avoid malloc failed */
+ buf_size = file_size > 0 ? file_size : 1;
+
+ if (!(buffer = (char *)BH_MALLOC(buf_size))) {
+ printf("Read file to buffer failed: alloc memory failed.\n");
+ _close(file);
+ return NULL;
+ }
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ printf("Read file, total size: %u\n", file_size);
+#endif
+
+ read_size = _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;
+}
+#else /* else of defined(_WIN32) || defined(_WIN32_) */
+char *
+bh_read_file_to_buffer(const char *filename, uint32 *ret_size)
+{
+ char *buffer;
+ int file;
+ uint32 file_size, buf_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;
+
+ /* At lease alloc 1 byte to avoid malloc failed */
+ buf_size = file_size > 0 ? file_size : 1;
+
+ if (!(buffer = BH_MALLOC(buf_size))) {
+ printf("Read file to buffer failed: alloc memory failed.\n");
+ close(file);
+ return NULL;
+ }
+#if WASM_ENABLE_MEMORY_TRACING != 0
+ printf("Read file, total size: %u\n", file_size);
+#endif
+
+ 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;
+}
+#endif /* end of defined(_WIN32) || defined(_WIN32_) */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.h
new file mode 100644
index 000000000..bbebf847f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/bh_read_file.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _BH_FILE_H
+#define _BH_FILE_H
+
+#include "bh_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *
+bh_read_file_to_buffer(const char *filename, uint32 *ret_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _BH_FILE_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/shared_uncommon.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/shared_uncommon.cmake
new file mode 100644
index 000000000..0a15b87b8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/utils/uncommon/shared_uncommon.cmake
@@ -0,0 +1,11 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (UNCOMMON_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${UNCOMMON_SHARED_DIR})
+
+file (GLOB_RECURSE source_all ${UNCOMMON_SHARED_DIR}/*.c)
+
+set (UNCOMMON_SHARED_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/version.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/version.h
new file mode 100644
index 000000000..de24b30bc
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/version.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WAMR_VERSION_H_
+#define _WAMR_VERSION_H_
+#define WAMR_VERSION_MAJOR 1
+#define WAMR_VERSION_MINOR 2
+#define WAMR_VERSION_PATCH 2
+#endif